Fix error handling add error tests
authorVitja Makarov <vitja.makarov@gmail.com>
Mon, 13 Dec 2010 17:50:41 +0000 (20:50 +0300)
committerVitja Makarov <vitja.makarov@gmail.com>
Mon, 13 Dec 2010 17:50:41 +0000 (20:50 +0300)
Cython/Compiler/ExprNodes.py
Cython/Compiler/ParseTreeTransforms.py
tests/errors/e_generators.pyx [new file with mode: 0644]

index 2fde811bd588fa4d783b28be6f562474586f4de5..bd45bae12d158df614d16d0640c5b71f2a846932 100755 (executable)
@@ -4978,11 +4978,15 @@ class YieldExprNode(ExprNode):
     #
     # arg         ExprNode   the value to return from the generator
     # label_name  string     name of the C label used for this yield
+    # label_num   integer    yield label number
 
     subexprs = ['arg']
     type = py_object_type
+    label_num = 0
 
     def analyse_types(self, env):
+        if not self.label_num:
+            error(self.pos, "'yield' not supported here")
         self.is_temp = 1
         if self.arg is not None:
             self.arg.analyse_types(env)
index 60cee2b0bec1130fdbae19fd5eda3428934bdad4..39cf2ffb5593592a2f5aa628b53233d003ecedc0 100644 (file)
@@ -1308,22 +1308,23 @@ class YieldNodeCollector(TreeVisitor):
     def __init__(self):
         super(YieldNodeCollector, self).__init__()
         self.yields = []
-        self.has_return = False
+        self.returns = []
+        self.has_return_value = False
 
     visit_Node = TreeVisitor.visitchildren
 
     def visit_YieldExprNode(self, node):
-        if self.has_return:
+        if self.has_return_value:
             error(node.pos, "'yield' outside function")
-        else:
-            self.yields.append(node)
-            node.label_num = len(self.yields)
+        self.yields.append(node)
+        node.label_num = len(self.yields)
 
     def visit_ReturnStatNode(self, node):
-        if self.yields:
-            error(collector.returns[0].pos, "'return' with argument inside generator")
-        else:
-            self.has_return = True
+        if node.value:
+            self.has_return_value = True
+            if self.yields:
+                error(node.pos, "'return' with argument inside generator")
+        self.returns.append(node)
 
     def visit_ClassDefNode(self, node):
         pass
@@ -1348,6 +1349,8 @@ class MarkClosureVisitor(CythonTransform):
         collector.visitchildren(node)
 
         if collector.yields:
+            if collector.returns and not collector.has_return_value:
+                error(collector.returns[0].pos, "'return' inside generators not yet supported ")
             node.is_generator = True
             node.needs_closure = True
             node.yields = collector.yields
diff --git a/tests/errors/e_generators.pyx b/tests/errors/e_generators.pyx
new file mode 100644 (file)
index 0000000..5cee59d
--- /dev/null
@@ -0,0 +1,24 @@
+def foo():
+    yield
+    return 0
+
+def bar(a):
+    return 0
+    yield
+
+def xxx():
+    yield
+    return
+
+yield
+
+class Foo:
+    yield
+
+_ERRORS = u"""
+3:4: 'return' with argument inside generator
+7:4: 'yield' outside function
+11:4: 'return' inside generators not yet supported
+13:0: 'yield' not supported here
+16:4: 'yield' not supported here
+"""