Kaydet (Commit) 06ded09d authored tarafından Neil Schemenauer's avatar Neil Schemenauer

Fix the 'compiler' package to generate correct code for MAKE_CLOSURE.

In the 2.5 development cycle, MAKE_CLOSURE as changed to take free
variables as a tuple rather than as individual items on the stack.
Closes patch #1534084.
üst 45381938
...@@ -382,16 +382,7 @@ class CodeGenerator: ...@@ -382,16 +382,7 @@ class CodeGenerator:
self.set_lineno(node) self.set_lineno(node)
for default in node.defaults: for default in node.defaults:
self.visit(default) self.visit(default)
frees = gen.scope.get_free_vars() self._makeClosure(gen, len(node.defaults))
if frees:
for name in frees:
self.emit('LOAD_CLOSURE', name)
self.emit('LOAD_CONST', gen)
self.emit('MAKE_CLOSURE', len(node.defaults))
else:
self.emit('LOAD_CONST', gen)
self.emit('MAKE_FUNCTION', len(node.defaults))
for i in range(ndecorators): for i in range(ndecorators):
self.emit('CALL_FUNCTION', 1) self.emit('CALL_FUNCTION', 1)
...@@ -405,14 +396,7 @@ class CodeGenerator: ...@@ -405,14 +396,7 @@ class CodeGenerator:
for base in node.bases: for base in node.bases:
self.visit(base) self.visit(base)
self.emit('BUILD_TUPLE', len(node.bases)) self.emit('BUILD_TUPLE', len(node.bases))
frees = gen.scope.get_free_vars() self._makeClosure(gen, 0)
for name in frees:
self.emit('LOAD_CLOSURE', name)
self.emit('LOAD_CONST', gen)
if frees:
self.emit('MAKE_CLOSURE', 0)
else:
self.emit('MAKE_FUNCTION', 0)
self.emit('CALL_FUNCTION', 0) self.emit('CALL_FUNCTION', 0)
self.emit('BUILD_CLASS') self.emit('BUILD_CLASS')
self.storeName(node.name) self.storeName(node.name)
...@@ -644,22 +628,25 @@ class CodeGenerator: ...@@ -644,22 +628,25 @@ class CodeGenerator:
self.newBlock() self.newBlock()
self.emit('POP_TOP') self.emit('POP_TOP')
def visitGenExpr(self, node): def _makeClosure(self, gen, args):
gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
self.get_module())
walk(node.code, gen)
gen.finish()
self.set_lineno(node)
frees = gen.scope.get_free_vars() frees = gen.scope.get_free_vars()
if frees: if frees:
for name in frees: for name in frees:
self.emit('LOAD_CLOSURE', name) self.emit('LOAD_CLOSURE', name)
self.emit('BUILD_TUPLE', len(frees))
self.emit('LOAD_CONST', gen) self.emit('LOAD_CONST', gen)
self.emit('MAKE_CLOSURE', 0) self.emit('MAKE_CLOSURE', args)
else: else:
self.emit('LOAD_CONST', gen) self.emit('LOAD_CONST', gen)
self.emit('MAKE_FUNCTION', 0) self.emit('MAKE_FUNCTION', args)
def visitGenExpr(self, node):
gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
self.get_module())
walk(node.code, gen)
gen.finish()
self.set_lineno(node)
self._makeClosure(gen, 0)
# precomputation of outmost iterable # precomputation of outmost iterable
self.visit(node.code.quals[0].iter) self.visit(node.code.quals[0].iter)
self.emit('GET_ITER') self.emit('GET_ITER')
......
...@@ -104,6 +104,19 @@ class CompilerTest(unittest.TestCase): ...@@ -104,6 +104,19 @@ class CompilerTest(unittest.TestCase):
self.assertEquals(flatten([1, [2]]), [1, 2]) self.assertEquals(flatten([1, [2]]), [1, 2])
self.assertEquals(flatten((1, (2,))), [1, 2]) self.assertEquals(flatten((1, (2,))), [1, 2])
def testNestedScope(self):
c = compiler.compile('def g():\n'
' a = 1\n'
' def f(): return a + 2\n'
' return f()\n'
'result = g()',
'<string>',
'exec')
dct = {}
exec c in dct
self.assertEquals(dct.get('result'), 3)
NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard) NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard)
############################################################################### ###############################################################################
......
...@@ -28,6 +28,9 @@ Library ...@@ -28,6 +28,9 @@ Library
- Bug #1531405, format_exception no longer raises an exception if - Bug #1531405, format_exception no longer raises an exception if
str(exception) raised an exception. str(exception) raised an exception.
- Fix a bug in the ``compiler`` package that caused invalid code to be
generated for nested functions.
Extension Modules Extension Modules
----------------- -----------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment