# HG changeset patch # User Paul Boddie # Date 1389626935 -3600 # Node ID a85708b59d14a533ab862c6e34e206d0ec51d91f # Parent dad7378cb29e7323669d1ec4151cf0b3df05d3be Added closure usage detection. diff -r dad7378cb29e -r a85708b59d14 micropython/data.py --- a/micropython/data.py Mon Dec 09 14:56:11 2013 +0100 +++ b/micropython/data.py Mon Jan 13 16:28:55 2014 +0100 @@ -7,7 +7,7 @@ program but which are wrapped in context-dependent structures in the running program. -Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Paul Boddie +Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -95,10 +95,17 @@ self.module = module self.namespace = {} + self.parent_namespaces = [] self.globals = set() self.lambdas = {} # only really useful for functions self.finalised = False + def set_parent_namespaces(self, namespaces): + self.parent_namespaces = namespaces + + def get_parent_namespaces(self): + return self.parent_namespaces + # Attribute/name definition and access. def __delitem__(self, name): @@ -214,23 +221,29 @@ # Locals. - elif not external and self.has_key(name): + if not external and self.has_key(name): return self[name], "local", self.full_name() + # Outer scopes. + + for outer in self.parent_namespaces[::-1]: + if outer.has_key(name): + print >>sys.stderr, "Warning: name %r in namespace %r is provided by an outer scope: %r" % (name, self.full_name(), outer.full_name()) + return outer[name], "outer", outer.full_name() + # Globals. - elif module and module is not self and module.has_key(name): + if module and module is not self and module.has_key(name): return module[name], "global", module.full_name() # Builtins. - elif builtins and builtins.has_key(name): + if builtins and builtins.has_key(name): return builtins[name], "builtins", builtins.full_name() # Unknown. - else: - return None, None, None + return None, None, None # Attribute definition methods. diff -r dad7378cb29e -r a85708b59d14 micropython/inspect.py --- a/micropython/inspect.py Mon Dec 09 14:56:11 2013 +0100 +++ b/micropython/inspect.py Mon Jan 13 16:28:55 2014 +0100 @@ -3,7 +3,7 @@ """ Inspect source files, obtaining details of classes and attributes. -Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Paul Boddie +Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -197,9 +197,9 @@ # the end of self.functions and are thus visited as the iteration # reaches the end of the original list. - for node, namespaces in self.functions: - self._visitFunctionBody(node, namespaces) - namespaces[-1].finalise_attribute_usage() + for node in self.functions: + self._visitFunctionBody(node) + node.unit.finalise_attribute_usage() def process_structure(self, node): @@ -808,7 +808,8 @@ # Record the namespace context of the function for later processing. - self.functions.append((node, self.namespaces + [function])) + function.set_parent_namespaces(self.namespaces[:]) + self.functions.append(node) # Store the function. @@ -823,10 +824,13 @@ function.make_dynamic() return function - def _visitFunctionBody(self, node, namespaces): + def _visitFunctionBody(self, node): "Enter the function." + function = node.unit + namespaces = function.get_parent_namespaces() + [function] + # Current namespace is the function. # Previous namespace is the class. diff -r dad7378cb29e -r a85708b59d14 tests/outer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/outer.py Mon Jan 13 16:28:55 2014 +0100 @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +def f(a): + def g(): + return a + return g + +result_1 = f(1)() +result_2 = f(2)() + +# vim: tabstop=4 expandtab shiftwidth=4