Support lambda in module scope #603
authorVitja Makarov <vitja.makarov@gmail.com>
Sat, 27 Nov 2010 16:09:38 +0000 (19:09 +0300)
committerVitja Makarov <vitja.makarov@gmail.com>
Sat, 27 Nov 2010 16:09:38 +0000 (19:09 +0300)
Cython/Compiler/Nodes.py
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/Symtab.py
tests/run/lambda_module.pyx [new file with mode: 0644]

index 10706766af77d56a8a5bec6fdcb42a4d885937ea..ae557f734424a6d1f4b7de3dc98d1a3591333caf 100644 (file)
@@ -2215,6 +2215,8 @@ class DefNode(FuncDefNode):
 
     def needs_assignment_synthesis(self, env, code=None):
         # Should enable for module level as well, that will require more testing...
+        if self.entry.is_lambda:
+            return True
         if env.is_module_scope:
             if code is None:
                 return env.directives['binding']
index d0443def6ed6e5d8089dde3bd14a00e3dec59545..3ab87d033428af1cf6eef07c7bcb965b2c830f1f 100644 (file)
@@ -181,9 +181,6 @@ class PostParse(ScopeTrackingTransform):
 
     def visit_LambdaNode(self, node):
         # unpack a lambda expression into the corresponding DefNode
-        if self.scope_type != 'function':
-            error(node.pos,
-                  "lambda functions are currently only supported in functions")
         lambda_id = self.lambda_counter
         self.lambda_counter += 1
         node.lambda_name = EncodedString(u'lambda%d' % lambda_id)
@@ -1366,7 +1363,7 @@ class CreateClosureClasses(CythonTransform):
         while cscope.is_py_class_scope or cscope.is_c_class_scope:
             cscope = cscope.outer_scope
 
-        if not from_closure and self.path:
+        if not from_closure and (self.path or inner_node):
             if not inner_node:
                 if not node.assmt:
                     raise InternalError, "DefNode does not have assignment node"
index 1f62c06ffe4fd493f9d4f938b3c84b23d1fc9661..1dec232167ad070f1975eb6c77dd0ac2c5a17cda 100644 (file)
@@ -75,6 +75,7 @@ class Entry(object):
     # is_cfunction     boolean    Is a C function
     # is_cmethod       boolean    Is a C method of an extension type
     # is_unbound_cmethod boolean  Is an unbound C method of an extension type
+    # is_lambda        boolean    Is a lambda function
     # is_type          boolean    Is a type definition
     # is_cclass        boolean    Is an extension class
     # is_cpp_class     boolean    Is a C++ class
@@ -137,6 +138,7 @@ class Entry(object):
     is_cfunction = 0
     is_cmethod = 0
     is_unbound_cmethod = 0
+    is_lambda = 0
     is_type = 0
     is_cclass = 0
     is_cpp_class = 0
@@ -530,7 +532,7 @@ class Scope(object):
         entry.name = EncodedString(func_cname)
         entry.func_cname = func_cname
         entry.signature = pyfunction_signature
-        self.pyfunc_entries.append(entry)
+        entry.is_lambda = True
         return entry
 
     def add_lambda_def(self, def_node):
diff --git a/tests/run/lambda_module.pyx b/tests/run/lambda_module.pyx
new file mode 100644 (file)
index 0000000..8bc3ef0
--- /dev/null
@@ -0,0 +1,25 @@
+# Module scope lambda functions
+__doc__ = """
+>>> pow2(16)
+256
+>>> with_closure(0)
+0
+>>> typed_lambda(1)(2)
+3
+>>> typed_lambda(1.5)(1.5)
+2
+>>> cdef_const_lambda()
+123
+>>> const_lambda()
+321
+"""
+
+pow2 = lambda x: x * x
+with_closure = lambda x:(lambda: x)()
+typed_lambda = lambda int x : (lambda int y: x + y)
+
+cdef int xxx = 123
+cdef_const_lambda = lambda: xxx
+
+yyy = 321
+const_lambda = lambda: yyy