1.1 --- a/micropython/data.py Mon Dec 09 14:56:11 2013 +0100
1.2 +++ b/micropython/data.py Mon Jan 13 16:28:55 2014 +0100
1.3 @@ -7,7 +7,7 @@
1.4 program but which are wrapped in context-dependent structures in the running
1.5 program.
1.6
1.7 -Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -95,10 +95,17 @@
1.13
1.14 self.module = module
1.15 self.namespace = {}
1.16 + self.parent_namespaces = []
1.17 self.globals = set()
1.18 self.lambdas = {} # only really useful for functions
1.19 self.finalised = False
1.20
1.21 + def set_parent_namespaces(self, namespaces):
1.22 + self.parent_namespaces = namespaces
1.23 +
1.24 + def get_parent_namespaces(self):
1.25 + return self.parent_namespaces
1.26 +
1.27 # Attribute/name definition and access.
1.28
1.29 def __delitem__(self, name):
1.30 @@ -214,23 +221,29 @@
1.31
1.32 # Locals.
1.33
1.34 - elif not external and self.has_key(name):
1.35 + if not external and self.has_key(name):
1.36 return self[name], "local", self.full_name()
1.37
1.38 + # Outer scopes.
1.39 +
1.40 + for outer in self.parent_namespaces[::-1]:
1.41 + if outer.has_key(name):
1.42 + print >>sys.stderr, "Warning: name %r in namespace %r is provided by an outer scope: %r" % (name, self.full_name(), outer.full_name())
1.43 + return outer[name], "outer", outer.full_name()
1.44 +
1.45 # Globals.
1.46
1.47 - elif module and module is not self and module.has_key(name):
1.48 + if module and module is not self and module.has_key(name):
1.49 return module[name], "global", module.full_name()
1.50
1.51 # Builtins.
1.52
1.53 - elif builtins and builtins.has_key(name):
1.54 + if builtins and builtins.has_key(name):
1.55 return builtins[name], "builtins", builtins.full_name()
1.56
1.57 # Unknown.
1.58
1.59 - else:
1.60 - return None, None, None
1.61 + return None, None, None
1.62
1.63 # Attribute definition methods.
1.64
2.1 --- a/micropython/inspect.py Mon Dec 09 14:56:11 2013 +0100
2.2 +++ b/micropython/inspect.py Mon Jan 13 16:28:55 2014 +0100
2.3 @@ -3,7 +3,7 @@
2.4 """
2.5 Inspect source files, obtaining details of classes and attributes.
2.6
2.7 -Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Paul Boddie <paul@boddie.org.uk>
2.8 +Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Paul Boddie <paul@boddie.org.uk>
2.9
2.10 This program is free software; you can redistribute it and/or modify it under
2.11 the terms of the GNU General Public License as published by the Free Software
2.12 @@ -197,9 +197,9 @@
2.13 # the end of self.functions and are thus visited as the iteration
2.14 # reaches the end of the original list.
2.15
2.16 - for node, namespaces in self.functions:
2.17 - self._visitFunctionBody(node, namespaces)
2.18 - namespaces[-1].finalise_attribute_usage()
2.19 + for node in self.functions:
2.20 + self._visitFunctionBody(node)
2.21 + node.unit.finalise_attribute_usage()
2.22
2.23 def process_structure(self, node):
2.24
2.25 @@ -808,7 +808,8 @@
2.26
2.27 # Record the namespace context of the function for later processing.
2.28
2.29 - self.functions.append((node, self.namespaces + [function]))
2.30 + function.set_parent_namespaces(self.namespaces[:])
2.31 + self.functions.append(node)
2.32
2.33 # Store the function.
2.34
2.35 @@ -823,10 +824,13 @@
2.36 function.make_dynamic()
2.37 return function
2.38
2.39 - def _visitFunctionBody(self, node, namespaces):
2.40 + def _visitFunctionBody(self, node):
2.41
2.42 "Enter the function."
2.43
2.44 + function = node.unit
2.45 + namespaces = function.get_parent_namespaces() + [function]
2.46 +
2.47 # Current namespace is the function.
2.48 # Previous namespace is the class.
2.49
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/tests/outer.py Mon Jan 13 16:28:55 2014 +0100
3.3 @@ -0,0 +1,11 @@
3.4 +#!/usr/bin/env python
3.5 +
3.6 +def f(a):
3.7 + def g():
3.8 + return a
3.9 + return g
3.10 +
3.11 +result_1 = f(1)()
3.12 +result_2 = f(2)()
3.13 +
3.14 +# vim: tabstop=4 expandtab shiftwidth=4