# HG changeset patch # User Paul Boddie # Date 1367171778 -7200 # Node ID 098cf40197a39660f20c505bc0244ba70e43c1e8 # Parent 8431cd5ebc653fd0b11ca3251f36de0a346f50f8 Changed the report generation to make use of deduction annotations. diff -r 8431cd5ebc65 -r 098cf40197a3 micropython/common.py --- a/micropython/common.py Sun Apr 28 19:23:05 2013 +0200 +++ b/micropython/common.py Sun Apr 28 19:56:18 2013 +0200 @@ -86,7 +86,7 @@ try: attributes.add(self.objtable.access(target.full_name(), attrname)) except TableError: - return None + pass return attributes @@ -129,47 +129,6 @@ return False - def possible_accessor_types(self, node, defining_users=1): - - """ - Given annotations made during the inspection process, return all possible - type names and indications of static usage for a 'node' involved in - attribute access. - - If 'defining_users' is set to a false value, attempt to get the type - names specifically applicable to the node, rather than retrieving more - general definition-based type observations. - """ - - all_target_names = [] - - # Where an attribute could already be detected and where its nature is - # not that of a general instance or an unresolved name, attempt to - # identify it. - - # Use explicit annotations on the node. - - attrs = self.possible_attributes_from_annotation(node) - if attrs: - target_names = set() - for (attr, value) in attrs: - # NOTE: Ignoring constant objects. - if attr: - target_names.add((attr.parent.full_name(), attr.is_static_attribute())) - all_target_names.append(target_names) - - # Use attribute usage observations. - - target_names = self.possible_accessor_types_from_usage(node, defining_users) - if target_names: - all_target_names.append(target_names) - - # Return the smallest set of target names. - - all_target_names.sort(key=lambda x: len(x)) - - return all_target_names and all_target_names[0] - def possible_attributes_from_annotation(self, node): """ diff -r 8431cd5ebc65 -r 098cf40197a3 micropython/report.py --- a/micropython/report.py Sun Apr 28 19:23:05 2013 +0200 +++ b/micropython/report.py Sun Apr 28 19:56:18 2013 +0200 @@ -3,7 +3,7 @@ """ View annotated sources. -Copyright (C) 2006, 2007, 2010, 2011, 2012 Paul Boddie +Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -345,7 +345,7 @@ for name in names: if not first: self.stream.write("
") - self.stream.write(name) + self.stream.write(self._text(name)) first = False self._names_list_end() @@ -419,17 +419,39 @@ values.sort() return values - def _attributes_to_attribute_names(self, attributes, attrname): + def _attribute_value_to_name(self, attr, value, target=False): + if value and not isinstance(value, Instance): + fullname = value.full_name() + elif isinstance(attr.parent, Instance): + fullname = "%s%s" % (attr.parent_type.full_name(), not target and ".%s" % attr.name or "") + else: + fullname = "%s%s" % (attr.parent.full_name(), not target and ".%s" % attr.name or "") + return fullname + + def _attributes_to_target_names(self, attributes): + + "Get the target names for the 'attributes'." + + output = [] + + if attributes: + for attr, value in attributes: + fullname = self._attribute_value_to_name(attr, value, True) + output.append(fullname) + + output.sort() + return output + + def _attributes_to_attribute_names(self, attributes): "Get the output form of the 'attributes'." output = [] - for value, target, target_name in attributes: - if value and not isinstance(value, Instance): - fullname = value.full_name() - else: - fullname = target_name + "." + attrname - output.append((fullname, value)) + + if attributes: + for attr, value in attributes: + fullname = self._attribute_value_to_name(attr, value, False) + output.append((fullname, value)) output.sort() return output @@ -1049,34 +1071,36 @@ first = False self._span_end() - def visitAssAttr(self, node): - possible_types = self.possible_accessor_types(node, defining_users=0) - - # Record whether types were already deduced. If not, get types using - # only this attribute. + def _visitAttr(self, node, label): + self.record_unknown_targets(node) - deduced = possible_types - if not possible_types: - possible_types = self._get_possible_types(node.attrname) + attributes = node._value_deduced and [self.get_attribute_and_value(node._value_deduced)] or \ + node._attr_deduced and [self.get_attribute_and_value(node._attr_deduced)] or \ + node._attrs_deduced or \ + map(self.get_attribute_and_value, node._attrs_deduced_from_specific_usage or []) - self.record_unknown_targets(possible_types, deduced, node) - attributes = self._get_attributes(possible_types, node.attrname) + possible_types = self._attributes_to_target_names(attributes) wraps_getattr = self._has_descendant(node.expr, compiler.ast.Getattr) if not wraps_getattr: - self._span_start("assattr") + self._span_start(label) self._accessor_start(possible_types) self.dispatch(node.expr) if not wraps_getattr: self._accessor_end(possible_types) + self.stream.write(".") - self._attribute_start(node.attrname, self._attributes_to_attribute_names(attributes, node.attrname)) - self._span(node.attrname, "attrname" + (not possible_types and " no-targets" or not deduced and " any-target" or "")) + self._attribute_start(node.attrname, self._attributes_to_attribute_names(attributes)) + self._span(node.attrname, "attrname" + (not possible_types and " no-targets" or "")) self._attribute_end(attributes) + if not wraps_getattr: self._span_end() + def visitAssAttr(self, node): + self._visitAttr(node, "assattr") + def visitAssList(self, node): self._span_start("list") self.stream.write("[") @@ -1157,37 +1181,7 @@ self._visitBinary(node, "//") def visitGetattr(self, node): - possible_types = self.possible_accessor_types(node, defining_users=0) - - # Record whether types were already deduced. If not, get types using - # only this attribute. - - deduced = possible_types - if not possible_types: - possible_types = self._get_possible_types(node.attrname) - - self.record_unknown_targets(possible_types, deduced, node) - attributes = self._get_attributes(possible_types, node.attrname) - - wraps_getattr = self._has_descendant(node.expr, compiler.ast.Getattr) - - if not wraps_getattr: - self._span_start("getattr") - self._accessor_start(possible_types) - - self.dispatch(node.expr) - - if not wraps_getattr: - self._accessor_end(possible_types) - - self.stream.write(".") - - self._attribute_start(node.attrname, self._attributes_to_attribute_names(attributes, node.attrname)) - self._span(node.attrname, "attrname" + (not possible_types and " no-targets" or not deduced and " any-target" or "")) - self._attribute_end(attributes) - - if not wraps_getattr: - self._span_end() + self._visitAttr(node, "getattr") def visitGenExpr(self, node): self._span_start("genexpr") @@ -1458,13 +1452,10 @@ # Statistics gathering methods. - def possible_accessor_types(self, node, defining_users=1): - return set([tn for (tn, st) in ASTVisitor.possible_accessor_types(self, node, defining_users)]) - - def record_unknown_targets(self, possible_types, deduced, node): - if not possible_types: + def record_unknown_targets(self, node): + if not node._attrs_deduced: self.program.unknown_target_nodes.append((self.units[-1], node)) - elif not deduced: + elif not node._attrs_deduced_from_specific_usage: self.program.independent_target_nodes.append((self.units[-1], node)) # Utility methods.