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.