Lichen

Changeset

640:439f4dc00e47
2017-02-28 Paul Boddie raw files shortlog changelog graph Renamed some variables for clarity and added some commentary.
optimiser.py (file)
     1.1 --- a/optimiser.py	Tue Feb 28 19:22:58 2017 +0100
     1.2 +++ b/optimiser.py	Tue Feb 28 22:08:02 2017 +0100
     1.3 @@ -308,13 +308,15 @@
     1.4                  attrnames = filter(lambda x: not x.startswith("$t"), attrnames)
     1.5                  self.all_attrs[(objkind, name)] = attrnames
     1.6  
     1.7 -        self.locations = get_allocated_locations(self.all_attrs, get_attributes_and_sizes)
     1.8 +        self.locations = get_allocated_locations(self.all_attrs,
     1.9 +            get_attributes_and_sizes)
    1.10  
    1.11      def populate_parameters(self):
    1.12  
    1.13          "Populate parameter tables using parameter information."
    1.14  
    1.15 -        self.arg_locations = [set()] + get_allocated_locations(self.importer.function_parameters, get_parameters_and_sizes)
    1.16 +        self.arg_locations = [set()] + get_allocated_locations(
    1.17 +            self.importer.function_parameters, get_parameters_and_sizes)
    1.18  
    1.19      def position_attributes(self):
    1.20  
    1.21 @@ -777,8 +779,13 @@
    1.22  def get_attributes_and_sizes(d):
    1.23  
    1.24      """
    1.25 -    Return a matrix of attributes, a list of type names corresponding to columns
    1.26 -    in the matrix, and a list of ranked sizes each indicating...
    1.27 +    Get attribute and size information for the object attributes defined by 'd'
    1.28 +    providing a mapping from (object kind, type name) to attribute names.
    1.29 +
    1.30 +    Return a matrix of attributes (each row entry consisting of column values
    1.31 +    providing attribute names, with value positions corresponding to types
    1.32 +    providing such attributes), a list of the type names corresponding to the
    1.33 +    columns in the matrix, and a list of ranked sizes each indicating...
    1.34  
    1.35       * a weighted size depending on the kind of object
    1.36       * the minimum size of an object employing an attribute
    1.37 @@ -790,15 +797,15 @@
    1.38      sizes = {}
    1.39      objkinds = {}
    1.40  
    1.41 -    for name, attrnames in d.items():
    1.42 -        objkind, _name = name
    1.43 +    for objtype, attrnames in d.items():
    1.44 +        objkind, _name = objtype
    1.45  
    1.46          for attrname in attrnames:
    1.47  
    1.48              # Record each type supporting the attribute.
    1.49  
    1.50              init_item(attrs, attrname, set)
    1.51 -            attrs[attrname].add(name)
    1.52 +            attrs[attrname].add(objtype)
    1.53  
    1.54              # Maintain a record of the smallest object size supporting the given
    1.55              # attribute.
    1.56 @@ -815,13 +822,13 @@
    1.57  
    1.58      # Obtain attribute details in order of size and occupancy.
    1.59  
    1.60 -    names = d.keys()
    1.61 +    all_objtypes = d.keys()
    1.62  
    1.63      rsizes = []
    1.64      for attrname, size in sizes.items():
    1.65          priority = "<instance>" in objkinds[attrname] and 0.5 or 1
    1.66          occupied = len(attrs[attrname])
    1.67 -        key = (priority * size, size, len(names) - occupied, attrname)
    1.68 +        key = (priority * size, size, len(all_objtypes) - occupied, attrname)
    1.69          rsizes.append(key)
    1.70  
    1.71      rsizes.sort()
    1.72 @@ -829,16 +836,20 @@
    1.73      # Make a matrix of attributes.
    1.74  
    1.75      matrix = {}
    1.76 -    for attrname, types in attrs.items():
    1.77 +    for attrname, objtypes in attrs.items():
    1.78 +
    1.79 +        # Traverse the object types, adding the attribute name if the object
    1.80 +        # type supports the attribute, adding None otherwise.
    1.81 +
    1.82          row = []
    1.83 -        for name in names:
    1.84 -            if name in types:
    1.85 +        for objtype in all_objtypes:
    1.86 +            if objtype in objtypes:
    1.87                  row.append(attrname)
    1.88              else:
    1.89                  row.append(None)
    1.90          matrix[attrname] = row
    1.91  
    1.92 -    return matrix, names, rsizes
    1.93 +    return matrix, all_objtypes, rsizes
    1.94  
    1.95  def get_parameters_and_sizes(d):
    1.96  
    1.97 @@ -912,26 +923,52 @@
    1.98      matrix, names, rsizes = fn(d)
    1.99      allocated = []
   1.100  
   1.101 -    x = 0
   1.102 -    while x < len(rsizes):
   1.103 -        weight, size, free, attrname = rsizes[x]
   1.104 +    # Try to allocate each attribute name in turn.
   1.105 +
   1.106 +    pos = 0
   1.107 +
   1.108 +    while pos < len(rsizes):
   1.109 +        weight, size, free, attrname = rsizes[pos]
   1.110 +
   1.111 +        # Obtain the object information for the attribute name.
   1.112 +
   1.113          base = matrix[attrname]
   1.114 -        y = x + 1
   1.115 +
   1.116 +        # Examine attribute names that follow in the ranking, attempting to
   1.117 +        # accumulate compatible attributes that can co-exist in the same
   1.118 +        # position within structures.
   1.119 +
   1.120 +        y = pos + 1
   1.121          while y < len(rsizes):
   1.122              _weight, _size, _free, _attrname = rsizes[y]
   1.123 +
   1.124 +            # Determine whether this attribute is supported by too many types
   1.125 +            # to co-exist.
   1.126 +
   1.127              occupied = len(names) - _free
   1.128              if occupied > free:
   1.129                  break
   1.130 +
   1.131 +            # Merge the attribute support for both this and the currently
   1.132 +            # considered attribute, testing for conflicts. Adopt the merged row
   1.133 +            # details if they do not conflict.
   1.134 +
   1.135              new = combine_rows(base, matrix[_attrname])
   1.136              if new:
   1.137                  del matrix[_attrname]
   1.138                  del rsizes[y]
   1.139                  base = new
   1.140                  free -= occupied
   1.141 +
   1.142 +            # Otherwise, look for other compatible attributes.
   1.143 +
   1.144              else:
   1.145                  y += 1
   1.146 +
   1.147 +        # Allocate the merged details at the current position.
   1.148 +
   1.149          allocated.append(base)
   1.150 -        x += 1
   1.151 +        pos += 1
   1.152  
   1.153      # Return the list of attribute names from each row of the allocated
   1.154      # attributes table.