cython-devel

changeset 3980:cb1b7b395979

Support class closures and nested classes.

Disable some pyregr tests. As side effect this seems to solve ticket #537
author Vitja Makarov <vitja.makarov@gmail.com>
date Fri Nov 19 02:28:12 2010 +0300 (2 years ago)
parents f4ed9d5c8be6
children cb468a581638
files Cython/Compiler/Nodes.py Cython/Compiler/ParseTreeTransforms.py Cython/Compiler/Parsing.py tests/bugs.txt
line diff
1.1 --- a/Cython/Compiler/Nodes.py Sat Nov 20 22:42:08 2010 +0100 1.2 +++ b/Cython/Compiler/Nodes.py Fri Nov 19 02:28:12 2010 +0300 1.3 @@ -1177,7 +1177,7 @@ 1.4 def create_local_scope(self, env): 1.5 genv = env 1.6 while genv.is_py_class_scope or genv.is_c_class_scope: 1.7 - genv = env.outer_scope 1.8 + genv = genv.outer_scope 1.9 if self.needs_closure: 1.10 lenv = ClosureScope(name=self.entry.name, 1.11 outer_scope = genv, 1.12 @@ -1255,11 +1255,15 @@ 1.13 self.generate_function_header(code, 1.14 with_pymethdef = with_pymethdef) 1.15 # ----- Local variable declarations 1.16 + # Find function scope 1.17 + cenv = env 1.18 + while cenv.is_py_class_scope or cenv.is_c_class_scope: 1.19 + cenv = cenv.outer_scope 1.20 if lenv.is_closure_scope: 1.21 code.put(lenv.scope_class.type.declaration_code(Naming.cur_scope_cname)) 1.22 code.putln(";") 1.23 - elif env.is_closure_scope: 1.24 - code.put(env.scope_class.type.declaration_code(Naming.outer_scope_cname)) 1.25 + elif cenv.is_closure_scope: 1.26 + code.put(cenv.scope_class.type.declaration_code(Naming.outer_scope_cname)) 1.27 code.putln(";") 1.28 self.generate_argument_declarations(lenv, code) 1.29 for entry in lenv.var_entries: 1.30 @@ -1310,14 +1314,14 @@ 1.31 code.putln("}") 1.32 code.put_gotref(Naming.cur_scope_cname) 1.33 # Note that it is unsafe to decref the scope at this point. 1.34 - if env.is_closure_scope: 1.35 + if cenv.is_closure_scope: 1.36 code.putln("%s = (%s)%s;" % ( 1.37 outer_scope_cname, 1.38 - env.scope_class.type.declaration_code(''), 1.39 + cenv.scope_class.type.declaration_code(''), 1.40 Naming.self_cname)) 1.41 if self.needs_closure: 1.42 # inner closures own a reference to their outer parent 1.43 - code.put_incref(outer_scope_cname, env.scope_class.type) 1.44 + code.put_incref(outer_scope_cname, cenv.scope_class.type) 1.45 code.put_giveref(outer_scope_cname) 1.46 # ----- Trace function call 1.47 if profile: 1.48 @@ -2211,18 +2215,21 @@ 1.49 1.50 def synthesize_assignment_node(self, env): 1.51 import ExprNodes 1.52 + genv = env 1.53 + while genv.is_py_class_scope or genv.is_c_class_scope: 1.54 + genv = genv.outer_scope 1.55 + 1.56 + if genv.is_closure_scope: 1.57 + rhs = ExprNodes.InnerFunctionNode( 1.58 + self.pos, pymethdef_cname = self.entry.pymethdef_cname) 1.59 + else: 1.60 + rhs = ExprNodes.PyCFunctionNode( 1.61 + self.pos, pymethdef_cname = self.entry.pymethdef_cname, binding = env.directives['binding']) 1.62 + 1.63 if env.is_py_class_scope: 1.64 - rhs = ExprNodes.PyCFunctionNode(self.pos, 1.65 - pymethdef_cname = self.entry.pymethdef_cname) 1.66 if not self.is_staticmethod and not self.is_classmethod: 1.67 rhs.binding = True 1.68 1.69 - elif env.is_closure_scope: 1.70 - rhs = ExprNodes.InnerFunctionNode( 1.71 - self.pos, pymethdef_cname = self.entry.pymethdef_cname) 1.72 - else: 1.73 - rhs = ExprNodes.PyCFunctionNode( 1.74 - self.pos, pymethdef_cname = self.entry.pymethdef_cname, binding = env.directives['binding']) 1.75 self.assmt = SingleAssignmentNode(self.pos, 1.76 lhs = ExprNodes.NameNode(self.pos, name = self.name), 1.77 rhs = rhs) 1.78 @@ -3036,8 +3043,8 @@ 1.79 1.80 def create_scope(self, env): 1.81 genv = env 1.82 - while env.is_py_class_scope or env.is_c_class_scope: 1.83 - env = env.outer_scope 1.84 + while genv.is_py_class_scope or genv.is_c_class_scope: 1.85 + genv = genv.outer_scope 1.86 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv) 1.87 return cenv 1.88
2.1 --- a/Cython/Compiler/ParseTreeTransforms.py Sat Nov 20 22:42:08 2010 +0100 2.2 +++ b/Cython/Compiler/ParseTreeTransforms.py Fri Nov 19 02:28:12 2010 +0300 2.3 @@ -1325,7 +1325,7 @@ 2.4 return node 2.5 2.6 def create_class_from_scope(self, node, target_module_scope): 2.7 - as_name = "%s%s" % (Naming.closure_class_prefix, node.entry.cname) 2.8 + as_name = '%s_%s' % (target_module_scope.next_id(Naming.closure_class_prefix), node.entry.cname) 2.9 func_scope = node.local_scope 2.10 2.11 entry = target_module_scope.declare_c_class(name = as_name, 2.12 @@ -1334,11 +1334,15 @@ 2.13 class_scope = entry.type.scope 2.14 class_scope.is_internal = True 2.15 class_scope.directives = {'final': True} 2.16 - if node.entry.scope.is_closure_scope: 2.17 + 2.18 + cscope = node.entry.scope 2.19 + while cscope.is_py_class_scope or cscope.is_c_class_scope: 2.20 + cscope = cscope.outer_scope 2.21 + if cscope.is_closure_scope: 2.22 class_scope.declare_var(pos=node.pos, 2.23 name=Naming.outer_scope_cname, # this could conflict? 2.24 cname=Naming.outer_scope_cname, 2.25 - type=node.entry.scope.scope_class.type, 2.26 + type=cscope.scope_class.type, 2.27 is_cdef=True) 2.28 entries = func_scope.entries.items() 2.29 entries.sort()
3.1 --- a/Cython/Compiler/Parsing.py Sat Nov 20 22:42:08 2010 +0100 3.2 +++ b/Cython/Compiler/Parsing.py Fri Nov 19 02:28:12 2010 +0300 3.3 @@ -1740,7 +1740,7 @@ 3.4 s.level = ctx.level 3.5 return p_def_statement(s, decorators) 3.6 elif s.sy == 'class': 3.7 - if ctx.level != 'module': 3.8 + if ctx.level not in ('module', 'function', 'class', 'other'): 3.9 s.error("class definition not allowed here") 3.10 return p_class_statement(s, decorators) 3.11 elif s.sy == 'include':
4.1 --- a/tests/bugs.txt Sat Nov 20 22:42:08 2010 +0100 4.2 +++ b/tests/bugs.txt Fri Nov 19 02:28:12 2010 +0300 4.3 @@ -23,6 +23,8 @@ 4.4 pyregr.test_threadsignals 4.5 pyregr.test_module 4.6 pyregr.test_capi 4.7 +pyregr.test_socket 4.8 +pyregr.test_threading 4.9 4.10 # CPython regression tests that don't make sense 4.11 pyregr.test_gdb