mirror of https://github.com/python/cpython
Fix a bug in the ``compiler`` package that caused invalid code to be
generated for generator expressions.
This commit is contained in:
parent
7ae354846f
commit
4c6b0d5bec
|
@ -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,
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue