cython-devel
changeset 3980:cb1b7b395979
Support class closures and nested classes.
Disable some pyregr tests. As side effect this seems to solve ticket #537
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
