# HG changeset patch # User Paul Boddie # Date 1342280562 -7200 # Node ID d13e02292ffaacb51152e264114b21f672a96801 # Parent 512fb25ed7b3f917a353f77f809f92eda56a17b2 Record unsatisfiable usage observations for potential later display as warnings. diff -r 512fb25ed7b3 -r d13e02292ffa micropython/__init__.py --- a/micropython/__init__.py Sat Jul 14 01:37:42 2012 +0200 +++ b/micropython/__init__.py Sat Jul 14 17:42:42 2012 +0200 @@ -48,7 +48,7 @@ import micropython.table import bisect import os -#import sys +import sys try: set @@ -444,6 +444,10 @@ self.attribute_users_visited = set() self.attributes_to_visit = {} + # Attribute usage type deduction failures. + + self.attribute_usage_failures = set() + # Status information. self.completed = False @@ -689,9 +693,9 @@ # Using all attribute names for a particular name, attempt to get # specific object types. - all_objtypes = get_object_types_for_usage(usage, objtable, name, from_name, True) + all_objtypes = get_object_types_for_usage(usage, objtable, name, from_name, True, self) if not all_objtypes: - all_objtypes = get_object_types_for_usage(usage, objtable, name, from_name, False) + all_objtypes = get_object_types_for_usage(usage, objtable, name, from_name, False, self) # Where the name through which the attributes are accessed is the # special "self" name, restrict the possibilities to types @@ -821,6 +825,18 @@ else: self.add_attribute_to_visit(parentname, attrname) + def add_usage_failure(self, all_attributes, unit_name, name, attrnames): + + """ + Record a type deduction failure based on 'all_attributes' (where true + indicates that all attribute names were required; false indicating that + any were required) within the given 'unit_name' for the variable of the + given 'name' and for the specified 'attrnames'. + """ + + attrnames = tuple(attrnames) + self.attribute_usage_failures.add((unit_name, name, attrnames, all_attributes)) + # Constant accounting. def use_constant(self, const, from_name): diff -r 512fb25ed7b3 -r d13e02292ffa micropython/data.py --- a/micropython/data.py Sat Jul 14 01:37:42 2012 +0200 +++ b/micropython/data.py Sat Jul 14 17:42:42 2012 +0200 @@ -460,7 +460,7 @@ attrtypes = {} for name, combined_usage in usage.items(): if combined_usage is not None: - objtypes = get_object_types_for_usage(combined_usage, objtable, name, self.full_name(), True) + objtypes = get_object_types_for_usage(combined_usage, objtable, name, self.full_name(), True, self.module.importer) if objtypes: if isinstance(self, Function) and self.is_method() and name == "self": objtypes = filter_using_self(objtypes, self.parent) diff -r 512fb25ed7b3 -r d13e02292ffa micropython/inspect.py --- a/micropython/inspect.py Sat Jul 14 01:37:42 2012 +0200 +++ b/micropython/inspect.py Sat Jul 14 17:42:42 2012 +0200 @@ -839,7 +839,6 @@ elif isinstance(value, Module): self.store_module_attr(attrname, value) - print >>sys.stderr, "Warning: attribute %r of module %r set outside the module." % (node.attrname, expr.get_value().name) elif isinstance(value, Class): self.store_class_attr(attrname, value) diff -r 512fb25ed7b3 -r d13e02292ffa micropython/types.py --- a/micropython/types.py Sat Jul 14 01:37:42 2012 +0200 +++ b/micropython/types.py Sat Jul 14 17:42:42 2012 +0200 @@ -26,7 +26,7 @@ except NameError: from sets import Set as set -def get_object_types_for_usage(usage, objtable, name, unit_name, all_attributes): +def get_object_types_for_usage(usage, objtable, name, unit_name, all_attributes, importer=None): """ Return for the given attribute 'usage', using the 'objtable', the object @@ -38,6 +38,9 @@ list must be matched to provide object types. Otherwise, the presence of any attribute from a usage list in a type's set of attributes will be enough to provide that type as a suitable object type. + + If 'importer' is specified and not None, it will be used to record warnings + about unsatisfiable usage situations. """ all_objtypes = set() @@ -49,14 +52,10 @@ if all_attributes: objtypes = objtable.all_possible_objects_plus_status(attrnames) - if not objtypes: - print >>sys.stderr, "Warning: usage in %r for %r finds no object supporting all attributes %r" % ( - unit_name, name, attrnames.keys()) else: objtypes = objtable.any_possible_objects_plus_status(attrnames) - if not objtypes: - print >>sys.stderr, "Warning: usage in %r for %r finds no object supporting any attributes %r" % ( - unit_name, name, attrnames.keys()) + if not objtypes and importer: + importer.add_usage_failure(all_attributes, unit_name, name, attrnames.keys()) all_objtypes.update(objtypes) diff -r 512fb25ed7b3 -r d13e02292ffa test.py --- a/test.py Sat Jul 14 01:37:42 2012 +0200 +++ b/test.py Sat Jul 14 17:42:42 2012 +0200 @@ -22,6 +22,15 @@ print "%6d" % (len(table_slice) - table_slice.count(None)), \ "".join(entry and "#" or "_" for entry in table_slice) +def show_warnings(attribute_usage_failures): + failures = list(attribute_usage_failures) + failures.sort() + for unit_name, name, attrnames, all_attributes in failures: + attrnames = list(attrnames) + attrnames.sort() + print >>sys.stderr, "%s: Name %r with %s attributes %r" % ( + unit_name, name, all_attributes and "all" or "any", ", ".join(attrnames)) + def attrs(obj): for name, attr in obj.items(): print name, attr @@ -61,6 +70,17 @@ m = i.load_from_file(filename) p.finalise() + + # Show warnings. + + if "-w" in sys.argv: + print >>sys.stderr + print >>sys.stderr, "Warnings:" + show_warnings(i.attribute_usage_failures) + print >>sys.stderr + + # Make the builtins module available through a variable. + b = i.get_module("__builtins__") # Make a report.