Commit 4c6b0d5b authored by Neil Schemenauer's avatar Neil Schemenauer

Fix a bug in the ``compiler`` package that caused invalid code to be

generated for generator expressions.
parent 7ae35484
......@@ -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,
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment