micropython

Changeset

437:c57594e43338
2011-06-26 Paul Boddie raw files shortlog changelog graph Moved the definition of accessor types into the function finalisation code, moving finalisation itself to after the object table has been redefined, resulting in substantially fewer accessor types being generated for any given set of attribute names (usage) where coverage analysis has eliminated many objects from a program. Fixed the presentation of various things in reports, adding support for some missing AST nodes.
micropython/__init__.py (file) micropython/common.py (file) micropython/data.py (file) micropython/inspect.py (file) micropython/report.py (file)
     1.1 --- a/micropython/__init__.py	Sun Jun 26 17:01:29 2011 +0200
     1.2 +++ b/micropython/__init__.py	Sun Jun 26 23:54:37 2011 +0200
     1.3 @@ -37,8 +37,7 @@
     1.4  which the functionality of the micropython package may be accessed.
     1.5  """
     1.6  
     1.7 -from micropython.common import ObjectSet, ProcessingError, TableError, \
     1.8 -    TableGenerationError
     1.9 +from micropython.common import *
    1.10  import micropython.ast
    1.11  import micropython.data
    1.12  import micropython.opt
    1.13 @@ -95,13 +94,14 @@
    1.14          self.get_parameter_table()
    1.15  
    1.16          self.importer.vacuum(objtable)
    1.17 -        self.importer.finalise()
    1.18  
    1.19          # Now remove unneeded things from the tables.
    1.20  
    1.21 -        self.get_object_table(reset=1)
    1.22 +        objtable = self.get_object_table(reset=1)
    1.23          self.get_parameter_table(reset=1)
    1.24  
    1.25 +        self.importer.finalise(objtable)
    1.26 +
    1.27      def get_image(self, with_builtins=0):
    1.28  
    1.29          """
    1.30 @@ -432,7 +432,7 @@
    1.31  
    1.32          self.vacuumed = 1
    1.33  
    1.34 -    def finalise(self):
    1.35 +    def finalise(self, objtable):
    1.36  
    1.37          "Finalise the program (which should have been vacuumed first)."
    1.38  
    1.39 @@ -447,7 +447,7 @@
    1.40          # Prepare module information again.
    1.41  
    1.42          for module in self.get_modules():
    1.43 -            module.finalise()
    1.44 +            module.finalise(objtable)
    1.45  
    1.46          self.finalised = 1
    1.47  
    1.48 @@ -612,25 +612,9 @@
    1.49              # Using all attribute names for a particular name, attempt to get
    1.50              # specific object types.
    1.51  
    1.52 -            all_objtypes = set()
    1.53 -
    1.54 -            for attrnames in usage:
    1.55 -                objtypes = objtable.all_possible_objects_plus_status(attrnames)
    1.56 -                if not objtypes:
    1.57 -                    print "Warning: usage in %r for %r finds no object supporting all attributes %r" % (from_name, name, attrnames)
    1.58 -                    objtypes = objtable.any_possible_objects_plus_status(attrnames)
    1.59 -                    if not objtypes:
    1.60 -                        print "Warning: usage in %r for %r finds no object supporting any attributes %r" % (from_name, name, attrnames)
    1.61 +            all_objtypes = get_object_types_for_usage(usage, objtable, name, from_name)
    1.62  
    1.63 -                all_objtypes.update(objtypes)
    1.64 -
    1.65 -            # Record the object types for generating guards.
    1.66 -
    1.67 -            if user is not None:
    1.68 -                if not hasattr(user, "_attrtypes"):
    1.69 -                    user._attrtypes = {}
    1.70 -
    1.71 -                user._attrtypes[name] = all_objtypes
    1.72 +            # Investigate the object types.
    1.73  
    1.74              self._collect_attributes_for_types(from_name, objtable, all_objtypes, usage)
    1.75  
     2.1 --- a/micropython/common.py	Sun Jun 26 17:01:29 2011 +0200
     2.2 +++ b/micropython/common.py	Sun Jun 26 23:54:37 2011 +0200
     2.3 @@ -260,6 +260,30 @@
     2.4  
     2.5      return hasattr(node, "unit") and node.unit.parent.has_key(node.unit.name)
     2.6  
     2.7 +def get_object_types_for_usage(usage, objtable, name, unit_name):
     2.8 +
     2.9 +    """
    2.10 +    Return for the given attribute 'usage', using the 'objtable', the object
    2.11 +    types which satisfy such usage, reporting any problems for the given 'name'
    2.12 +    and 'unit_name'.
    2.13 +    """
    2.14 +
    2.15 +    all_objtypes = set()
    2.16 +
    2.17 +    for attrnames in usage:
    2.18 +        objtypes = objtable.all_possible_objects_plus_status(attrnames)
    2.19 +        if not objtypes:
    2.20 +            print "Warning: usage in %r for %r finds no object supporting all attributes %r" % (
    2.21 +                unit_name, name, attrnames)
    2.22 +            objtypes = objtable.any_possible_objects_plus_status(attrnames)
    2.23 +            if not objtypes:
    2.24 +                print "Warning: usage in %r for %r finds no object supporting any attributes %r" % (
    2.25 +                    unit_name, name, attrnames)
    2.26 +
    2.27 +        all_objtypes.update(objtypes)
    2.28 +
    2.29 +    return all_objtypes
    2.30 +
    2.31  # Errors.
    2.32  
    2.33  class ProcessingError(Exception):
     3.1 --- a/micropython/data.py	Sun Jun 26 17:01:29 2011 +0200
     3.2 +++ b/micropython/data.py	Sun Jun 26 23:54:37 2011 +0200
     3.3 @@ -143,6 +143,9 @@
     3.4  
     3.5      # Administrative methods.
     3.6  
     3.7 +    def finalise(self, objtable):
     3.8 +        self.finalise_attributes()
     3.9 +
    3.10      def items_for_vacuum(self):
    3.11          return self.items() + self.lambdas.items()
    3.12  
    3.13 @@ -1777,6 +1780,10 @@
    3.14  
    3.15      # Administrative methods.
    3.16  
    3.17 +    def finalise(self, objtable):
    3.18 +        self.finalise_attributes()
    3.19 +        self.finalise_users(objtable)
    3.20 +
    3.21      def items_for_vacuum(self):
    3.22          return self.lambdas.items()
    3.23  
    3.24 @@ -1833,6 +1840,17 @@
    3.25  
    3.26          return i
    3.27  
    3.28 +    def finalise_users(self, objtable):
    3.29 +
    3.30 +        "Record the object types for generating guards."
    3.31 +
    3.32 +        # Visit each user and examine the attribute usage for each name.
    3.33 +
    3.34 +        for user in self.all_attribute_users:
    3.35 +            user._attrtypes = {}
    3.36 +            for name, usage in user._attrcombined.items():
    3.37 +                user._attrtypes[name] = get_object_types_for_usage(usage, objtable, name, self.full_name())
    3.38 +
    3.39      def as_instantiator(self):
    3.40  
    3.41          "Make an instantiator function from a method, keeping all arguments."
     4.1 --- a/micropython/inspect.py	Sun Jun 26 17:01:29 2011 +0200
     4.2 +++ b/micropython/inspect.py	Sun Jun 26 23:54:37 2011 +0200
     4.3 @@ -229,12 +229,12 @@
     4.4          for obj in self.all_objects:
     4.5              obj.unfinalise_attributes()
     4.6  
     4.7 -    def finalise(self):
     4.8 +    def finalise(self, objtable):
     4.9  
    4.10          "Finalise the module."
    4.11  
    4.12          for obj in self.all_objects:
    4.13 -            obj.finalise_attributes()
    4.14 +            obj.finalise(objtable)
    4.15  
    4.16      def add_object(self, obj, any_scope=0):
    4.17  
     5.1 --- a/micropython/report.py	Sun Jun 26 17:01:29 2011 +0200
     5.2 +++ b/micropython/report.py	Sun Jun 26 23:54:37 2011 +0200
     5.3 @@ -236,7 +236,10 @@
     5.4          can be used to customise the CSS classes employed.
     5.5          """
     5.6  
     5.7 -        self._summary_link(module.full_name(), obj.full_name(), obj.name, classes)
     5.8 +        if isinstance(obj, Class) or (isinstance(obj, Function) and obj.is_method()):
     5.9 +            self._summary_link(module.full_name(), obj.full_name(), obj.name, classes)
    5.10 +        else:
    5.11 +            self._span(obj.name, classes)
    5.12  
    5.13      def _object_name_ref(self, module, obj, name=None, classes=None):
    5.14  
    5.15 @@ -268,7 +271,7 @@
    5.16      def _op(self, symbol, name=None, leading=0, trailing=1):
    5.17          if leading:
    5.18              self.stream.write(" ")
    5.19 -        self._span_start("operation")
    5.20 +        self._span_start(name and "operation" or None)
    5.21          self._span(symbol, "operator")
    5.22          if name is not None:
    5.23              self._popup_start()
    5.24 @@ -834,7 +837,7 @@
    5.25          self._accessor_end(target_names)
    5.26          self._span_start("attr")
    5.27          self.stream.write(".")
    5.28 -        self._name(node.attrname)
    5.29 +        self._span(node.attrname, "attrname")
    5.30          self._span_end()
    5.31          self._span_end()
    5.32  
    5.33 @@ -858,6 +861,12 @@
    5.34      def visitBitand(self, node):
    5.35          self._visitBitBinary(node, "bitand", "&")
    5.36  
    5.37 +    def visitBitor(self, node):
    5.38 +        self._visitBitBinary(node, "bitor", "|")
    5.39 +
    5.40 +    def visitBitxor(self, node):
    5.41 +        self._visitBitBinary(node, "bitxor", "^")
    5.42 +
    5.43      def visitCallFunc(self, node):
    5.44          self._span_start("callfunc")
    5.45          self.dispatch(node.node)