Lichen

Changeset

847:eb168cb289d4
2018-07-11 Paul Boddie raw files shortlog changelog graph Simplified various operations in the generator and optimiser, relying on more general mappings for attribute names instead of those providing them in order, employing references for the optimiser's all_attrs mapping keys instead of tuples.
generator.py (file) optimiser.py (file)
     1.1 --- a/generator.py	Thu Jul 05 23:40:53 2018 +0200
     1.2 +++ b/generator.py	Wed Jul 11 18:33:51 2018 +0200
     1.3 @@ -3,7 +3,7 @@
     1.4  """
     1.5  Generate C code from object layouts and other deduced information.
     1.6  
     1.7 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
     1.8 +Copyright (C) 2015, 2016, 2017, 2018 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 @@ -204,14 +204,12 @@
    1.13              # Generate table and structure data.
    1.14  
    1.15              function_instance_attrs = None
    1.16 -            objects = self.optimiser.attr_table.items()
    1.17 +            objects = self.optimiser.all_attrs.items()
    1.18              objects.sort()
    1.19  
    1.20              self.callables = {}
    1.21  
    1.22 -            for ref, indexes in objects:
    1.23 -                attrnames = self.get_attribute_names(indexes)
    1.24 -
    1.25 +            for ref, attrnames in objects:
    1.26                  kind = ref.get_kind()
    1.27                  path = ref.get_origin()
    1.28                  table_name = encode_tablename(kind, path)
    1.29 @@ -613,8 +611,7 @@
    1.30          # Obtain the attributes.
    1.31  
    1.32          cls = ref.get_origin()
    1.33 -        indexes = self.optimiser.attr_table[ref]
    1.34 -        attrnames = self.get_attribute_names(indexes)
    1.35 +        attrnames = self.optimiser.all_attrs[ref]
    1.36          attrs = self.get_instance_attributes(cls, attrnames)
    1.37  
    1.38          # Set the data, if provided.
    1.39 @@ -867,22 +864,6 @@
    1.40          num_parameters = len(parameters) + 1
    1.41          return num_parameters - (defaults and len(defaults) or 0), num_parameters
    1.42  
    1.43 -    def get_attribute_names(self, indexes):
    1.44 -
    1.45 -        """
    1.46 -        Given a list of attribute table 'indexes', return a list of attribute
    1.47 -        names.
    1.48 -        """
    1.49 -
    1.50 -        all_attrnames = self.optimiser.all_attrnames
    1.51 -        attrnames = []
    1.52 -        for i in indexes:
    1.53 -            if i is None:
    1.54 -                attrnames.append(None)
    1.55 -            else:
    1.56 -                attrnames.append(all_attrnames[i])
    1.57 -        return attrnames
    1.58 -
    1.59      def get_static_attributes(self, kind, name, attrnames):
    1.60  
    1.61          """
    1.62 @@ -987,17 +968,8 @@
    1.63          structure of the given 'kind', adding entries to the object 'structure'.
    1.64          """
    1.65  
    1.66 -        # Populate function instance structures for functions.
    1.67 -
    1.68 -        if ref.has_kind("<function>"):
    1.69 -            origin = self.function_type
    1.70 -            structure_ref = Reference("<instance>", self.function_type)
    1.71 -
    1.72 -        # Otherwise, just populate the appropriate structures.
    1.73 -
    1.74 -        else:
    1.75 -            origin = ref.get_origin()
    1.76 -            structure_ref = ref
    1.77 +        structure_ref = self.get_target_structure(ref)
    1.78 +        origin = structure_ref.get_origin()
    1.79  
    1.80          for attrname in self.optimiser.structures[structure_ref]:
    1.81  
    1.82 @@ -1129,6 +1101,20 @@
    1.83  
    1.84                  structure.append(self.encode_member(origin, attrname, attr, kind))
    1.85  
    1.86 +    def get_target_structure(self, ref):
    1.87 +
    1.88 +        "Return the target structure type and reference for 'ref'."
    1.89 +
    1.90 +        # Populate function instance structures for functions.
    1.91 +
    1.92 +        if ref.has_kind("<function>"):
    1.93 +            return Reference("<instance>", self.function_type)
    1.94 +
    1.95 +        # Otherwise, just populate the appropriate structures.
    1.96 +
    1.97 +        else:
    1.98 +            return ref
    1.99 +
   1.100      def encode_member(self, path, name, ref, structure_type):
   1.101  
   1.102          """
     2.1 --- a/optimiser.py	Thu Jul 05 23:40:53 2018 +0200
     2.2 +++ b/optimiser.py	Wed Jul 11 18:33:51 2018 +0200
     2.3 @@ -3,7 +3,7 @@
     2.4  """
     2.5  Optimise object layouts and generate access instruction plans.
     2.6  
     2.7 -Copyright (C) 2014, 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
     2.8 +Copyright (C) 2014, 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
     2.9  
    2.10  This program is free software; you can redistribute it and/or modify it under
    2.11  the terms of the GNU General Public License as published by the Free Software
    2.12 @@ -413,6 +413,12 @@
    2.13          finally:
    2.14              f.close()
    2.15  
    2.16 +    def is_allocated_attribute(self, attrname):
    2.17 +
    2.18 +        "Return whether 'attrname' is to be allocated in an object."
    2.19 +
    2.20 +        return not attrname.startswith("$t")
    2.21 +
    2.22      def populate_objects(self):
    2.23  
    2.24          "Populate objects using attribute and usage information."
    2.25 @@ -432,8 +438,8 @@
    2.26  
    2.27                  # Remove temporary names from structures.
    2.28  
    2.29 -                attrnames = filter(lambda x: not x.startswith("$t"), attrnames)
    2.30 -                self.all_attrs[(objkind, name)] = attrnames
    2.31 +                attrnames = filter(self.is_allocated_attribute, attrnames)
    2.32 +                self.all_attrs[Reference(objkind, name)] = attrnames
    2.33  
    2.34          try:
    2.35              self.locations = get_allocated_locations(self.all_attrs,
    2.36 @@ -495,8 +501,7 @@
    2.37  
    2.38          # Record the structures.
    2.39  
    2.40 -        for (objkind, name), attrnames in self.all_attrs.items():
    2.41 -            key = Reference(objkind, name)
    2.42 +        for key, attrnames in self.all_attrs.items():
    2.43              l = self.structures[key] = [None] * len(attrnames)
    2.44  
    2.45              for attrname in attrnames:
    2.46 @@ -719,7 +724,7 @@
    2.47  
    2.48      """
    2.49      Get attribute and size information for the object attributes defined by 'd'
    2.50 -    providing a mapping from (object kind, type name) to attribute names.
    2.51 +    providing a mapping from object references to attribute names.
    2.52  
    2.53      Return a matrix of attributes (each row entry consisting of column values
    2.54      providing attribute names, with value positions corresponding to types
    2.55 @@ -736,15 +741,15 @@
    2.56      sizes = {}
    2.57      objkinds = {}
    2.58  
    2.59 -    for objtype, attrnames in d.items():
    2.60 -        objkind, _name = objtype
    2.61 +    for ref, attrnames in d.items():
    2.62 +        objkind = ref.get_kind()
    2.63  
    2.64          for attrname in attrnames:
    2.65  
    2.66              # Record each type supporting the attribute.
    2.67  
    2.68              init_item(attrs, attrname, set)
    2.69 -            attrs[attrname].add(objtype)
    2.70 +            attrs[attrname].add(ref)
    2.71  
    2.72              # Maintain a record of the smallest object size supporting the given
    2.73              # attribute.
    2.74 @@ -761,13 +766,13 @@
    2.75  
    2.76      # Obtain attribute details in order of size and occupancy.
    2.77  
    2.78 -    all_objtypes = d.keys()
    2.79 +    all_refs = d.keys()
    2.80  
    2.81      rsizes = []
    2.82      for attrname, size in sizes.items():
    2.83          priority = "<instance>" in objkinds[attrname] and 0.5 or 1
    2.84          occupied = len(attrs[attrname])
    2.85 -        key = (priority * size, size, len(all_objtypes) - occupied, attrname)
    2.86 +        key = (priority * size, size, len(all_refs) - occupied, attrname)
    2.87          rsizes.append(key)
    2.88  
    2.89      rsizes.sort()
    2.90 @@ -775,20 +780,20 @@
    2.91      # Make a matrix of attributes.
    2.92  
    2.93      matrix = {}
    2.94 -    for attrname, objtypes in attrs.items():
    2.95 +    for attrname, refs in attrs.items():
    2.96  
    2.97          # Traverse the object types, adding the attribute name if the object
    2.98          # type supports the attribute, adding None otherwise.
    2.99  
   2.100          row = []
   2.101 -        for objtype in all_objtypes:
   2.102 -            if objtype in objtypes:
   2.103 +        for ref in all_refs:
   2.104 +            if ref in refs:
   2.105                  row.append(attrname)
   2.106              else:
   2.107                  row.append(None)
   2.108          matrix[attrname] = row
   2.109  
   2.110 -    return matrix, all_objtypes, rsizes
   2.111 +    return matrix, all_refs, rsizes
   2.112  
   2.113  def get_parameters_and_sizes(d):
   2.114