From: Neil Schemenauer Date: Wed, 16 Aug 2006 23:38:05 +0000 (+0000) Subject: Fix a bug in the ``compiler`` package that caused invalid code to be X-Git-Tag: v2.5c1~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4c6b0d5bec587770e0d83b550faae97fe251cc65;p=thirdparty%2FPython%2Fcpython.git 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 8dcdf68ada37..93437d6ceef0 100644 --- a/Lib/compiler/ast.py +++ b/Lib/compiler/ast.py @@ -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, diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py index e3667b594d3b..009438da6d8e 100644 --- a/Lib/compiler/pycodegen.py +++ b/Lib/compiler/pycodegen.py @@ -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) diff --git a/Lib/compiler/symbols.py b/Lib/compiler/symbols.py index 8eb5fceca794..8f6298060d82 100644 --- a/Lib/compiler/symbols.py +++ b/Lib/compiler/symbols.py @@ -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) diff --git a/Lib/test/test_compiler.py b/Lib/test/test_compiler.py index 1efb6a620fd6..81f2ea892505 100644 --- a/Lib/test/test_compiler.py +++ b/Lib/test/test_compiler.py @@ -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)', + '', + '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 b3a3e7df499b..c4824110ebb9 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -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