1.1 --- a/micropython/report.py Sun Apr 28 19:23:05 2013 +0200
1.2 +++ b/micropython/report.py Sun Apr 28 19:56:18 2013 +0200
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 View annotated sources.
1.6
1.7 -Copyright (C) 2006, 2007, 2010, 2011, 2012 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -345,7 +345,7 @@
1.13 for name in names:
1.14 if not first:
1.15 self.stream.write("<br />")
1.16 - self.stream.write(name)
1.17 + self.stream.write(self._text(name))
1.18 first = False
1.19 self._names_list_end()
1.20
1.21 @@ -419,17 +419,39 @@
1.22 values.sort()
1.23 return values
1.24
1.25 - def _attributes_to_attribute_names(self, attributes, attrname):
1.26 + def _attribute_value_to_name(self, attr, value, target=False):
1.27 + if value and not isinstance(value, Instance):
1.28 + fullname = value.full_name()
1.29 + elif isinstance(attr.parent, Instance):
1.30 + fullname = "%s%s" % (attr.parent_type.full_name(), not target and ".%s" % attr.name or "")
1.31 + else:
1.32 + fullname = "%s%s" % (attr.parent.full_name(), not target and ".%s" % attr.name or "")
1.33 + return fullname
1.34 +
1.35 + def _attributes_to_target_names(self, attributes):
1.36 +
1.37 + "Get the target names for the 'attributes'."
1.38 +
1.39 + output = []
1.40 +
1.41 + if attributes:
1.42 + for attr, value in attributes:
1.43 + fullname = self._attribute_value_to_name(attr, value, True)
1.44 + output.append(fullname)
1.45 +
1.46 + output.sort()
1.47 + return output
1.48 +
1.49 + def _attributes_to_attribute_names(self, attributes):
1.50
1.51 "Get the output form of the 'attributes'."
1.52
1.53 output = []
1.54 - for value, target, target_name in attributes:
1.55 - if value and not isinstance(value, Instance):
1.56 - fullname = value.full_name()
1.57 - else:
1.58 - fullname = target_name + "." + attrname
1.59 - output.append((fullname, value))
1.60 +
1.61 + if attributes:
1.62 + for attr, value in attributes:
1.63 + fullname = self._attribute_value_to_name(attr, value, False)
1.64 + output.append((fullname, value))
1.65
1.66 output.sort()
1.67 return output
1.68 @@ -1049,34 +1071,36 @@
1.69 first = False
1.70 self._span_end()
1.71
1.72 - def visitAssAttr(self, node):
1.73 - possible_types = self.possible_accessor_types(node, defining_users=0)
1.74 -
1.75 - # Record whether types were already deduced. If not, get types using
1.76 - # only this attribute.
1.77 + def _visitAttr(self, node, label):
1.78 + self.record_unknown_targets(node)
1.79
1.80 - deduced = possible_types
1.81 - if not possible_types:
1.82 - possible_types = self._get_possible_types(node.attrname)
1.83 + attributes = node._value_deduced and [self.get_attribute_and_value(node._value_deduced)] or \
1.84 + node._attr_deduced and [self.get_attribute_and_value(node._attr_deduced)] or \
1.85 + node._attrs_deduced or \
1.86 + map(self.get_attribute_and_value, node._attrs_deduced_from_specific_usage or [])
1.87
1.88 - self.record_unknown_targets(possible_types, deduced, node)
1.89 - attributes = self._get_attributes(possible_types, node.attrname)
1.90 + possible_types = self._attributes_to_target_names(attributes)
1.91
1.92 wraps_getattr = self._has_descendant(node.expr, compiler.ast.Getattr)
1.93
1.94 if not wraps_getattr:
1.95 - self._span_start("assattr")
1.96 + self._span_start(label)
1.97 self._accessor_start(possible_types)
1.98 self.dispatch(node.expr)
1.99 if not wraps_getattr:
1.100 self._accessor_end(possible_types)
1.101 +
1.102 self.stream.write(".")
1.103 - self._attribute_start(node.attrname, self._attributes_to_attribute_names(attributes, node.attrname))
1.104 - self._span(node.attrname, "attrname" + (not possible_types and " no-targets" or not deduced and " any-target" or ""))
1.105 + self._attribute_start(node.attrname, self._attributes_to_attribute_names(attributes))
1.106 + self._span(node.attrname, "attrname" + (not possible_types and " no-targets" or ""))
1.107 self._attribute_end(attributes)
1.108 +
1.109 if not wraps_getattr:
1.110 self._span_end()
1.111
1.112 + def visitAssAttr(self, node):
1.113 + self._visitAttr(node, "assattr")
1.114 +
1.115 def visitAssList(self, node):
1.116 self._span_start("list")
1.117 self.stream.write("[")
1.118 @@ -1157,37 +1181,7 @@
1.119 self._visitBinary(node, "//")
1.120
1.121 def visitGetattr(self, node):
1.122 - possible_types = self.possible_accessor_types(node, defining_users=0)
1.123 -
1.124 - # Record whether types were already deduced. If not, get types using
1.125 - # only this attribute.
1.126 -
1.127 - deduced = possible_types
1.128 - if not possible_types:
1.129 - possible_types = self._get_possible_types(node.attrname)
1.130 -
1.131 - self.record_unknown_targets(possible_types, deduced, node)
1.132 - attributes = self._get_attributes(possible_types, node.attrname)
1.133 -
1.134 - wraps_getattr = self._has_descendant(node.expr, compiler.ast.Getattr)
1.135 -
1.136 - if not wraps_getattr:
1.137 - self._span_start("getattr")
1.138 - self._accessor_start(possible_types)
1.139 -
1.140 - self.dispatch(node.expr)
1.141 -
1.142 - if not wraps_getattr:
1.143 - self._accessor_end(possible_types)
1.144 -
1.145 - self.stream.write(".")
1.146 -
1.147 - self._attribute_start(node.attrname, self._attributes_to_attribute_names(attributes, node.attrname))
1.148 - self._span(node.attrname, "attrname" + (not possible_types and " no-targets" or not deduced and " any-target" or ""))
1.149 - self._attribute_end(attributes)
1.150 -
1.151 - if not wraps_getattr:
1.152 - self._span_end()
1.153 + self._visitAttr(node, "getattr")
1.154
1.155 def visitGenExpr(self, node):
1.156 self._span_start("genexpr")
1.157 @@ -1458,13 +1452,10 @@
1.158
1.159 # Statistics gathering methods.
1.160
1.161 - def possible_accessor_types(self, node, defining_users=1):
1.162 - return set([tn for (tn, st) in ASTVisitor.possible_accessor_types(self, node, defining_users)])
1.163 -
1.164 - def record_unknown_targets(self, possible_types, deduced, node):
1.165 - if not possible_types:
1.166 + def record_unknown_targets(self, node):
1.167 + if not node._attrs_deduced:
1.168 self.program.unknown_target_nodes.append((self.units[-1], node))
1.169 - elif not deduced:
1.170 + elif not node._attrs_deduced_from_specific_usage:
1.171 self.program.independent_target_nodes.append((self.units[-1], node))
1.172
1.173 # Utility methods.