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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
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
Hide 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):
self
.
block
.
positions
.
add
(
node
.
pos
[:
2
])
def
mark_assignment
(
self
,
lhs
,
rhs
,
entry
):
if
self
.
block
:
if
not
self
.
is_tracked
(
entry
):
return
entry
=
entry
.
defining_entry
if
self
.
block
and
self
.
is_tracked
(
entry
):
assignment
=
NameAssignment
(
lhs
,
rhs
,
entry
)
self
.
block
.
stats
.
append
(
assignment
)
self
.
block
.
gen
[
entry
]
=
assignment
self
.
entries
.
add
(
entry
)
def
mark_argument
(
self
,
lhs
,
rhs
,
entry
):
entry
=
entry
.
defining_entry
if
self
.
block
and
self
.
is_tracked
(
entry
):
assignment
=
Argument
(
lhs
,
rhs
,
entry
)
self
.
block
.
stats
.
append
(
assignment
)
...
...
@@ -177,6 +177,7 @@ class ControlFlow(object):
self
.
entries
.
add
(
entry
)
def
mark_deletion
(
self
,
node
,
entry
):
entry
=
entry
.
defining_entry
if
self
.
block
and
self
.
is_tracked
(
entry
):
assignment
=
NameDeletion
(
node
,
entry
)
self
.
block
.
stats
.
append
(
assignment
)
...
...
@@ -184,6 +185,7 @@ class ControlFlow(object):
self
.
entries
.
add
(
entry
)
def
mark_reference
(
self
,
node
,
entry
):
entry
=
entry
.
defining_entry
if
self
.
block
and
self
.
is_tracked
(
entry
):
self
.
block
.
stats
.
append
(
NameReference
(
node
,
entry
))
# Local variable is definitely bound after this reference
...
...
@@ -534,6 +536,8 @@ def check_definitions(flow, compiler_directives):
node
.
cf_is_null
=
True
if
node
.
allow_null
or
entry
.
from_closure
or
entry
.
is_pyclass_attr
:
pass
# Can be uninitialized here
elif
entry
.
in_closure
:
pass
# not smart enough to get this right
elif
node
.
cf_is_null
:
if
(
entry
.
type
.
is_pyobject
or
entry
.
type
.
is_unspecified
or
entry
.
error_on_uninitialized
):
...
...
Cython/Compiler/Optimize.py
View file @
8e7a120b
...
...
@@ -1657,9 +1657,20 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
return
node
return
kwargs
class
InlineDefNodeCalls
(
Visitor
.
Cython
Transform
):
class
InlineDefNodeCalls
(
Visitor
.
Env
Transform
):
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
):
self
.
visitchildren
(
node
)
if
not
self
.
current_directives
.
get
(
'optimize.inline_defnode_calls'
):
...
...
@@ -1667,10 +1678,7 @@ class InlineDefNodeCalls(Visitor.CythonTransform):
function_name
=
node
.
function
if
not
function_name
.
is_name
:
return
node
if
(
function_name
.
cf_state
is
None
# global scope
or
not
function_name
.
cf_state
.
is_single
):
return
node
function
=
function_name
.
cf_state
.
one
().
rhs
function
=
self
.
get_constant_value_node
(
function_name
)
if
not
isinstance
(
function
,
ExprNodes
.
PyCFunctionNode
):
return
node
inlined
=
ExprNodes
.
InlinedDefNodeCallNode
(
...
...
Cython/Compiler/Symtab.py
View file @
8e7a120b
...
...
@@ -198,9 +198,10 @@ class Entry(object):
self
.
cf_assignments
=
[]
self
.
cf_references
=
[]
self
.
inner_entries
=
[]
self
.
defining_entry
=
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
):
error
(
pos
,
"'%s' does not match previous declaration"
%
self
.
name
)
...
...
@@ -210,20 +211,36 @@ class Entry(object):
return
[
self
]
+
self
.
overloaded_alternatives
def
all_entries
(
self
):
"""
Returns all entries for this entry, including the equivalent ones
in other closures.
"""
if
self
.
from_closure
:
return
self
.
outer_entry
.
all_entries
()
return
[
self
]
+
self
.
inner_entries
entries
=
[]
def
collect_inner_entries
(
entry
):
entries
.
append
(
entry
)
for
e
in
entry
.
inner_entries
:
collect_inner_entries
(
e
)
collect_inner_entries
(
self
)
return
entries
class
InnerEntry
(
Entry
):
"""
An entry in a closure scope that represents the real outer Entry.
"""
from_closure
=
True
def
__init__
(
self
,
outer_entry
,
scope
):
Entry
.
__init__
(
self
,
outer_entry
.
name
,
outer_entry
.
cname
,
outer_entry
.
type
,
outer_entry
.
pos
)
self
.
outer_entry
=
outer_entry
self
.
scope
=
scope
# 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
):
...
...
@@ -1534,15 +1551,9 @@ class LocalScope(Scope):
# The actual c fragment for the different scopes differs
# on the outside and inside, so we make a new entry
entry
.
in_closure
=
True
# Would it be better to declare_var here?
inner_entry
=
Entry
(
entry
.
name
,
entry
.
cname
,
entry
.
type
,
entry
.
pos
)
inner_entry
.
scope
=
self
inner_entry
=
InnerEntry
(
entry
,
self
)
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
entry
.
inner_entries
.
append
(
inner_entry
)
return
inner_entry
return
entry
...
...
Cython/Compiler/TypeInference.py
View file @
8e7a120b
...
...
@@ -360,11 +360,9 @@ class SimpleAssignmentTypeInferer(object):
ready_to_infer
=
[]
for
name
,
entry
in
scope
.
entries
.
items
():
if
entry
.
type
is
unspecified_type
:
entries
=
entry
.
all_entries
()
all
=
set
()
for
e
in
entries
:
for
assmt
in
e
.
cf_assignments
:
all
.
update
(
assmt
.
type_dependencies
(
e
.
scope
))
for
assmt
in
entry
.
cf_assignments
:
all
.
update
(
assmt
.
type_dependencies
(
entry
.
scope
))
if
all
:
dependancies_by_entry
[
entry
]
=
all
for
dep
in
all
:
...
...
@@ -390,8 +388,7 @@ class SimpleAssignmentTypeInferer(object):
entry
=
ready_to_infer
.
pop
()
types
=
[
assmt
.
rhs
.
infer_type
(
scope
)
for
e
in
entry
.
all_entries
()
for
assmt
in
e
.
cf_assignments
for
assmt
in
entry
.
cf_assignments
]
if
types
and
Utils
.
all
(
types
):
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():
pass
call
(
1
,
sideeffect
(
2
),
3
,
sideeffect
(
4
),
sideeffect
(
5
))
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():
nonlocal
x
x
=
2.0
inner
()
assert
x
==
2.0
assert
x
==
2.0
,
str
(
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