From: Robert Bradshaw Date: Thu, 23 Apr 2009 10:56:04 +0000 (-0700) Subject: closure cleanup, test X-Git-Tag: 0.13.beta0~2^2~156 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=afd7ed54a2ae0ae53f0baf7cf137d77a73f81255;p=cython.git closure cleanup, test --- diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 49bc277b..7f611afc 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -1062,13 +1062,17 @@ class FuncDefNode(StatNode, BlockNode): lenv.scope_class.type.typeptr_cname, Naming.empty_tuple)) # TODO: error handling - # The code below assumes the local variables are innitially NULL + code.put_gotref(Naming.cur_scope_cname) + # The code below is because we assume the local variables are + # innitially NULL. # Note that it is unsafe to decref the scope at this point. for entry in lenv.arg_entries + lenv.var_entries: if entry.in_closure and entry.type.is_pyobject: + code.put_gotref(entry.cname) # so the refnanny doesn't whine code.put_var_decref_clear(entry) if env.is_closure_scope: if lenv.is_closure_scope: + code.put_gotref(outer_scope_cname) code.put_decref(outer_scope_cname, env.scope_class.type) code.putln("%s = (%s)%s;" % ( outer_scope_cname, @@ -1883,7 +1887,7 @@ class DefNode(FuncDefNode): if arg.is_generic: # or arg.needs_conversion: if arg.needs_conversion: code.putln("PyObject *%s = 0;" % arg.hdr_cname) - elif not entry.in_closure: + elif not arg.entry.in_closure: code.put_var_declaration(arg.entry) def generate_keyword_list(self, code): diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index e732eaa0..f2356854 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -865,8 +865,6 @@ class CreateClosureClasses(CythonTransform): 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) func_scope = node.local_scope @@ -875,7 +873,6 @@ class CreateClosureClasses(CythonTransform): func_scope.scope_class = entry class_scope = entry.type.scope if node.entry.scope.is_closure_scope: - print "yes", class_scope class_scope.declare_var(pos=node.pos, name=Naming.outer_scope_cname, # this could conflict? cname=Naming.outer_scope_cname, diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 681ef4af..b1a361ee 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -1057,7 +1057,6 @@ class LocalScope(Scope): entry = Scope.lookup(self, name) if entry is not None: if entry.scope is not self and entry.scope.is_closure_scope: - 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 @@ -1072,9 +1071,7 @@ class LocalScope(Scope): return entry def mangle_closure_cnames(self, outer_scope_cname): - print "mangling", self for entry in self.entries.values(): - print entry.name, entry.in_closure, entry.from_closure if entry.from_closure: cname = entry.outer_entry.cname if cname.startswith(Naming.cur_scope_cname): @@ -1083,8 +1080,7 @@ class LocalScope(Scope): 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): is_closure_scope = True diff --git a/tests/run/closures_T82.pyx b/tests/run/closures_T82.pyx new file mode 100644 index 00000000..9b89f1a9 --- /dev/null +++ b/tests/run/closures_T82.pyx @@ -0,0 +1,20 @@ +__doc__ = u""" +>>> f = add_n(3) +>>> f(2) +5 + +>>> a(5)() +8 +""" + +def add_n(int n): + def f(int x): + return x+n + return f + +def a(int x): + def b(): + def c(): + return 3+x + return c() + return b