summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/compiler/ast.py4
-rw-r--r--Lib/compiler/pycodegen.py19
-rw-r--r--Lib/compiler/symbols.py2
-rw-r--r--Lib/test/test_compiler.py7
-rw-r--r--Misc/NEWS3
5 files changed, 26 insertions, 9 deletions
diff --git a/Lib/compiler/ast.py b/Lib/compiler/ast.py
index 8dcdf68ada..93437d6cee 100644
--- a/Lib/compiler/ast.py
+++ b/Lib/compiler/ast.py
@@ -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,
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index e3667b594d..009438da6d 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -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)
diff --git a/Lib/compiler/symbols.py b/Lib/compiler/symbols.py
index 8eb5fceca7..8f6298060d 100644
--- a/Lib/compiler/symbols.py
+++ b/Lib/compiler/symbols.py
@@ -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)
diff --git a/Lib/test/test_compiler.py b/Lib/test/test_compiler.py
index 1efb6a620f..81f2ea8925 100644
--- a/Lib/test/test_compiler.py
+++ b/Lib/test/test_compiler.py
@@ -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)
diff --git a/Misc/NEWS b/Misc/NEWS
index b3a3e7df49..c4824110eb 100644
--- 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