Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
e6a6a9a4
Commit
e6a6a9a4
authored
Feb 13, 2015
by
Travis Hance
Committed by
Travis Hance
Feb 21, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
made an enum for ScopeInfo
parent
6b935b9b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
169 additions
and
17 deletions
+169
-17
src/analysis/scoping_analysis.cpp
src/analysis/scoping_analysis.cpp
+25
-7
src/analysis/scoping_analysis.h
src/analysis/scoping_analysis.h
+30
-0
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+6
-5
src/codegen/irgen/hooks.cpp
src/codegen/irgen/hooks.cpp
+14
-0
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+5
-5
test/tests/eval_test.py
test/tests/eval_test.py
+89
-0
No files found.
src/analysis/scoping_analysis.cpp
View file @
e6a6a9a4
...
@@ -104,6 +104,9 @@ public:
...
@@ -104,6 +104,9 @@ public:
}
}
bool
refersToClosure
(
InternedString
name
)
override
{
return
false
;
}
bool
refersToClosure
(
InternedString
name
)
override
{
return
false
;
}
bool
saveInClosure
(
InternedString
name
)
override
{
return
false
;
}
bool
saveInClosure
(
InternedString
name
)
override
{
return
false
;
}
VarScopeType
getScopeTypeOfName
(
InternedString
name
)
override
{
return
refersToGlobal
(
name
)
?
VarScopeType
::
GLOBAL
:
VarScopeType
::
FAST
;
}
InternedString
mangleName
(
InternedString
id
)
override
{
return
id
;
}
InternedString
mangleName
(
InternedString
id
)
override
{
return
id
;
}
InternedString
internString
(
llvm
::
StringRef
s
)
override
{
abort
();
}
InternedString
internString
(
llvm
::
StringRef
s
)
override
{
abort
();
}
...
@@ -174,10 +177,11 @@ private:
...
@@ -174,10 +177,11 @@ private:
ScopeInfo
*
parent
;
ScopeInfo
*
parent
;
ScopingAnalysis
::
ScopeNameUsage
*
usage
;
ScopingAnalysis
::
ScopeNameUsage
*
usage
;
AST
*
ast
;
AST
*
ast
;
bool
usesNameLookup
;
public:
public:
ScopeInfoBase
(
ScopeInfo
*
parent
,
ScopingAnalysis
::
ScopeNameUsage
*
usage
,
AST
*
ast
)
ScopeInfoBase
(
ScopeInfo
*
parent
,
ScopingAnalysis
::
ScopeNameUsage
*
usage
,
AST
*
ast
,
bool
usesNameLookup
)
:
parent
(
parent
),
usage
(
usage
),
ast
(
ast
)
{
:
parent
(
parent
),
usage
(
usage
),
ast
(
ast
)
,
usesNameLookup
(
usesNameLookup
)
{
assert
(
parent
);
assert
(
parent
);
assert
(
usage
);
assert
(
usage
);
assert
(
ast
);
assert
(
ast
);
...
@@ -219,6 +223,18 @@ public:
...
@@ -219,6 +223,18 @@ public:
return
usage
->
referenced_from_nested
.
count
(
name
)
!=
0
;
return
usage
->
referenced_from_nested
.
count
(
name
)
!=
0
;
}
}
VarScopeType
getScopeTypeOfName
(
InternedString
name
)
override
{
if
(
refersToGlobal
(
name
))
return
VarScopeType
::
GLOBAL
;
if
(
refersToClosure
(
name
))
return
VarScopeType
::
DEREF
;
if
(
usesNameLookup
)
return
VarScopeType
::
NAME
;
if
(
saveInClosure
(
name
))
return
VarScopeType
::
CLOSURE
;
return
VarScopeType
::
FAST
;
}
InternedString
mangleName
(
const
InternedString
id
)
override
{
InternedString
mangleName
(
const
InternedString
id
)
override
{
return
pyston
::
mangleName
(
id
,
usage
->
private_name
,
usage
->
scoping
->
getInternedStrings
());
return
pyston
::
mangleName
(
id
,
usage
->
private_name
,
usage
->
scoping
->
getInternedStrings
());
}
}
...
@@ -530,15 +546,17 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
...
@@ -530,15 +546,17 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
ScopeInfo
*
parent_info
=
this
->
scopes
[(
usage
->
parent
==
NULL
)
?
this
->
parent_module
:
usage
->
parent
->
node
];
ScopeInfo
*
parent_info
=
this
->
scopes
[(
usage
->
parent
==
NULL
)
?
this
->
parent_module
:
usage
->
parent
->
node
];
switch
(
node
->
type
)
{
switch
(
node
->
type
)
{
case
AST_TYPE
:
:
ClassDef
:
case
AST_TYPE
:
:
ClassDef
:
{
case
AST_TYPE
:
:
FunctionDef
:
ScopeInfoBase
*
scopeInfo
case
AST_TYPE
:
:
Lambda
:
{
=
new
ScopeInfoBase
(
parent_info
,
usage
,
usage
->
node
,
true
/* usesNameLookup */
);
ScopeInfoBase
*
scopeInfo
=
new
ScopeInfoBase
(
parent_info
,
usage
,
usage
->
node
);
this
->
scopes
[
node
]
=
scopeInfo
;
this
->
scopes
[
node
]
=
scopeInfo
;
break
;
break
;
}
}
case
AST_TYPE
:
:
FunctionDef
:
case
AST_TYPE
:
:
Lambda
:
case
AST_TYPE
:
:
GeneratorExp
:
{
case
AST_TYPE
:
:
GeneratorExp
:
{
ScopeInfoBase
*
scopeInfo
=
new
ScopeInfoBase
(
parent_info
,
usage
,
usage
->
node
);
ScopeInfoBase
*
scopeInfo
=
new
ScopeInfoBase
(
parent_info
,
usage
,
usage
->
node
,
false
/* usesNameLookup */
);
this
->
scopes
[
node
]
=
scopeInfo
;
this
->
scopes
[
node
]
=
scopeInfo
;
break
;
break
;
}
}
...
...
src/analysis/scoping_analysis.h
View file @
e6a6a9a4
...
@@ -33,9 +33,39 @@ public:
...
@@ -33,9 +33,39 @@ public:
virtual
bool
takesClosure
()
=
0
;
virtual
bool
takesClosure
()
=
0
;
virtual
bool
passesThroughClosure
()
=
0
;
virtual
bool
passesThroughClosure
()
=
0
;
// Various ways a variable name can be resolved.
// These all correspond to STORE_* or LOAD_* bytecodes in CPython.
//
// By way of example:
//
// def f():
// print a # GLOBAL
//
// b = 0
// print b # FAST
//
// c = 0 # CLOSURE
// def g():
// print c # DEREF
//
// class C(object):
// print d # NAME
//
// def g():
// exec "sdfasdfds()"
// # existence of 'exec' statement forces this to NAME:
// print e # NAME
//
// # protip: you can figure this stuff out by doing something like this in CPython:
// import dis
// print dis.dis(g)
enum
class
VarScopeType
{
FAST
,
GLOBAL
,
CLOSURE
,
DEREF
,
NAME
};
virtual
bool
refersToGlobal
(
InternedString
name
)
=
0
;
virtual
bool
refersToGlobal
(
InternedString
name
)
=
0
;
virtual
bool
refersToClosure
(
InternedString
name
)
=
0
;
virtual
bool
refersToClosure
(
InternedString
name
)
=
0
;
virtual
bool
saveInClosure
(
InternedString
name
)
=
0
;
virtual
bool
saveInClosure
(
InternedString
name
)
=
0
;
virtual
VarScopeType
getScopeTypeOfName
(
InternedString
name
)
=
0
;
virtual
InternedString
mangleName
(
InternedString
id
)
=
0
;
virtual
InternedString
mangleName
(
InternedString
id
)
=
0
;
virtual
InternedString
internString
(
llvm
::
StringRef
)
=
0
;
virtual
InternedString
internString
(
llvm
::
StringRef
)
=
0
;
...
...
src/codegen/ast_interpreter.cpp
View file @
e6a6a9a4
...
@@ -999,14 +999,15 @@ Value ASTInterpreter::visit_str(AST_Str* node) {
...
@@ -999,14 +999,15 @@ Value ASTInterpreter::visit_str(AST_Str* node) {
Value
ASTInterpreter
::
visit_name
(
AST_Name
*
node
)
{
Value
ASTInterpreter
::
visit_name
(
AST_Name
*
node
)
{
switch
(
node
->
lookup_type
)
{
switch
(
node
->
lookup_type
)
{
case
AST_Name
:
:
UNKNOWN
:
{
case
AST_Name
:
:
UNKNOWN
:
{
if
(
scope_info
->
refersToGlobal
(
node
->
id
))
{
ScopeInfo
::
VarScopeType
vst
=
scope_info
->
getScopeTypeOfName
(
node
->
id
);
if
(
vst
==
ScopeInfo
::
VarScopeType
::
GLOBAL
)
{
node
->
lookup_type
=
AST_Name
::
GLOBAL
;
node
->
lookup_type
=
AST_Name
::
GLOBAL
;
return
getGlobal
(
source_info
->
parent_module
,
&
node
->
id
.
str
());
return
getGlobal
(
source_info
->
parent_module
,
&
node
->
id
.
str
());
}
else
if
(
scope_info
->
refersToClosure
(
node
->
id
)
)
{
}
else
if
(
vst
==
ScopeInfo
::
VarScopeType
::
DEREF
)
{
node
->
lookup_type
=
AST_Name
::
CLOSURE
;
node
->
lookup_type
=
AST_Name
::
CLOSURE
;
return
getattr
(
passed_closure
,
node
->
id
.
c_str
());
return
getattr
(
passed_closure
,
node
->
id
.
c_str
());
}
else
{
}
else
{
bool
is_old_local
=
(
source_info
->
ast
->
type
==
AST_TYPE
::
ClassDef
);
bool
is_old_local
=
(
vst
==
ScopeInfo
::
VarScopeType
::
NAME
);
node
->
lookup_type
=
is_old_local
?
AST_Name
::
LOCAL
:
AST_Name
::
FAST_LOCAL
;
node
->
lookup_type
=
is_old_local
?
AST_Name
::
LOCAL
:
AST_Name
::
FAST_LOCAL
;
SymMap
::
iterator
it
=
sym_table
.
find
(
node
->
id
);
SymMap
::
iterator
it
=
sym_table
.
find
(
node
->
id
);
...
@@ -1015,8 +1016,8 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
...
@@ -1015,8 +1016,8 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
return
value
;
return
value
;
}
}
// classdefs have different scoping rules than functions:
// classdefs
(and some other cases like eval)
have different scoping rules than functions:
if
(
source_info
->
ast
->
type
==
AST_TYPE
::
ClassDef
)
if
(
is_old_local
)
return
getGlobal
(
source_info
->
parent_module
,
&
node
->
id
.
str
());
return
getGlobal
(
source_info
->
parent_module
,
&
node
->
id
.
str
());
assertNameDefined
(
0
,
node
->
id
.
c_str
(),
UnboundLocalError
,
true
);
assertNameDefined
(
0
,
node
->
id
.
c_str
(),
UnboundLocalError
,
true
);
...
...
src/codegen/irgen/hooks.cpp
View file @
e6a6a9a4
...
@@ -300,6 +300,20 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
...
@@ -300,6 +300,20 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
((
void
(
*
)())
cf
->
code
)();
((
void
(
*
)())
cf
->
code
)();
}
}
/*
void compileAndRunExpression(AST_expr* expr, BoxedModule* bm) {
CompiledFunction* cf;
AST_stmt* stmt = new AST_Expr(expr);
{ // scope for limiting the locked region:
LOCK_REGION(codegen_rwlock.asWrite());
Timer _t("for compileModule()");
ScopingAnalysis* scoping = runScopingAnalysis(
}
*/
// If a function version keeps failing its speculations, kill it (remove it
// If a function version keeps failing its speculations, kill it (remove it
// from the list of valid function versions). The next time we go to call
// from the list of valid function versions). The next time we go to call
// the function, we will have to pick a different version, potentially recompiling.
// the function, we will have to pick a different version, potentially recompiling.
...
...
src/codegen/irgen/irgenerator.cpp
View file @
e6a6a9a4
...
@@ -867,10 +867,11 @@ private:
...
@@ -867,10 +867,11 @@ private:
bool
is_kill
=
irstate
->
getSourceInfo
()
->
liveness
->
isKill
(
node
,
myblock
);
bool
is_kill
=
irstate
->
getSourceInfo
()
->
liveness
->
isKill
(
node
,
myblock
);
assert
(
!
is_kill
||
node
->
id
.
str
()[
0
]
==
'#'
);
assert
(
!
is_kill
||
node
->
id
.
str
()[
0
]
==
'#'
);
if
(
scope_info
->
refersToGlobal
(
node
->
id
))
{
ScopeInfo
::
VarScopeType
vst
=
scope_info
->
getScopeTypeOfName
(
node
->
id
);
if
(
vst
==
ScopeInfo
::
VarScopeType
::
GLOBAL
)
{
assert
(
!
is_kill
);
assert
(
!
is_kill
);
return
_getGlobal
(
node
,
unw_info
);
return
_getGlobal
(
node
,
unw_info
);
}
else
if
(
scope_info
->
refersToClosure
(
node
->
id
)
)
{
}
else
if
(
vst
==
ScopeInfo
::
VarScopeType
::
DEREF
)
{
assert
(
!
is_kill
);
assert
(
!
is_kill
);
assert
(
scope_info
->
takesClosure
());
assert
(
scope_info
->
takesClosure
());
...
@@ -881,7 +882,7 @@ private:
...
@@ -881,7 +882,7 @@ private:
}
else
{
}
else
{
if
(
symbol_table
.
find
(
node
->
id
)
==
symbol_table
.
end
())
{
if
(
symbol_table
.
find
(
node
->
id
)
==
symbol_table
.
end
())
{
// classdefs have different scoping rules than functions:
// classdefs have different scoping rules than functions:
if
(
irstate
->
getSourceInfo
()
->
ast
->
type
==
AST_TYPE
::
ClassDef
)
{
if
(
vst
==
ScopeInfo
::
VarScopeType
::
NAME
)
{
return
_getGlobal
(
node
,
unw_info
);
return
_getGlobal
(
node
,
unw_info
);
}
}
...
@@ -900,8 +901,7 @@ private:
...
@@ -900,8 +901,7 @@ private:
=
static_cast
<
ConcreteCompilerVariable
*>
(
_getFake
(
defined_name
,
true
));
=
static_cast
<
ConcreteCompilerVariable
*>
(
_getFake
(
defined_name
,
true
));
if
(
is_defined_var
)
{
if
(
is_defined_var
)
{
// classdefs have different scoping rules than functions:
if
(
vst
==
ScopeInfo
::
VarScopeType
::
NAME
)
{
if
(
irstate
->
getSourceInfo
()
->
ast
->
type
==
AST_TYPE
::
ClassDef
)
{
llvm
::
Value
*
v
=
handlePotentiallyUndefined
(
llvm
::
Value
*
v
=
handlePotentiallyUndefined
(
is_defined_var
,
g
.
llvm_value_type_ptr
,
curblock
,
emitter
,
false
,
is_defined_var
,
g
.
llvm_value_type_ptr
,
curblock
,
emitter
,
false
,
[
=
](
IREmitter
&
emitter
)
{
[
=
](
IREmitter
&
emitter
)
{
...
...
test/tests/eval_
closures
.py
→
test/tests/eval_
test
.py
View file @
e6a6a9a4
# expected: fail
# expected: fail
# - eval not implemented
# - eval not implemented
# - closures not implemented
# - closures not implemented
print
eval
(
"3 + 4"
)
a
=
5
print
eval
(
"a"
)
print
eval
(
"[b for b in range(5)]"
)
print
b
c
=
2
print
eval
(
"[c for c in range(5)]"
)
print
c
try
:
print
eval
(
"int('abc')"
)
except
ValueError
:
print
'got ValueError'
d
=
19
e
=
20
i
=
21
def
func
():
print
eval
(
"d"
)
e
=
20
print
eval
(
"e"
)
eval
(
"[f for f in range(5)]"
)
eval
(
"[g for g in range(5)]"
)
try
:
g
except
NameError
:
print
'g not found'
h
=
2
eval
(
"[h for h in range(5)]"
)
print
h
eval
(
"[i for i in range(5)]"
)
j
=
24
def
inner
():
return
j
print
eval
(
"inner()"
)
func
()
print
i
print
eval
(
"(lambda k : k+2)(3)"
)
l
=
100
print
eval
(
"(lambda k : l+2)(3)"
)
print
eval
(
"(lambda k : [m for m in range(5)])(3)"
)
try
:
print
m
except
NameError
:
print
'm not found'
n
=
200
print
eval
(
"(lambda k : [n for n in range(5)])(3)"
)
print
n
print
eval
(
"eval('3 + 2342')"
)
x
=
2
x
=
2
def
wrap
():
def
wrap
():
x
=
1
x
=
1
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment