1.1 --- a/micropython/inspect.py Sun Jun 06 03:03:09 2010 +0200
1.2 +++ b/micropython/inspect.py Sun Jun 06 15:27:50 2010 +0200
1.3 @@ -67,8 +67,9 @@
1.4
1.5 Assignments to names within functions are not generally considered to cause the
1.6 targets of such assignments to provide constant values since functions can be
1.7 -invoked many times with different inputs. However, there may be benefits in
1.8 -considering a local to be constant within a single invocation.
1.9 +invoked many times with different inputs. This affects particularly the
1.10 +definition of functions or lambdas within functions. However, there may be
1.11 +benefits in considering a local to be constant within a single invocation.
1.12 """
1.13
1.14 from micropython.common import *
1.15 @@ -111,6 +112,7 @@
1.16
1.17 self.in_init = 0 # Find instance attributes in __init__ methods.
1.18 self.in_method = 0 # Find instance attributes in all methods.
1.19 + self.in_function = 0 # Note function presence, affecting definitions.
1.20 self.in_loop = 0 # Note loop "membership", affecting assignments.
1.21 self.namespaces = []
1.22 self.module = None
1.23 @@ -440,6 +442,7 @@
1.24 node.defaults,
1.25 (node.flags & 4 != 0),
1.26 (node.flags & 8 != 0),
1.27 + self.in_loop or self.in_function,
1.28 self,
1.29 node
1.30 )
1.31 @@ -467,19 +470,8 @@
1.32
1.33 # Test the defaults and assess whether an dynamic object will result.
1.34
1.35 - if function.make_dynamic():
1.36 -
1.37 - # Forbid dynamic methods, since the context of methods is the
1.38 - # instance itself.
1.39 -
1.40 - if self.in_class():
1.41 - raise InspectError(self.full_name(), node, "Methods cannot define dynamic defaults.")
1.42 -
1.43 - result = Instance() # indicates no known target
1.44 - else:
1.45 - result = function
1.46 -
1.47 - return result
1.48 + function.make_dynamic()
1.49 + return function
1.50
1.51 def _visitFunctionBody(self, node, namespaces):
1.52
1.53 @@ -493,9 +485,16 @@
1.54 self.in_init = 1
1.55 self.in_method = 1
1.56
1.57 + in_function = self.in_function
1.58 + in_loop = self.in_loop
1.59 + self.in_function = 1
1.60 + self.in_loop = 0
1.61 +
1.62 self.namespaces = namespaces
1.63 self.dispatch(node.code)
1.64
1.65 + self.in_loop = in_loop
1.66 + self.in_function = in_function
1.67 self.in_init = 0
1.68 self.in_method = 0
1.69
1.70 @@ -610,6 +609,9 @@
1.71 print "Class %r in %r is not global: ignored." % (node.name, self.namespaces[-1].full_name())
1.72 return None
1.73 else:
1.74 + if self.in_loop:
1.75 + print "Warning: class %r in %r defined in a loop." % (node.name, self.full_name())
1.76 +
1.77 cls = Class(node.name, self.get_namespace(), self, node)
1.78
1.79 # Visit the base class expressions, attempting to find concrete
1.80 @@ -711,6 +713,7 @@
1.81 self.use_name("__iter__", node.list)
1.82 self.use_name("next")
1.83
1.84 + in_loop = self.in_loop
1.85 self.in_loop = 1
1.86 self.dispatch(node.assign)
1.87 self.dispatch(node.list)
1.88 @@ -721,7 +724,7 @@
1.89 self.new_branch()
1.90 self.dispatch(node.body)
1.91 self.shelve_branch()
1.92 - self.in_loop = 0
1.93 + self.in_loop = in_loop
1.94
1.95 # Maintain a branch for the else clause or the current retained usage
1.96 # where execution avoids the conditional clauses.
1.97 @@ -1000,12 +1003,13 @@
1.98
1.99 # Propagate attribute usage to branches.
1.100
1.101 + in_loop = self.in_loop
1.102 self.in_loop = 1
1.103 self.dispatch(node.test)
1.104 self.new_branch(node)
1.105 self.dispatch(node.body)
1.106 self.shelve_branch()
1.107 - self.in_loop = 0
1.108 + self.in_loop = in_loop
1.109
1.110 # Maintain a branch for the else clause or the current retained usage
1.111 # where execution avoids the conditional clauses.