Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
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
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cython
Commits
8e7a120b
Commit
8e7a120b
authored
Dec 29, 2012
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
d3b253b8
b80966c6
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
78 additions
and
36 deletions
+78
-36
Cython/Compiler/FlowControl.py
Cython/Compiler/FlowControl.py
+7
-3
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+13
-5
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+32
-21
Cython/Compiler/TypeInference.py
Cython/Compiler/TypeInference.py
+3
-6
tests/run/closure_inlining.pyx
tests/run/closure_inlining.pyx
+22
-0
tests/run/cross_closure_type_inference.pyx
tests/run/cross_closure_type_inference.pyx
+1
-1
No files found.
Cython/Compiler/FlowControl.py
View file @
8e7a120b
...
@@ -161,15 +161,15 @@ class ControlFlow(object):
...
@@ -161,15 +161,15 @@ class ControlFlow(object):
self
.
block
.
positions
.
add
(
node
.
pos
[:
2
])
self
.
block
.
positions
.
add
(
node
.
pos
[:
2
])
def
mark_assignment
(
self
,
lhs
,
rhs
,
entry
):
def
mark_assignment
(
self
,
lhs
,
rhs
,
entry
):
if
self
.
block
:
entry
=
entry
.
defining_entry
if
not
self
.
is_tracked
(
entry
):
if
self
.
block
and
self
.
is_tracked
(
entry
):
return
assignment
=
NameAssignment
(
lhs
,
rhs
,
entry
)
assignment
=
NameAssignment
(
lhs
,
rhs
,
entry
)
self
.
block
.
stats
.
append
(
assignment
)
self
.
block
.
stats
.
append
(
assignment
)
self
.
block
.
gen
[
entry
]
=
assignment
self
.
block
.
gen
[
entry
]
=
assignment
self
.
entries
.
add
(
entry
)
self
.
entries
.
add
(
entry
)
def
mark_argument
(
self
,
lhs
,
rhs
,
entry
):
def
mark_argument
(
self
,
lhs
,
rhs
,
entry
):
entry
=
entry
.
defining_entry
if
self
.
block
and
self
.
is_tracked
(
entry
):
if
self
.
block
and
self
.
is_tracked
(
entry
):
assignment
=
Argument
(
lhs
,
rhs
,
entry
)
assignment
=
Argument
(
lhs
,
rhs
,
entry
)
self
.
block
.
stats
.
append
(
assignment
)
self
.
block
.
stats
.
append
(
assignment
)
...
@@ -177,6 +177,7 @@ class ControlFlow(object):
...
@@ -177,6 +177,7 @@ class ControlFlow(object):
self
.
entries
.
add
(
entry
)
self
.
entries
.
add
(
entry
)
def
mark_deletion
(
self
,
node
,
entry
):
def
mark_deletion
(
self
,
node
,
entry
):
entry
=
entry
.
defining_entry
if
self
.
block
and
self
.
is_tracked
(
entry
):
if
self
.
block
and
self
.
is_tracked
(
entry
):
assignment
=
NameDeletion
(
node
,
entry
)
assignment
=
NameDeletion
(
node
,
entry
)
self
.
block
.
stats
.
append
(
assignment
)
self
.
block
.
stats
.
append
(
assignment
)
...
@@ -184,6 +185,7 @@ class ControlFlow(object):
...
@@ -184,6 +185,7 @@ class ControlFlow(object):
self
.
entries
.
add
(
entry
)
self
.
entries
.
add
(
entry
)
def
mark_reference
(
self
,
node
,
entry
):
def
mark_reference
(
self
,
node
,
entry
):
entry
=
entry
.
defining_entry
if
self
.
block
and
self
.
is_tracked
(
entry
):
if
self
.
block
and
self
.
is_tracked
(
entry
):
self
.
block
.
stats
.
append
(
NameReference
(
node
,
entry
))
self
.
block
.
stats
.
append
(
NameReference
(
node
,
entry
))
# Local variable is definitely bound after this reference
# Local variable is definitely bound after this reference
...
@@ -534,6 +536,8 @@ def check_definitions(flow, compiler_directives):
...
@@ -534,6 +536,8 @@ def check_definitions(flow, compiler_directives):
node
.
cf_is_null
=
True
node
.
cf_is_null
=
True
if
node
.
allow_null
or
entry
.
from_closure
or
entry
.
is_pyclass_attr
:
if
node
.
allow_null
or
entry
.
from_closure
or
entry
.
is_pyclass_attr
:
pass
# Can be uninitialized here
pass
# Can be uninitialized here
elif
entry
.
in_closure
:
pass
# not smart enough to get this right
elif
node
.
cf_is_null
:
elif
node
.
cf_is_null
:
if
(
entry
.
type
.
is_pyobject
or
entry
.
type
.
is_unspecified
or
if
(
entry
.
type
.
is_pyobject
or
entry
.
type
.
is_unspecified
or
entry
.
error_on_uninitialized
):
entry
.
error_on_uninitialized
):
...
...
Cython/Compiler/Optimize.py
View file @
8e7a120b
...
@@ -1657,9 +1657,20 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
...
@@ -1657,9 +1657,20 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
return
node
return
node
return
kwargs
return
kwargs
class
InlineDefNodeCalls
(
Visitor
.
Cython
Transform
):
class
InlineDefNodeCalls
(
Visitor
.
Env
Transform
):
visit_Node
=
Visitor
.
VisitorTransform
.
recurse_to_children
visit_Node
=
Visitor
.
VisitorTransform
.
recurse_to_children
def
get_constant_value_node
(
self
,
name_node
):
if
not
name_node
.
cf_state
or
not
name_node
.
cf_state
.
is_single
:
# no single assignment in the current scope
return
None
entry
=
self
.
current_env
().
lookup
(
name_node
.
name
)
if
not
entry
or
(
not
entry
.
cf_assignments
or
len
(
entry
.
cf_assignments
)
!=
1
):
# not just a single assignment in all closures
return
None
return
name_node
.
cf_state
.
one
().
rhs
def
visit_SimpleCallNode
(
self
,
node
):
def
visit_SimpleCallNode
(
self
,
node
):
self
.
visitchildren
(
node
)
self
.
visitchildren
(
node
)
if
not
self
.
current_directives
.
get
(
'optimize.inline_defnode_calls'
):
if
not
self
.
current_directives
.
get
(
'optimize.inline_defnode_calls'
):
...
@@ -1667,10 +1678,7 @@ class InlineDefNodeCalls(Visitor.CythonTransform):
...
@@ -1667,10 +1678,7 @@ class InlineDefNodeCalls(Visitor.CythonTransform):
function_name
=
node
.
function
function_name
=
node
.
function
if
not
function_name
.
is_name
:
if
not
function_name
.
is_name
:
return
node
return
node
if
(
function_name
.
cf_state
is
None
# global scope
function
=
self
.
get_constant_value_node
(
function_name
)
or
not
function_name
.
cf_state
.
is_single
):
return
node
function
=
function_name
.
cf_state
.
one
().
rhs
if
not
isinstance
(
function
,
ExprNodes
.
PyCFunctionNode
):
if
not
isinstance
(
function
,
ExprNodes
.
PyCFunctionNode
):
return
node
return
node
inlined
=
ExprNodes
.
InlinedDefNodeCallNode
(
inlined
=
ExprNodes
.
InlinedDefNodeCallNode
(
...
...
Cython/Compiler/Symtab.py
View file @
8e7a120b
...
@@ -198,9 +198,10 @@ class Entry(object):
...
@@ -198,9 +198,10 @@ class Entry(object):
self
.
cf_assignments
=
[]
self
.
cf_assignments
=
[]
self
.
cf_references
=
[]
self
.
cf_references
=
[]
self
.
inner_entries
=
[]
self
.
inner_entries
=
[]
self
.
defining_entry
=
self
def
__repr__
(
self
):
def
__repr__
(
self
):
return
"
Entry(name=%s, type=%s)"
%
(
self
.
name
,
self
.
type
)
return
"
%s(name=%s, type=%s)"
%
(
type
(
self
).
__name__
,
self
.
name
,
self
.
type
)
def
redeclared
(
self
,
pos
):
def
redeclared
(
self
,
pos
):
error
(
pos
,
"'%s' does not match previous declaration"
%
self
.
name
)
error
(
pos
,
"'%s' does not match previous declaration"
%
self
.
name
)
...
@@ -210,20 +211,36 @@ class Entry(object):
...
@@ -210,20 +211,36 @@ class Entry(object):
return
[
self
]
+
self
.
overloaded_alternatives
return
[
self
]
+
self
.
overloaded_alternatives
def
all_entries
(
self
):
def
all_entries
(
self
):
return
[
self
]
+
self
.
inner_entries
class
InnerEntry
(
Entry
):
"""
"""
Returns all entries for this entry, including the equivalent ones
An entry in a closure scope that represents the real outer Entry.
in other closures.
"""
"""
if
self
.
from_closure
:
from_closure
=
True
return
self
.
outer_entry
.
all_entries
()
def
__init__
(
self
,
outer_entry
,
scope
):
entries
=
[]
Entry
.
__init__
(
self
,
outer_entry
.
name
,
def
collect_inner_entries
(
entry
):
outer_entry
.
cname
,
entries
.
append
(
entry
)
outer_entry
.
type
,
for
e
in
entry
.
inner_entries
:
outer_entry
.
pos
)
collect_inner_entries
(
e
)
self
.
outer_entry
=
outer_entry
collect_inner_entries
(
self
)
self
.
scope
=
scope
return
entries
# share state with (outermost) defining entry
outermost_entry
=
outer_entry
while
outermost_entry
.
outer_entry
:
outermost_entry
=
outermost_entry
.
outer_entry
self
.
defining_entry
=
outermost_entry
self
.
inner_entries
=
outermost_entry
.
inner_entries
self
.
cf_assignments
=
outermost_entry
.
cf_assignments
self
.
cf_references
=
outermost_entry
.
cf_references
self
.
overloaded_alternatives
=
outermost_entry
.
overloaded_alternatives
self
.
inner_entries
.
append
(
self
)
def
__getattr__
(
self
,
name
):
return
getattr
(
self
.
defining_entry
,
name
)
class
Scope
(
object
):
class
Scope
(
object
):
...
@@ -1534,15 +1551,9 @@ class LocalScope(Scope):
...
@@ -1534,15 +1551,9 @@ class LocalScope(Scope):
# The actual c fragment for the different scopes differs
# The actual c fragment for the different scopes differs
# on the outside and inside, so we make a new entry
# on the outside and inside, so we make a new entry
entry
.
in_closure
=
True
entry
.
in_closure
=
True
# Would it be better to declare_var here?
inner_entry
=
InnerEntry
(
entry
,
self
)
inner_entry
=
Entry
(
entry
.
name
,
entry
.
cname
,
entry
.
type
,
entry
.
pos
)
inner_entry
.
scope
=
self
inner_entry
.
is_variable
=
True
inner_entry
.
is_variable
=
True
inner_entry
.
outer_entry
=
entry
inner_entry
.
from_closure
=
True
inner_entry
.
is_declared_generic
=
entry
.
is_declared_generic
self
.
entries
[
name
]
=
inner_entry
self
.
entries
[
name
]
=
inner_entry
entry
.
inner_entries
.
append
(
inner_entry
)
return
inner_entry
return
inner_entry
return
entry
return
entry
...
...
Cython/Compiler/TypeInference.py
View file @
8e7a120b
...
@@ -360,11 +360,9 @@ class SimpleAssignmentTypeInferer(object):
...
@@ -360,11 +360,9 @@ class SimpleAssignmentTypeInferer(object):
ready_to_infer
=
[]
ready_to_infer
=
[]
for
name
,
entry
in
scope
.
entries
.
items
():
for
name
,
entry
in
scope
.
entries
.
items
():
if
entry
.
type
is
unspecified_type
:
if
entry
.
type
is
unspecified_type
:
entries
=
entry
.
all_entries
()
all
=
set
()
all
=
set
()
for
e
in
entries
:
for
assmt
in
entry
.
cf_assignments
:
for
assmt
in
e
.
cf_assignments
:
all
.
update
(
assmt
.
type_dependencies
(
entry
.
scope
))
all
.
update
(
assmt
.
type_dependencies
(
e
.
scope
))
if
all
:
if
all
:
dependancies_by_entry
[
entry
]
=
all
dependancies_by_entry
[
entry
]
=
all
for
dep
in
all
:
for
dep
in
all
:
...
@@ -390,8 +388,7 @@ class SimpleAssignmentTypeInferer(object):
...
@@ -390,8 +388,7 @@ class SimpleAssignmentTypeInferer(object):
entry
=
ready_to_infer
.
pop
()
entry
=
ready_to_infer
.
pop
()
types
=
[
types
=
[
assmt
.
rhs
.
infer_type
(
scope
)
assmt
.
rhs
.
infer_type
(
scope
)
for
e
in
entry
.
all_entries
()
for
assmt
in
entry
.
cf_assignments
for
assmt
in
e
.
cf_assignments
]
]
if
types
and
Utils
.
all
(
types
):
if
types
and
Utils
.
all
(
types
):
entry_type
=
spanning_type
(
types
,
entry
.
might_overflow
,
entry
.
pos
)
entry_type
=
spanning_type
(
types
,
entry
.
might_overflow
,
entry
.
pos
)
...
...
tests/run/closure_inlining.pyx
View file @
8e7a120b
...
@@ -106,3 +106,25 @@ def test_sideeffect_call_order():
...
@@ -106,3 +106,25 @@ def test_sideeffect_call_order():
pass
pass
call
(
1
,
sideeffect
(
2
),
3
,
sideeffect
(
4
),
sideeffect
(
5
))
call
(
1
,
sideeffect
(
2
),
3
,
sideeffect
(
4
),
sideeffect
(
5
))
return
L
return
L
def
test_redef
(
redefine
):
"""
>>> test_redef(False)
1
>>> test_redef(True)
2
"""
def
inner
():
return
1
def
inner2
():
return
2
def
redef
():
nonlocal
inner
inner
=
inner2
if
redefine
:
redef
()
assert
inner
==
inner2
else
:
assert
inner
!=
inner2
return
inner
()
tests/run/cross_closure_type_inference.pyx
View file @
8e7a120b
...
@@ -14,7 +14,7 @@ def test_outer_inner_double():
...
@@ -14,7 +14,7 @@ def test_outer_inner_double():
nonlocal
x
nonlocal
x
x
=
2.0
x
=
2.0
inner
()
inner
()
assert
x
==
2.0
assert
x
==
2.0
,
str
(
x
)
return
cython
.
typeof
(
x
)
return
cython
.
typeof
(
x
)
...
...
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