1.1 --- a/micropython/inspect.py Sun Oct 25 18:35:53 2009 +0100
1.2 +++ b/micropython/inspect.py Sat Oct 31 22:59:35 2009 +0100
1.3 @@ -286,7 +286,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 @@ -296,9 +296,27 @@
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 use_attribute(self, attr, attrname):
1.36 + self.get_namespace()._use_attribute(attr, attrname)
1.37 +
1.38 # Visitor methods.
1.39
1.40 def default(self, node, *args):
1.41 @@ -346,7 +364,7 @@
1.42
1.43 function = Function(
1.44 name,
1.45 - self.get_parent(),
1.46 + self.get_namespace(),
1.47 node.argnames,
1.48 node.defaults,
1.49 (node.flags & 4 != 0),
1.50 @@ -417,6 +435,9 @@
1.51
1.52 def visitAssAttr(self, node):
1.53 expr = self.dispatch(node.expr)
1.54 +
1.55 + # Record the attribute on the presumed target.
1.56 +
1.57 if isinstance(expr, Attr):
1.58 if expr.name == "self":
1.59 if not self.store_class_attr(node.attrname):
1.60 @@ -424,6 +445,12 @@
1.61 elif isinstance(expr.get_value(), Module):
1.62 self.store_module_attr(node.attrname, expr.get_value())
1.63 print "Warning: attribute %r of module %r set outside the module." % (node.attrname, expr.get_value().name)
1.64 +
1.65 + # Note usage of the attribute.
1.66 +
1.67 + if expr.parent is self.get_namespace():
1.68 + self.use_attribute(expr, node.attrname)
1.69 +
1.70 return None
1.71
1.72 def visitAssList(self, node):
1.73 @@ -441,6 +468,7 @@
1.74
1.75 def visitAssName(self, node):
1.76 self.store(node.name, self.expr)
1.77 + self.reset_attributes(node.name)
1.78 self.use_name(node.name)
1.79 return None
1.80
1.81 @@ -494,7 +522,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 @@ -577,17 +605,30 @@
1.91 visitFloorDiv = _visitBinary
1.92
1.93 def visitFor(self, node):
1.94 + self.new_branchpoint()
1.95
1.96 # Declare names which will be used by generated code.
1.97
1.98 self.use_name("__iter__")
1.99 self.use_name("next")
1.100
1.101 + self.dispatch(node.assign)
1.102 + self.dispatch(node.list)
1.103 +
1.104 # Enter the loop.
1.105
1.106 self.in_loop = 1
1.107 - self.NOP(node)
1.108 + self.new_branch()
1.109 + self.dispatch(node.body)
1.110 + self.shelve_branch()
1.111 self.in_loop = 0
1.112 +
1.113 + if node.else_ is not None:
1.114 + self.new_branch()
1.115 + self.dispatch(node.else_)
1.116 + self.shelve_branch()
1.117 +
1.118 + self.merge_branches()
1.119 return None
1.120
1.121 def visitFrom(self, node):
1.122 @@ -633,6 +674,8 @@
1.123 expr = self.dispatch(node.expr)
1.124 attrname = node.attrname
1.125
1.126 + # Attempt to identify the nature of the attribute.
1.127 +
1.128 if isinstance(expr, Attr):
1.129 value = expr.get_value()
1.130 if isinstance(value, (Class, Module)):
1.131 @@ -641,6 +684,12 @@
1.132 attr = UnresolvedName(attrname, value.full_name(), self)
1.133 else:
1.134 attr = None
1.135 +
1.136 + # Note usage of the attribute.
1.137 +
1.138 + if expr.parent is self.get_namespace():
1.139 + self.use_attribute(expr, attrname)
1.140 +
1.141 elif self.builtins is not None:
1.142 attr = self.builtins.get(attrname)
1.143 else:
1.144 @@ -662,11 +711,21 @@
1.145 # The name is recorded in an earlier process.
1.146
1.147 def visitIf(self, node):
1.148 + self.new_branchpoint()
1.149 +
1.150 for test, body in node.tests:
1.151 self.dispatch(test)
1.152 +
1.153 + self.new_branch()
1.154 self.dispatch(body)
1.155 + self.shelve_branch()
1.156 +
1.157 if node.else_ is not None:
1.158 + self.new_branch()
1.159 self.dispatch(node.else_)
1.160 + self.shelve_branch()
1.161 +
1.162 + self.merge_branches()
1.163 return None
1.164
1.165 visitIfExp = NOP
1.166 @@ -767,7 +826,11 @@
1.167
1.168 def visitTryExcept(self, node):
1.169 self.dispatch(node.body)
1.170 +
1.171 + self.new_branchpoint()
1.172 +
1.173 for name, var, n in node.handlers:
1.174 + self.new_branch()
1.175
1.176 # Establish the local for the handler.
1.177
1.178 @@ -775,8 +838,15 @@
1.179 self.dispatch(var)
1.180 if n is not None:
1.181 self.dispatch(n)
1.182 +
1.183 + self.shelve_branch()
1.184 +
1.185 if node.else_ is not None:
1.186 + self.new_branch()
1.187 self.dispatch(node.else_)
1.188 + self.shelve_branch()
1.189 +
1.190 + self.merge_branches()
1.191 return None
1.192
1.193 visitTryFinally = NOP
1.194 @@ -788,9 +858,21 @@
1.195 visitUnarySub = _visitUnary
1.196
1.197 def visitWhile(self, node):
1.198 + self.new_branchpoint()
1.199 +
1.200 self.in_loop = 1
1.201 - self.NOP(node)
1.202 + self.dispatch(node.test)
1.203 + self.new_branch()
1.204 + self.dispatch(node.body)
1.205 + self.shelve_branch()
1.206 self.in_loop = 0
1.207 +
1.208 + if node.else_ is not None:
1.209 + self.new_branch()
1.210 + self.dispatch(node.else_)
1.211 + self.shelve_branch()
1.212 +
1.213 + self.merge_branches()
1.214 return None
1.215
1.216 visitWith = NOP