Fix a bug in the ``compiler`` package that caused invalid code to be generated for generator expressions.
diff --git a/Lib/compiler/ast.py b/Lib/compiler/ast.py index 8dcdf68..93437d6 100644 --- a/Lib/compiler/ast.py +++ b/Lib/compiler/ast.py
@@ -583,11 +583,9 @@ 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 e3667b5..009438d 100644 --- a/Lib/compiler/pycodegen.py +++ b/Lib/compiler/pycodegen.py
@@ -658,18 +658,19 @@ 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 @@ 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 @@ 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 8eb5fce..8f62980 100644 --- a/Lib/compiler/symbols.py +++ b/Lib/compiler/symbols.py
@@ -188,7 +188,7 @@ 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 1efb6a6..81f2ea8 100644 --- a/Lib/test/test_compiler.py +++ b/Lib/test/test_compiler.py
@@ -116,6 +116,13 @@ 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 b3a3e7d..c482411 100644 --- a/Misc/NEWS +++ b/Misc/NEWS
@@ -64,6 +64,9 @@ 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