1.1 --- a/micropython/inspect.py Fri Nov 06 01:07:48 2009 +0100
1.2 +++ b/micropython/inspect.py Fri Nov 06 01:17:07 2009 +0100
1.3 @@ -293,7 +293,7 @@
1.4
1.5 self.namespaces[-2].add_instance_attribute(name)
1.6
1.7 - def get_parent(self):
1.8 + def get_namespace(self):
1.9
1.10 "Return the parent (or most recent) namespace currently exposed."
1.11
1.12 @@ -303,9 +303,30 @@
1.13
1.14 "Use the given 'name' within the current namespace/unit."
1.15
1.16 - unit = self.get_parent()
1.17 + unit = self.get_namespace()
1.18 self.importer.use_name(name, unit.name)
1.19
1.20 + def new_branchpoint(self):
1.21 + self.get_namespace()._new_branchpoint()
1.22 +
1.23 + def new_branch(self):
1.24 + self.get_namespace()._new_branch()
1.25 +
1.26 + def shelve_branch(self):
1.27 + self.get_namespace()._shelve_branch()
1.28 +
1.29 + def merge_branches(self):
1.30 + self.get_namespace()._merge_branches()
1.31 +
1.32 + def reset_attributes(self, name):
1.33 + self.get_namespace()._reset_attributes(name)
1.34 +
1.35 + def reset_all_attributes(self):
1.36 + self.get_namespace()._reset_all_attributes()
1.37 +
1.38 + def use_attribute(self, attr, attrname):
1.39 + return self.get_namespace()._use_attribute(attr, attrname)
1.40 +
1.41 # Visitor methods.
1.42
1.43 def default(self, node, *args):
1.44 @@ -353,7 +374,7 @@
1.45
1.46 function = Function(
1.47 name,
1.48 - self.get_parent(),
1.49 + self.get_namespace(),
1.50 node.argnames,
1.51 node.defaults,
1.52 (node.flags & 4 != 0),
1.53 @@ -437,7 +458,8 @@
1.54
1.55 # Note usage of the attribute.
1.56
1.57 - node._attrnames = expr.use_attribute(node.attrname)
1.58 + if expr.parent is self.get_namespace():
1.59 + node._attrnames = self.use_attribute(expr, node.attrname)
1.60
1.61 return None
1.62
1.63 @@ -459,6 +481,7 @@
1.64 raise InspectError(self.full_name(), node, "Deletion of attribute %r is not supported." % node.name)
1.65
1.66 self.store(node.name, self.expr)
1.67 + self.reset_attributes(node.name)
1.68 self.use_name(node.name)
1.69 return None
1.70
1.71 @@ -497,7 +520,8 @@
1.72
1.73 visitBitxor = _visitBinary
1.74
1.75 - visitBreak = NOP
1.76 + def visitBreak(self, node):
1.77 + self.reset_all_attributes()
1.78
1.79 visitCallFunc = OP
1.80
1.81 @@ -512,7 +536,7 @@
1.82 print "Class %r in %r is not global: ignored." % (node.name, self.namespaces[-1].full_name())
1.83 return None
1.84 else:
1.85 - cls = Class(node.name, self.get_parent(), self, node)
1.86 + cls = Class(node.name, self.get_namespace(), self, node)
1.87
1.88 # Visit the base class expressions, attempting to find concrete
1.89 # definitions of classes.
1.90 @@ -576,7 +600,8 @@
1.91 self.use_name(self.importer.get_constant_type_name(node.value))
1.92 return self.importer.make_constant(node.value)
1.93
1.94 - visitContinue = NOP
1.95 + def visitContinue(self, node):
1.96 + self.reset_all_attributes()
1.97
1.98 visitDecorators = NOP
1.99
1.100 @@ -595,17 +620,34 @@
1.101 visitFloorDiv = _visitBinary
1.102
1.103 def visitFor(self, node):
1.104 + self.new_branchpoint()
1.105
1.106 # Declare names which will be used by generated code.
1.107
1.108 self.use_name("__iter__")
1.109 self.use_name("next")
1.110
1.111 + self.dispatch(node.assign)
1.112 + self.dispatch(node.list)
1.113 +
1.114 # Enter the loop.
1.115 + # Propagate attribute usage to branches.
1.116
1.117 self.in_loop = 1
1.118 - self.NOP(node)
1.119 + self.new_branch()
1.120 + self.dispatch(node.body)
1.121 + self.shelve_branch()
1.122 self.in_loop = 0
1.123 +
1.124 + # Maintain a branch for the else clause or the current retained usage
1.125 + # where execution avoids the conditional clauses.
1.126 +
1.127 + self.new_branch()
1.128 + if node.else_ is not None:
1.129 + self.dispatch(node.else_)
1.130 + self.shelve_branch()
1.131 +
1.132 + self.merge_branches()
1.133 return None
1.134
1.135 def visitFrom(self, node):
1.136 @@ -664,7 +706,8 @@
1.137
1.138 # Note usage of the attribute.
1.139
1.140 - node._attrnames = expr.use_attribute(node.attrname)
1.141 + if expr.parent is self.get_namespace():
1.142 + node._attrnames = self.use_attribute(expr, attrname)
1.143
1.144 elif self.builtins is not None:
1.145 attr = self.builtins.get(attrname)
1.146 @@ -687,11 +730,26 @@
1.147 # The name is recorded in an earlier process.
1.148
1.149 def visitIf(self, node):
1.150 + self.new_branchpoint()
1.151 +
1.152 + # Propagate attribute usage to branches.
1.153 +
1.154 for test, body in node.tests:
1.155 self.dispatch(test)
1.156 +
1.157 + self.new_branch()
1.158 self.dispatch(body)
1.159 + self.shelve_branch()
1.160 +
1.161 + # Maintain a branch for the else clause or the current retained usage
1.162 + # where execution avoids the conditional clauses.
1.163 +
1.164 + self.new_branch()
1.165 if node.else_ is not None:
1.166 self.dispatch(node.else_)
1.167 + self.shelve_branch()
1.168 +
1.169 + self.merge_branches()
1.170 return None
1.171
1.172 visitIfExp = NOP
1.173 @@ -792,7 +850,11 @@
1.174
1.175 def visitTryExcept(self, node):
1.176 self.dispatch(node.body)
1.177 +
1.178 + self.new_branchpoint()
1.179 +
1.180 for name, var, n in node.handlers:
1.181 + self.new_branch()
1.182
1.183 # Establish the local for the handler.
1.184
1.185 @@ -800,8 +862,15 @@
1.186 self.dispatch(var)
1.187 if n is not None:
1.188 self.dispatch(n)
1.189 +
1.190 + self.shelve_branch()
1.191 +
1.192 if node.else_ is not None:
1.193 + self.new_branch()
1.194 self.dispatch(node.else_)
1.195 + self.shelve_branch()
1.196 +
1.197 + self.merge_branches()
1.198 return None
1.199
1.200 visitTryFinally = NOP
1.201 @@ -813,9 +882,26 @@
1.202 visitUnarySub = _visitUnary
1.203
1.204 def visitWhile(self, node):
1.205 + self.new_branchpoint()
1.206 +
1.207 + # Propagate attribute usage to branches.
1.208 +
1.209 self.in_loop = 1
1.210 - self.NOP(node)
1.211 + self.dispatch(node.test)
1.212 + self.new_branch()
1.213 + self.dispatch(node.body)
1.214 + self.shelve_branch()
1.215 self.in_loop = 0
1.216 +
1.217 + # Maintain a branch for the else clause or the current retained usage
1.218 + # where execution avoids the conditional clauses.
1.219 +
1.220 + self.new_branch()
1.221 + if node.else_ is not None:
1.222 + self.dispatch(node.else_)
1.223 + self.shelve_branch()
1.224 +
1.225 + self.merge_branches()
1.226 return None
1.227
1.228 visitWith = NOP