1.1 --- a/micropython/report.py Fri Nov 02 00:36:01 2012 +0100
1.2 +++ b/micropython/report.py Fri Nov 02 00:58:26 2012 +0100
1.3 @@ -453,10 +453,14 @@
1.4 if attributes:
1.5 self._span_end()
1.6
1.7 + def _get_possible_types(self, attrname):
1.8 + objtable = self.program.get_object_table()
1.9 + return objtable.any_possible_objects([attrname])
1.10 +
1.11 def _get_attributes(self, possible_types, attrname):
1.12 objtable = self.program.get_object_table()
1.13 attributes = []
1.14 - for target_name, is_static in possible_types:
1.15 + for target_name in possible_types:
1.16 target = objtable.get_object(target_name)
1.17 try:
1.18 attr = objtable.access(target_name, attrname)
1.19 @@ -618,6 +622,8 @@
1.20 self.visitor = self
1.21 self.module = module
1.22 self.program = program
1.23 + self.program.unknown_target_nodes = []
1.24 + self.units = []
1.25
1.26 def to_stream(self, stream):
1.27
1.28 @@ -631,9 +637,13 @@
1.29 self.stream.write(html_footer)
1.30
1.31 def visitModule(self, node):
1.32 + self.units.append(node.unit)
1.33 +
1.34 self._doc(node, "module")
1.35 self.default(node)
1.36
1.37 + self.units.pop()
1.38 +
1.39 # Statements.
1.40
1.41 def visitAssert(self, node):
1.42 @@ -673,6 +683,8 @@
1.43 # Use inspected details where possible.
1.44
1.45 cls = node.unit
1.46 + self.units.append(cls)
1.47 +
1.48 bases = cls.bases
1.49 self.stream.write("<div class='class nowrap' id='%s'>\n" % cls.full_name())
1.50
1.51 @@ -718,6 +730,8 @@
1.52 self.stream.write("</div>\n")
1.53 self.stream.write("</div>\n")
1.54
1.55 + self.units.pop()
1.56 +
1.57 def visitContinue(self, node):
1.58 self.stream.write("<div class='continue nowrap'>\n")
1.59 self._keyword("continue")
1.60 @@ -772,6 +786,8 @@
1.61 return
1.62
1.63 fn = node.unit
1.64 + self.units.append(fn)
1.65 +
1.66 self.stream.write("<div class='function nowrap' id='%s'>\n" % fn.full_name())
1.67
1.68 # Write the declaration line.
1.69 @@ -792,6 +808,8 @@
1.70 self.stream.write("</div>\n")
1.71 self.stream.write("</div>\n")
1.72
1.73 + self.units.pop()
1.74 +
1.75 def visitGlobal(self, node):
1.76 self.stream.write("<div class='global nowrap'>\n")
1.77 self._keyword("global")
1.78 @@ -1021,21 +1039,19 @@
1.79
1.80 def visitAssAttr(self, node):
1.81 possible_types = self.possible_accessor_types(node, defining_users=0)
1.82 - target_names = set(["%s%s" % (is_static and "static " or "", target_name)
1.83 - for target_name, is_static in possible_types])
1.84 attributes = self._get_attributes(possible_types, node.attrname)
1.85
1.86 wraps_getattr = isinstance(node.expr, compiler.ast.Getattr)
1.87
1.88 if not wraps_getattr:
1.89 self._span_start("assattr")
1.90 - self._accessor_start(target_names)
1.91 + self._accessor_start(possible_types)
1.92 self.dispatch(node.expr)
1.93 if not wraps_getattr:
1.94 - self._accessor_end(target_names)
1.95 + self._accessor_end(possible_types)
1.96 self.stream.write(".")
1.97 self._attribute_start(node.attrname, self._attributes_to_attribute_names(attributes, node.attrname))
1.98 - self._span(node.attrname, "attrname" + (not target_names and " no-targets" or ""))
1.99 + self._span(node.attrname, "attrname" + (not possible_types and " no-targets" or ""))
1.100 self._attribute_end(attributes)
1.101 if not wraps_getattr:
1.102 self._span_end()
1.103 @@ -1121,25 +1137,23 @@
1.104
1.105 def visitGetattr(self, node):
1.106 possible_types = self.possible_accessor_types(node, defining_users=0)
1.107 - target_names = set(["%s%s" % (is_static and "static " or "", target_name)
1.108 - for target_name, is_static in possible_types])
1.109 attributes = self._get_attributes(possible_types, node.attrname)
1.110
1.111 wraps_getattr = isinstance(node.expr, compiler.ast.Getattr)
1.112
1.113 if not wraps_getattr:
1.114 self._span_start("getattr")
1.115 - self._accessor_start(target_names)
1.116 + self._accessor_start(possible_types)
1.117
1.118 self.dispatch(node.expr)
1.119
1.120 if not wraps_getattr:
1.121 - self._accessor_end(target_names)
1.122 + self._accessor_end(possible_types)
1.123
1.124 self.stream.write(".")
1.125
1.126 self._attribute_start(node.attrname, self._attributes_to_attribute_names(attributes, node.attrname))
1.127 - self._span(node.attrname, "attrname" + (not target_names and " no-targets" or ""))
1.128 + self._span(node.attrname, "attrname" + (not possible_types and " no-targets" or ""))
1.129 self._attribute_end(attributes)
1.130
1.131 if not wraps_getattr:
1.132 @@ -1202,6 +1216,7 @@
1.133
1.134 def visitLambda(self, node):
1.135 fn = node.unit
1.136 + self.units.append(fn)
1.137
1.138 self._span_start("lambda")
1.139 self._keyword("lambda")
1.140 @@ -1212,6 +1227,8 @@
1.141 self._span_end()
1.142 self._span_end()
1.143
1.144 + self.units.pop()
1.145 +
1.146 def visitLeftShift(self, node):
1.147 self._visitBinary(node, "<<")
1.148
1.149 @@ -1409,6 +1426,16 @@
1.150 self.stream.write("=")
1.151 self.dispatch(default)
1.152
1.153 + # Statistics gathering methods.
1.154 +
1.155 + def possible_accessor_types(self, node, defining_users=1):
1.156 + possible_types = [tn for (tn, st) in ASTVisitor.possible_accessor_types(self, node, defining_users)]
1.157 + if not possible_types:
1.158 + possible_types = self._get_possible_types(node.attrname)
1.159 + if not possible_types:
1.160 + self.program.unknown_target_nodes.append((self.units[-1], node))
1.161 + return possible_types
1.162 +
1.163 # Convenience functions.
1.164
1.165 def summarise(module, program, filename):