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)
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')
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)
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)
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