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

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

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

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