1.1 --- a/micropython/inspect.py Tue Apr 20 01:11:41 2010 +0200
1.2 +++ b/micropython/inspect.py Wed Apr 21 00:58:29 2010 +0200
1.3 @@ -315,12 +315,23 @@
1.4
1.5 return (self.namespaces[-1:] or [self])[0]
1.6
1.7 - def use_name(self, name):
1.8 + def use_name(self, name, node=None):
1.9 +
1.10 + """
1.11 + Use the given 'name' within the current namespace/unit, either in
1.12 + conjunction with a particular object (if 'node' is specified and not
1.13 + None) or unconditionally.
1.14 + """
1.15
1.16 - "Use the given 'name' within the current namespace/unit."
1.17 + if node is not None and isinstance(node, compiler.ast.Name):
1.18 + self.use_attribute(node.name, name)
1.19
1.20 - unit = self.get_namespace()
1.21 - self.importer.use_name(name, unit.full_name())
1.22 + # For general name usage, declare usage of the given name from this
1.23 + # particular unit.
1.24 +
1.25 + else:
1.26 + unit = self.get_namespace()
1.27 + self.importer.use_name(name, unit.full_name())
1.28
1.29 # Attribute usage methods.
1.30 # These are convenience methods which refer to the specific namespace's
1.31 @@ -351,12 +362,21 @@
1.32 self.get_namespace()._define_attribute_user(node)
1.33
1.34 def use_attribute(self, name, attrname):
1.35 +
1.36 + "Note usage on the attribute user 'name' of the attribute 'attrname'."
1.37 +
1.38 return self.get_namespace()._use_attribute(name, attrname)
1.39
1.40 - # Specific attribute usage, nominating specific attributes which can be
1.41 - # resolved during inspection.
1.42 + def use_specific_attribute(self, objname, attrname):
1.43
1.44 - def use_specific_attribute(self, objname, attrname):
1.45 + """
1.46 + Note attribute usage specifically on 'objname' - an object which is
1.47 + known at inspection time - or in the current unit if 'objname' is None,
1.48 + nominating a specific attribute 'attrname'.
1.49 +
1.50 + This bypasses attribute user mechanisms.
1.51 + """
1.52 +
1.53 from_name = self.get_namespace().full_name()
1.54 objname = objname or from_name
1.55 self.importer.use_specific_name(objname, attrname, from_name)
1.56 @@ -387,7 +407,7 @@
1.57 "Accounting method for the unary operator 'node'."
1.58
1.59 method = unary_methods[node.__class__.__name__]
1.60 - self.use_name(method)
1.61 + self.use_name(method, node)
1.62 return self.OP(node)
1.63
1.64 def _visitBinary(self, node):
1.65 @@ -395,8 +415,8 @@
1.66 "Accounting method for the binary operator 'node'."
1.67
1.68 left_method, right_method = binary_methods[node.__class__.__name__]
1.69 - self.use_name(left_method)
1.70 - self.use_name(right_method)
1.71 + self.use_name(left_method, node)
1.72 + self.use_name(right_method, node)
1.73 return self.OP(node)
1.74
1.75 def _visitFunction(self, node, name):
1.76 @@ -505,7 +525,7 @@
1.77
1.78 # Declare names which will be used by generated code.
1.79
1.80 - self.use_name("__getitem__")
1.81 + self.use_name("__getitem__", node)
1.82
1.83 # Process the assignment.
1.84
1.85 @@ -534,9 +554,9 @@
1.86 # Accounting.
1.87
1.88 aug_method, (left_method, right_method) = augassign_methods[node.op]
1.89 - self.use_name(aug_method)
1.90 - self.use_name(left_method)
1.91 - self.use_name(right_method)
1.92 + self.use_name(aug_method, node)
1.93 + self.use_name(left_method, node)
1.94 + self.use_name(right_method, node)
1.95
1.96 # Process the assignment.
1.97
1.98 @@ -624,14 +644,24 @@
1.99 # Accounting.
1.100 # NOTE: Replicates some code in micropython.ast.visitCompare.
1.101
1.102 + this_node = node
1.103 +
1.104 for op in node.ops:
1.105 op_name, next_node = op
1.106 +
1.107 + # Get the applicable methods.
1.108 +
1.109 methods = comparison_methods[op_name]
1.110 +
1.111 + # Define name/attribute usage.
1.112 +
1.113 if methods is not None:
1.114 - self.use_name(methods[0])
1.115 - self.use_name(methods[1])
1.116 + self.use_name(methods[0], this_node)
1.117 + self.use_name(methods[1], next_node)
1.118 elif op_name.endswith("in"):
1.119 - self.use_name("__contains__")
1.120 + self.use_name("__contains__", next_node)
1.121 +
1.122 + this_node = next_node
1.123
1.124 return self.OP(node)
1.125
1.126 @@ -639,7 +669,7 @@
1.127
1.128 # Register the constant, if necessary, returning the resulting object.
1.129
1.130 - self.use_name(self.importer.get_constant_type_name(node.value))
1.131 + self.use_name(self.importer.get_constant_type_name(node.value), node)
1.132 return self.importer.make_constant(node.value)
1.133
1.134 visitContinue = NOP_ABANDON
1.135 @@ -665,7 +695,7 @@
1.136
1.137 # Declare names which will be used by generated code.
1.138
1.139 - self.use_name("__iter__")
1.140 + self.use_name("__iter__", node.list)
1.141 self.use_name("next")
1.142
1.143 self.in_loop = 1
1.144 @@ -757,7 +787,7 @@
1.145 node._attrusers = self.use_attribute(expr.name, attrname)
1.146 node._username = expr.name
1.147 else:
1.148 - self.use_name(attrname)
1.149 + self.use_name(attrname, node.expr)
1.150
1.151 elif self.builtins is not None:
1.152 attr = self.builtins.get(attrname)
1.153 @@ -916,7 +946,7 @@
1.154 visitSub = _visitBinary
1.155
1.156 def visitSubscript(self, node):
1.157 - self.use_name("__getitem__")
1.158 + self.use_name("__getitem__", node)
1.159 self.OP(node)
1.160
1.161 def visitTryExcept(self, node):