]> granicus.if.org Git - python/commitdiff
Fix a bug in the ``compiler`` package that caused invalid code to be
authorNeil Schemenauer <nascheme@enme.ucalgary.ca>
Wed, 16 Aug 2006 23:38:05 +0000 (23:38 +0000)
committerNeil Schemenauer <nascheme@enme.ucalgary.ca>
Wed, 16 Aug 2006 23:38:05 +0000 (23:38 +0000)
generated for generator expressions.

Lib/compiler/ast.py
Lib/compiler/pycodegen.py
Lib/compiler/symbols.py
Lib/test/test_compiler.py
Misc/NEWS

index 8dcdf68ada373c716e10aa8f4185831050e4cff5..93437d6ceef07800e8d6ebaa9b6e6716438aff05 100644 (file)
@@ -583,11 +583,9 @@ class GenExpr(Node):
     def __init__(self, code, lineno=None):
         self.code = code
         self.lineno = lineno
-        self.argnames = ['[outmost-iterable]']
+        self.argnames = ['.0']
         self.varargs = self.kwargs = None
 
-
-
     def getChildren(self):
         return self.code,
 
index e3667b594d3bd45260d0ac1cdec81a8925579a55..009438da6d8eba9461c1963539c618ad2ad49416 100644 (file)
@@ -658,18 +658,19 @@ class CodeGenerator:
 
         stack = []
         for i, for_ in zip(range(len(node.quals)), node.quals):
-            start, anchor = self.visit(for_)
+            start, anchor, end = self.visit(for_)
             cont = None
             for if_ in for_.ifs:
                 if cont is None:
                     cont = self.newBlock()
                 self.visit(if_, cont)
-            stack.insert(0, (start, cont, anchor))
+            stack.insert(0, (start, cont, anchor, end))
 
         self.visit(node.expr)
         self.emit('YIELD_VALUE')
+        self.emit('POP_TOP')
 
-        for start, cont, anchor in stack:
+        for start, cont, anchor, end in stack:
             if cont:
                 skip_one = self.newBlock()
                 self.emit('JUMP_FORWARD', skip_one)
@@ -678,14 +679,22 @@ class CodeGenerator:
                 self.nextBlock(skip_one)
             self.emit('JUMP_ABSOLUTE', start)
             self.startBlock(anchor)
+            self.emit('POP_BLOCK')
+            self.setups.pop()
+            self.startBlock(end)
+
         self.emit('LOAD_CONST', None)
 
     def visitGenExprFor(self, node):
         start = self.newBlock()
         anchor = self.newBlock()
+        end = self.newBlock()
+
+        self.setups.push((LOOP, start))
+        self.emit('SETUP_LOOP', end)
 
         if node.is_outmost:
-            self.loadName('[outmost-iterable]')
+            self.loadName('.0')
         else:
             self.visit(node.iter)
             self.emit('GET_ITER')
@@ -695,7 +704,7 @@ class CodeGenerator:
         self.emit('FOR_ITER', anchor)
         self.nextBlock()
         self.visit(node.assign)
-        return start, anchor
+        return start, anchor, end
 
     def visitGenExprIf(self, node, branch):
         self.set_lineno(node, force=True)
index 8eb5fceca79418be427a5422d2c2a14fc95de20d..8f6298060d825808bb66ef1dcd99485232f3616f 100644 (file)
@@ -188,7 +188,7 @@ class GenExprScope(Scope):
         i = self.__counter
         self.__counter += 1
         self.__super_init("generator expression<%d>"%i, module, klass)
-        self.add_param('[outmost-iterable]')
+        self.add_param('.0')
 
     def get_names(self):
         keys = Scope.get_names(self)
index 1efb6a620fd62b3ba00cdce446b4bae6ddd39c30..81f2ea89250504071537814a719a1708d1920959 100644 (file)
@@ -116,6 +116,13 @@ class CompilerTest(unittest.TestCase):
         exec c in dct
         self.assertEquals(dct.get('result'), 3)
 
+    def testGenExp(self):
+        c = compiler.compile('list((i,j) for i in range(3) if i < 3'
+                             '           for j in range(4) if j > 2)',
+                             '<string>',
+                             'eval')
+        self.assertEquals(eval(c), [(0, 3), (1, 3), (2, 3)])
+
 
 NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard)
 
index b3a3e7df499bb38008048aed4251879f74f1716a..c4824110ebb9eb76d0832063f529c72fac2ae376 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -64,6 +64,9 @@ Core and builtins
 Library
 -------
 
+- Fix a bug in the ``compiler`` package that caused invalid code to be
+  generated for generator expressions.
+
 - The distutils version has been changed to 2.5.0. The change to
   keep it programmatically in sync with the Python version running
   the code (introduced in 2.5b3) has been reverted. It will continue