# HG changeset patch # User Paul Boddie # Date 1385650179 -3600 # Node ID 4fec4d70b1f2f60fc717646db56087ff092b5de4 # Parent f2a948d357c9e758a80002ae63ec1de7f1629cda Improved handling of nested functions (also affecting lambdas), also excluding the special "" argument from report and syspython output. diff -r f2a948d357c9 -r 4fec4d70b1f2 micropython/common.py --- a/micropython/common.py Mon Nov 25 15:03:12 2013 +0100 +++ b/micropython/common.py Thu Nov 28 15:49:39 2013 +0100 @@ -47,11 +47,14 @@ definitions = [] for n in node.getChildNodes(): if isinstance(n, (compiler.ast.Class, compiler.ast.Function)): + self.current_definition = n definitions.append(self.dispatch(n)) - else: - definitions += self.process_definitions(n) + definitions += self.process_definitions(n) return definitions + def processing_definition(self, n): + return self.current_definition is n + # Visitor support methods. def default(self, node, *args): diff -r f2a948d357c9 -r 4fec4d70b1f2 micropython/report.py --- a/micropython/report.py Mon Nov 25 15:03:12 2013 +0100 +++ b/micropython/report.py Thu Nov 28 15:49:39 2013 +0100 @@ -1493,6 +1493,14 @@ if not first: self.stream.write(", ") + # NOTE: The special context argument should not be reproduced. + # NOTE: For "dynamic" functions, the context is used to access + # NOTE: things like defaults, but could be extended for closures to + # NOTE: refer to many namespaces. + + elif param == "": + continue + # Handle tuple parameters. if isinstance(param, tuple): diff -r f2a948d357c9 -r 4fec4d70b1f2 micropython/syspython.py --- a/micropython/syspython.py Mon Nov 25 15:03:12 2013 +0100 +++ b/micropython/syspython.py Thu Nov 28 15:49:39 2013 +0100 @@ -70,7 +70,7 @@ self.module = module self.program = program self.objtable = program.get_object_table() - self.in_main = False + self.current_definition = None self.units = [] def get_unit(self): @@ -86,6 +86,18 @@ module = self.dispatch(self.module.astnode) stream.write(str(module)) + def get_original_arguments(self, argnames): + + # NOTE: The special context argument should not be reproduced. + # NOTE: For "dynamic" functions, the context is used to access + # NOTE: things like defaults, but could be extended for closures to + # NOTE: refer to many namespaces. + + if argnames and argnames[0] == "": + return argnames[1:] + else: + return argnames + def NOP(self, node): return node @@ -94,6 +106,7 @@ self.units.append(module) definitions = self.process_definitions(node) + self.current_definition = None # keywords(name, ...) @@ -116,14 +129,11 @@ # def __main__(): # ... - self.in_main = True - main = compiler.ast.Function( [], "__main__", [], [], 0, "Module initialisation.", compiler.ast.Stmt(globalnames + self.dispatch(node.node).nodes) ) - self.in_main = False self.units.pop() return compiler.ast.Module(node.doc, compiler.ast.Stmt(keywords + definitions + [main])) @@ -163,7 +173,7 @@ try: # Incorporate class body code in the main function. - if self.in_main: + if not self.processing_definition(node): return self.dispatch(node.code) else: return self._visitClassDefinition(node) @@ -332,7 +342,10 @@ self.units.append(node.unit) try: - if self.in_main: + # NOTE: Need to initialise any defaults outside a definition and to + # NOTE: transfer defaults to locals inside a definition. + + if not self.processing_definition(node): # Generate rebindings of functions. @@ -375,8 +388,9 @@ # NOTE: Should generate guards for attribute usage operations. code = self.dispatch(node.code) + argnames = self.get_original_arguments(node.argnames) - return compiler.ast.Function(node.decorators, node.name, node.argnames, defaults, node.flags, node.doc, + return compiler.ast.Function(node.decorators, node.name, argnames, defaults, node.flags, node.doc, compiler.ast.Stmt(localnames + globalnames + code.nodes)) visitGlobal = NOP @@ -892,9 +906,13 @@ def visitLambda(self, node): self.units.append(node.unit) + # NOTE: Need to initialise any defaults. + try: + argnames = self.get_original_arguments(node.argnames) + return compiler.ast.Lambda( - node.argnames, + argnames, [self.dispatch(n) for n in node.defaults], node.flags, self.dispatch(node.code) diff -r f2a948d357c9 -r 4fec4d70b1f2 tests/call_func_default_nested.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/call_func_default_nested.py Thu Nov 28 15:49:39 2013 +0100 @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +def outer(x): + def inner(y, z=x): + return y + z + return inner + +result_3 = outer(1)(2) +result_4 = outer(2)(2) + +# vim: tabstop=4 expandtab shiftwidth=4