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

generated for generator expressions.
This commit is contained in:
Neil Schemenauer 2006-08-16 23:38:05 +00:00
parent 7ae354846f
commit 4c6b0d5bec
5 changed files with 26 additions and 9 deletions

View 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,

View file

@ -658,18 +658,19 @@ def visitGenExprInner(self, node):
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 @@ def visitGenExprInner(self, node):
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 @@ def visitGenExprFor(self, node):
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)

View file

@ -188,7 +188,7 @@ def __init__(self, module, klass=None):
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)

View file

@ -116,6 +116,13 @@ def testNestedScope(self):
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)

View file

@ -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