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
c6b07f36
Commit
c6b07f36
authored
Apr 23, 2009
by
Robert Bradshaw
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Arbitrary nested closure support.
parent
a504dae0
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
91 additions
and
50 deletions
+91
-50
Cython/Compiler/Naming.py
Cython/Compiler/Naming.py
+2
-0
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+37
-24
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+14
-2
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+38
-24
No files found.
Cython/Compiler/Naming.py
View file @
c6b07f36
...
@@ -83,6 +83,8 @@ pymoduledef_cname = pyrex_prefix + "moduledef"
...
@@ -83,6 +83,8 @@ pymoduledef_cname = pyrex_prefix + "moduledef"
optional_args_cname
=
pyrex_prefix
+
"optional_args"
optional_args_cname
=
pyrex_prefix
+
"optional_args"
import_star
=
pyrex_prefix
+
"import_star"
import_star
=
pyrex_prefix
+
"import_star"
import_star_set
=
pyrex_prefix
+
"import_star_set"
import_star_set
=
pyrex_prefix
+
"import_star_set"
cur_scope_cname
=
pyrex_prefix
+
"scope"
outer_scope_cname
=
pyrex_prefix
+
"outer_scope"
line_c_macro
=
"__LINE__"
line_c_macro
=
"__LINE__"
...
...
Cython/Compiler/Nodes.py
View file @
c6b07f36
...
@@ -992,6 +992,12 @@ class FuncDefNode(StatNode, BlockNode):
...
@@ -992,6 +992,12 @@ class FuncDefNode(StatNode, BlockNode):
import
Buffer
import
Buffer
lenv
=
self
.
local_scope
lenv
=
self
.
local_scope
if
lenv
.
is_closure_scope
:
outer_scope_cname
=
"%s->%s"
%
(
Naming
.
cur_scope_cname
,
Naming
.
outer_scope_cname
)
else
:
outer_scope_cname
=
Naming
.
outer_scope_cname
lenv
.
mangle_closure_cnames
(
outer_scope_cname
)
# Generate closure function definitions
# Generate closure function definitions
self
.
body
.
generate_function_definitions
(
lenv
,
code
)
self
.
body
.
generate_function_definitions
(
lenv
,
code
)
...
@@ -1014,18 +1020,16 @@ class FuncDefNode(StatNode, BlockNode):
...
@@ -1014,18 +1020,16 @@ class FuncDefNode(StatNode, BlockNode):
self
.
generate_function_header
(
code
,
self
.
generate_function_header
(
code
,
with_pymethdef
=
env
.
is_py_class_scope
or
env
.
is_closure_scope
)
with_pymethdef
=
env
.
is_py_class_scope
or
env
.
is_closure_scope
)
# ----- Local variable declarations
# ----- Local variable declarations
# lenv.mangle_closure_cnames(Naming.cur_scope_cname)
if
lenv
.
is_closure_scope
:
if
self
.
needs_closure
:
code
.
put
(
lenv
.
scope_class
.
type
.
declaration_code
(
Naming
.
cur_scope_cname
))
code
.
put
(
lenv
.
scope_class
.
type
.
declaration_code
(
lenv
.
closure_cname
))
code
.
putln
(
";"
)
code
.
putln
(
";"
)
else
:
if
env
.
is_closure_scope
and
not
lenv
.
is_closure_scope
:
self
.
generate_argument_declarations
(
lenv
,
code
)
code
.
put
(
env
.
scope_class
.
type
.
declaration_code
(
Naming
.
outer_scope_cname
))
code
.
put_var_declarations
(
lenv
.
var_entries
)
code
.
putln
(
";"
)
if
env
.
is_closure_scope
:
self
.
generate_argument_declarations
(
lenv
,
code
)
code
.
putln
(
"%s = (%s)%s;"
%
(
for
entry
in
lenv
.
var_entries
:
env
.
scope_class
.
type
.
declaration_code
(
env
.
closure_cname
),
if
not
entry
.
in_closure
:
env
.
scope_class
.
type
.
declaration_code
(
''
),
code
.
put_var_declaration
(
entry
)
Naming
.
self_cname
))
init
=
""
init
=
""
if
not
self
.
return_type
.
is_void
:
if
not
self
.
return_type
.
is_void
:
if
self
.
return_type
.
is_pyobject
:
if
self
.
return_type
.
is_pyobject
:
...
@@ -1052,7 +1056,7 @@ class FuncDefNode(StatNode, BlockNode):
...
@@ -1052,7 +1056,7 @@ class FuncDefNode(StatNode, BlockNode):
# ----- Create closure scope object
# ----- Create closure scope object
if
self
.
needs_closure
:
if
self
.
needs_closure
:
code
.
putln
(
"%s = (%s)%s->tp_new(%s, %s, NULL);"
%
(
code
.
putln
(
"%s = (%s)%s->tp_new(%s, %s, NULL);"
%
(
lenv
.
closur
e_cname
,
Naming
.
cur_scop
e_cname
,
lenv
.
scope_class
.
type
.
declaration_code
(
''
),
lenv
.
scope_class
.
type
.
declaration_code
(
''
),
lenv
.
scope_class
.
type
.
typeptr_cname
,
lenv
.
scope_class
.
type
.
typeptr_cname
,
lenv
.
scope_class
.
type
.
typeptr_cname
,
lenv
.
scope_class
.
type
.
typeptr_cname
,
...
@@ -1061,9 +1065,15 @@ class FuncDefNode(StatNode, BlockNode):
...
@@ -1061,9 +1065,15 @@ class FuncDefNode(StatNode, BlockNode):
# The code below assumes the local variables are innitially NULL
# The code below assumes the local variables are innitially NULL
# Note that it is unsafe to decref the scope at this point.
# Note that it is unsafe to decref the scope at this point.
for
entry
in
lenv
.
arg_entries
+
lenv
.
var_entries
:
for
entry
in
lenv
.
arg_entries
+
lenv
.
var_entries
:
if
entry
.
type
.
is_pyobject
:
if
entry
.
in_closure
and
entry
.
type
.
is_pyobject
:
code
.
put_var_decref
(
entry
)
code
.
put_var_decref_clear
(
entry
)
code
.
putln
(
"%s = NULL;"
%
entry
.
cname
)
if
env
.
is_closure_scope
:
if
lenv
.
is_closure_scope
:
code
.
put_decref
(
outer_scope_cname
,
env
.
scope_class
.
type
)
code
.
putln
(
"%s = (%s)%s;"
%
(
outer_scope_cname
,
env
.
scope_class
.
type
.
declaration_code
(
''
),
Naming
.
self_cname
))
# ----- Fetch arguments
# ----- Fetch arguments
self
.
generate_argument_parsing_code
(
env
,
code
)
self
.
generate_argument_parsing_code
(
env
,
code
)
# If an argument is assigned to in the body, we must
# If an argument is assigned to in the body, we must
...
@@ -1167,13 +1177,16 @@ class FuncDefNode(StatNode, BlockNode):
...
@@ -1167,13 +1177,16 @@ class FuncDefNode(StatNode, BlockNode):
entry
.
xdecref_cleanup
=
1
entry
.
xdecref_cleanup
=
1
if
self
.
needs_closure
:
if
self
.
needs_closure
:
code
.
put_decref
(
lenv
.
closure_cname
,
lenv
.
scope_class
.
type
)
code
.
put_decref
(
Naming
.
cur_scope_cname
,
lenv
.
scope_class
.
type
)
else
:
for
entry
in
lenv
.
var_entries
:
code
.
put_var_decrefs
(
lenv
.
var_entries
,
used_only
=
1
)
if
entry
.
used
and
not
entry
.
in_closure
:
# Decref any increfed args
code
.
put_var_decref
(
entry
)
for
entry
in
lenv
.
arg_entries
:
# Decref any increfed args
if
entry
.
type
.
is_pyobject
and
lenv
.
control_flow
.
get_state
((
entry
.
name
,
'source'
))
!=
'arg'
:
for
entry
in
lenv
.
arg_entries
:
code
.
put_var_decref
(
entry
)
if
(
entry
.
type
.
is_pyobject
and
not
entry
.
in_closure
and
lenv
.
control_flow
.
get_state
((
entry
.
name
,
'source'
))
!=
'arg'
):
code
.
put_var_decref
(
entry
)
# ----- Return
# ----- Return
# This code is duplicated in ModuleNode.generate_module_init_func
# This code is duplicated in ModuleNode.generate_module_init_func
...
@@ -1815,7 +1828,7 @@ class DefNode(FuncDefNode):
...
@@ -1815,7 +1828,7 @@ class DefNode(FuncDefNode):
pymethdef_cname
=
self
.
entry
.
pymethdef_cname
))
pymethdef_cname
=
self
.
entry
.
pymethdef_cname
))
elif
env
.
is_closure_scope
:
elif
env
.
is_closure_scope
:
self_object
=
ExprNodes
.
TempNode
(
self
.
pos
,
env
.
scope_class
.
type
,
env
)
self_object
=
ExprNodes
.
TempNode
(
self
.
pos
,
env
.
scope_class
.
type
,
env
)
self_object
.
temp_cname
=
"((PyObject*)%s)"
%
env
.
closur
e_cname
self_object
.
temp_cname
=
"((PyObject*)%s)"
%
Naming
.
cur_scop
e_cname
rhs
=
ExprNodes
.
PyCFunctionNode
(
self
.
pos
,
rhs
=
ExprNodes
.
PyCFunctionNode
(
self
.
pos
,
self_object
=
self_object
,
self_object
=
self_object
,
pymethdef_cname
=
self
.
entry
.
pymethdef_cname
)
pymethdef_cname
=
self
.
entry
.
pymethdef_cname
)
...
@@ -1870,7 +1883,7 @@ class DefNode(FuncDefNode):
...
@@ -1870,7 +1883,7 @@ class DefNode(FuncDefNode):
if
arg
.
is_generic
:
# or arg.needs_conversion:
if
arg
.
is_generic
:
# or arg.needs_conversion:
if
arg
.
needs_conversion
:
if
arg
.
needs_conversion
:
code
.
putln
(
"PyObject *%s = 0;"
%
arg
.
hdr_cname
)
code
.
putln
(
"PyObject *%s = 0;"
%
arg
.
hdr_cname
)
el
s
e
:
el
if
not
entry
.
in_closur
e
:
code
.
put_var_declaration
(
arg
.
entry
)
code
.
put_var_declaration
(
arg
.
entry
)
def
generate_keyword_list
(
self
,
code
):
def
generate_keyword_list
(
self
,
code
):
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
c6b07f36
...
@@ -864,6 +864,9 @@ class CreateClosureClasses(CythonTransform):
...
@@ -864,6 +864,9 @@ class CreateClosureClasses(CythonTransform):
return
node
return
node
def
create_class_from_scope
(
self
,
node
,
target_module_scope
):
def
create_class_from_scope
(
self
,
node
,
target_module_scope
):
print
node
.
entry
.
scope
.
is_closure_scope
as_name
=
"%s%s"
%
(
Naming
.
closure_class_prefix
,
node
.
entry
.
cname
)
as_name
=
"%s%s"
%
(
Naming
.
closure_class_prefix
,
node
.
entry
.
cname
)
func_scope
=
node
.
local_scope
func_scope
=
node
.
local_scope
...
@@ -871,9 +874,17 @@ class CreateClosureClasses(CythonTransform):
...
@@ -871,9 +874,17 @@ class CreateClosureClasses(CythonTransform):
pos
=
node
.
pos
,
defining
=
True
,
implementing
=
True
)
pos
=
node
.
pos
,
defining
=
True
,
implementing
=
True
)
func_scope
.
scope_class
=
entry
func_scope
.
scope_class
=
entry
class_scope
=
entry
.
type
.
scope
class_scope
=
entry
.
type
.
scope
for
entry
in
func_scope
.
entries
.
values
()
:
if
node
.
entry
.
scope
.
is_closure_scope
:
cname
=
entry
.
cname
[
entry
.
cname
.
index
(
'->'
)
+
2
:]
# everywhere but here they're attached to this class
print
"yes"
,
class_scope
class_scope
.
declare_var
(
pos
=
node
.
pos
,
class_scope
.
declare_var
(
pos
=
node
.
pos
,
name
=
Naming
.
outer_scope_cname
,
# this could conflict?
cname
=
Naming
.
outer_scope_cname
,
type
=
node
.
entry
.
scope
.
scope_class
.
type
,
is_cdef
=
True
)
for
entry
in
func_scope
.
entries
.
values
():
# This is wasteful--we should do this later when we know which vars are actually being used inside...
cname
=
entry
.
cname
class_scope
.
declare_var
(
pos
=
entry
.
pos
,
name
=
entry
.
name
,
name
=
entry
.
name
,
cname
=
cname
,
cname
=
cname
,
type
=
entry
.
type
,
type
=
entry
.
type
,
...
@@ -882,6 +893,7 @@ class CreateClosureClasses(CythonTransform):
...
@@ -882,6 +893,7 @@ class CreateClosureClasses(CythonTransform):
def
visit_FuncDefNode
(
self
,
node
):
def
visit_FuncDefNode
(
self
,
node
):
if
node
.
needs_closure
:
if
node
.
needs_closure
:
self
.
create_class_from_scope
(
node
,
self
.
module_scope
)
self
.
create_class_from_scope
(
node
,
self
.
module_scope
)
self
.
visitchildren
(
node
)
return
node
return
node
...
...
Cython/Compiler/Symtab.py
View file @
c6b07f36
...
@@ -19,6 +19,7 @@ try:
...
@@ -19,6 +19,7 @@ try:
set
set
except
NameError
:
except
NameError
:
from
sets
import
Set
as
set
from
sets
import
Set
as
set
import
copy
possible_identifier
=
re
.
compile
(
ur"(?![0-9])\
w+$
", re.U).match
possible_identifier
=
re
.
compile
(
ur"(?![0-9])\
w+$
", re.U).match
nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
...
@@ -140,6 +141,7 @@ class Entry(object):
...
@@ -140,6 +141,7 @@ class Entry(object):
is_arg = 0
is_arg = 0
is_local = 0
is_local = 0
in_closure = 0
in_closure = 0
from_closure = 0
is_declared_generic = 0
is_declared_generic = 0
is_readonly = 0
is_readonly = 0
func_cname = None
func_cname = None
...
@@ -499,14 +501,7 @@ class Scope(object):
...
@@ -499,14 +501,7 @@ class Scope(object):
# Look up name in this scope or an enclosing one.
# Look up name in this scope or an enclosing one.
# Return None if not found.
# Return None if not found.
return (self.lookup_here(name)
return (self.lookup_here(name)
or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
or (self.outer_scope and self.outer_scope.lookup(name))
or None)
def lookup_from_inner(self, name):
# Look up name in this scope or an enclosing one.
# This is only called from enclosing scopes.
return (self.lookup_here(name)
or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
or None)
or None)
def lookup_here(self, name):
def lookup_here(self, name):
...
@@ -1013,7 +1008,7 @@ class ModuleScope(Scope):
...
@@ -1013,7 +1008,7 @@ class ModuleScope(Scope):
var_entry.is_readonly = 1
var_entry.is_readonly = 1
entry.as_variable = var_entry
entry.as_variable = var_entry
class LocalScope(Scope):
class LocalScope(Scope):
def __init__(self, name, outer_scope):
def __init__(self, name, outer_scope):
Scope.__init__(self, name, outer_scope, outer_scope)
Scope.__init__(self, name, outer_scope, outer_scope)
...
@@ -1056,21 +1051,39 @@ class LocalScope(Scope):
...
@@ -1056,21 +1051,39 @@ class LocalScope(Scope):
entry = self.global_scope().lookup_target(name)
entry = self.global_scope().lookup_target(name)
self.entries[name] = entry
self.entries[name] = entry
def lookup_from_inner(self, name):
def lookup(self, name):
entry = self.lookup_here(name)
# Look up name in this scope or an enclosing one.
if entry:
# Return None if not found.
entry.in_closure = 1
entry = Scope.lookup(self, name)
return entry
if entry is not None:
else:
if entry.scope is not self and entry.scope.is_closure_scope:
return (self.outer_scope and self.outer_scope.lookup_from_inner(name)) or None
print "making new entry for", entry.cname, "in", self
# 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.is_variable = True
inner_entry.outer_entry = entry
inner_entry.from_closure = True
self.entries[name] = inner_entry
return inner_entry
return entry
def mangle_closure_cnames(self, scope_var):
def mangle_closure_cnames(self, outer_scope_cname):
print "mangling", self
for entry in self.entries.values():
for entry in self.entries.values():
if entry.in_closure:
print entry.name, entry.in_closure, entry.from_closure
if not hasattr(entry, '
orig_cname
'):
if entry.from_closure:
entry.orig_cname = entry.cname
cname = entry.outer_entry.cname
entry.cname = scope_var + "->" + entry.cname
if cname.startswith(Naming.cur_scope_cname):
cname = cname[len(Naming.cur_scope_cname)+2:]
entry.cname = "%s->%s" % (outer_scope_cname, cname)
elif entry.in_closure:
entry.original_cname = entry.cname
entry.cname = "%s->%s" % (Naming.cur_scope_cname, entry.cname)
print entry.cname
class ClosureScope(LocalScope):
class ClosureScope(LocalScope):
...
@@ -1085,8 +1098,9 @@ class ClosureScope(LocalScope):
...
@@ -1085,8 +1098,9 @@ class ClosureScope(LocalScope):
# entry.in_closure = 1
# entry.in_closure = 1
# LocalScope.mangle_closure_cnames(self, scope_var)
# LocalScope.mangle_closure_cnames(self, scope_var)
def mangle(self, prefix, name):
# def mangle(self, prefix, name):
return "%s->%s" % (self.closure_cname, name)
# return "%s->%s" % (self.cur_scope_cname, name)
# return "%s->%s" % (self.closure_cname, name)
def declare_pyfunction(self, name, pos):
def declare_pyfunction(self, name, pos):
# Add an entry for a Python function.
# Add an entry for a Python function.
...
...
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