# HG changeset patch # User Paul Boddie # Date 1385744939 -3600 # Node ID c53bbfded454f713326b3205459e3b1d08d4f2aa # Parent d905247ced6d2dd64b96f36f12601723a8ec0941 Fixed the scope of defaults and added the setdefaults special function for the initialisation of defaults for non-dynamic functions. diff -r d905247ced6d -r c53bbfded454 docs/syspython.txt --- a/docs/syspython.txt Fri Nov 29 01:38:25 2013 +0100 +++ b/docs/syspython.txt Fri Nov 29 18:08:59 2013 +0100 @@ -166,9 +166,9 @@ ... if something: - storelocal(inner, static(outer.inner)) + storelocal(inner, static(module.outer.inner)) else: - storelocal(inner, static("outer.inner#2")) + storelocal(inner, static("module.outer.inner#2")) return inner Where functions are dynamic - that is they have additional state associated @@ -189,7 +189,7 @@ def inner(__context__, y, z=x): localnames(__context__, y, z) ... - storelocal(inner, makedynamic(static(outer.inner), x)) + storelocal(inner, makedynamic(static(module.outer.inner), x)) return inner The special makedynamic invocation creates an object referring to the function @@ -199,6 +199,21 @@ to any default information that needs to be transferred to the local namespace. +Function defaults that do not require a dynamic function are initialised using +the setdefaults special function as follows: + + class C: + const = ... + def f(a, b=const): + ... + + ... + setdefaults(module.f, module.C.const) + +Where multiple definitions of a name are involved, setdefaults may also be +used in a store operation and can be assumed to return a reference to the +function whose defaults are being set. + Imports ------- diff -r d905247ced6d -r c53bbfded454 micropython/syspython.py --- a/micropython/syspython.py Fri Nov 29 01:38:25 2013 +0100 +++ b/micropython/syspython.py Fri Nov 29 18:08:59 2013 +0100 @@ -387,32 +387,41 @@ if not used_by_unit(node): return compiler.ast.Stmt([]) - self.units.append(node.unit) + if not self.processing_definition(node): - try: - if not self.processing_definition(node): - - # Generate rebindings of functions where multiple definitions - # exist within a scope. Also generate dynamic function object - # initialisation. + # Generate rebindings of functions where multiple definitions + # exist within a scope. Also generate dynamic function object + # initialisation. - fn = node.unit - if fn.name == fn.original_name and not fn.is_dynamic(): - return compiler.ast.Stmt([]) - else: - if fn.is_dynamic(): - ref = compiler.ast.CallFunc( - special_name("makedynamic"), - [quoted_ref(fn)] + fn.defaults - ) - else: - ref = quoted_ref(fn) + fn = node.unit + if fn.is_dynamic(): + ref = compiler.ast.CallFunc( + special_name("makedynamic"), + [quoted_ref(fn)] + [self.dispatch(n) for n in fn.defaults] + ) + elif fn.defaults: + ref = compiler.ast.CallFunc( + special_name("setdefaults"), + [quoted_ref(fn)] + [self.dispatch(n) for n in fn.defaults] + ) + if fn.name == fn.original_name: + return ref + elif fn.name == fn.original_name: + return compiler.ast.Stmt([]) + else: + ref = quoted_ref(fn) - return self.store_value(fn.parent, "local", fn.original_name, ref) - else: + return self.store_value(fn.parent, "local", fn.original_name, ref) + + # Where this function is being processed, visit the definition in its + # entirety. + + else: + self.units.append(node.unit) + try: return self._visitFunctionDefinition(node) - finally: - self.units.pop() + finally: + self.units.pop() def _visitFunctionDefinition(self, node): fn = node.unit @@ -440,8 +449,6 @@ definitions = self.process_definitions(node) self.current_definition = current - defaults = [self.dispatch(n) for n in node.defaults] - # NOTE: Any required defaults should be copied into the local namespace # NOTE: using the __context__ reference to the instance of the function. @@ -449,7 +456,7 @@ code = self.dispatch(node.code) - return compiler.ast.Function(node.decorators, node.name, node.argnames, defaults, node.flags, node.doc, + return compiler.ast.Function(node.decorators, node.name, node.argnames, node.defaults, node.flags, node.doc, compiler.ast.Stmt(localnames + globalnames + definitions + code.nodes)) visitGlobal = NOP