[Python-checkins] r51109 - in python/trunk: Lib/compiler/pycodegen.py Lib/test/test_compiler.py Misc/NEWS
neil.schemenauer
python-checkins at python.org
Fri Aug 4 18:20:31 CEST 2006
Author: neil.schemenauer
Date: Fri Aug 4 18:20:30 2006
New Revision: 51109
Modified:
python/trunk/Lib/compiler/pycodegen.py
python/trunk/Lib/test/test_compiler.py
python/trunk/Misc/NEWS
Log:
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.
Modified: python/trunk/Lib/compiler/pycodegen.py
==============================================================================
--- python/trunk/Lib/compiler/pycodegen.py (original)
+++ python/trunk/Lib/compiler/pycodegen.py Fri Aug 4 18:20:30 2006
@@ -382,16 +382,7 @@
self.set_lineno(node)
for default in node.defaults:
self.visit(default)
- frees = gen.scope.get_free_vars()
- 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))
-
+ self._makeClosure(gen, len(node.defaults))
for i in range(ndecorators):
self.emit('CALL_FUNCTION', 1)
@@ -405,14 +396,7 @@
for base in node.bases:
self.visit(base)
self.emit('BUILD_TUPLE', len(node.bases))
- frees = gen.scope.get_free_vars()
- 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._makeClosure(gen, 0)
self.emit('CALL_FUNCTION', 0)
self.emit('BUILD_CLASS')
self.storeName(node.name)
@@ -644,22 +628,25 @@
self.newBlock()
self.emit('POP_TOP')
- 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)
+ def _makeClosure(self, gen, args):
frees = gen.scope.get_free_vars()
if frees:
for name in frees:
self.emit('LOAD_CLOSURE', name)
+ self.emit('BUILD_TUPLE', len(frees))
self.emit('LOAD_CONST', gen)
- self.emit('MAKE_CLOSURE', 0)
+ self.emit('MAKE_CLOSURE', args)
else:
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
self.visit(node.code.quals[0].iter)
self.emit('GET_ITER')
Modified: python/trunk/Lib/test/test_compiler.py
==============================================================================
--- python/trunk/Lib/test/test_compiler.py (original)
+++ python/trunk/Lib/test/test_compiler.py Fri Aug 4 18:20:30 2006
@@ -104,6 +104,19 @@
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)
###############################################################################
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS (original)
+++ python/trunk/Misc/NEWS Fri Aug 4 18:20:30 2006
@@ -28,6 +28,9 @@
- Bug #1531405, format_exception no longer raises an exception if
str(exception) raised an exception.
+- Fix a bug in the ``compiler`` package that caused invalid code to be
+ generated for nested functions.
+
Extension Modules
-----------------
More information about the Python-checkins
mailing list