1.1 --- a/generator.py Mon Feb 13 16:03:52 2017 +0100
1.2 +++ b/generator.py Mon Feb 13 16:55:30 2017 +0100
1.3 @@ -217,7 +217,7 @@
1.4 # Define special attributes.
1.5
1.6 attrs["__fn__"] = path
1.7 - attrs["__args__"] = encode_size("pmin", path)
1.8 + attrs["__args__"] = path
1.9
1.10 self.populate_structure(Reference(kind, path), attrs, kind, structure)
1.11
1.12 @@ -270,7 +270,7 @@
1.13 # Set a special callable attribute on the instance.
1.14
1.15 function_instance_attrs["__fn__"] = path
1.16 - function_instance_attrs["__args__"] = encode_size("pmin", path)
1.17 + function_instance_attrs["__args__"] = path
1.18
1.19 structure = self.populate_function(path, function_instance_attrs)
1.20 self.write_structure(f_decls, f_defs, path, table_name, structure)
1.21 @@ -286,22 +286,48 @@
1.22
1.23 print >>f_signatures, "__attr %s(__attr args[]);" % encode_function_pointer(path)
1.24
1.25 + # Generate parameter table size data.
1.26 +
1.27 + min_parameters = {}
1.28 + max_parameters = {}
1.29 + size_parameters = {}
1.30 +
1.31 # Consolidate parameter tables for instantiators and functions.
1.32
1.33 parameter_tables = set()
1.34
1.35 for path, function_path in self.callables.items():
1.36 + argmin, argmax = self.get_argument_limits(function_path)
1.37 +
1.38 + # Obtain the parameter table members.
1.39 +
1.40 parameters = self.optimiser.parameters[function_path]
1.41 if not parameters:
1.42 parameters = ()
1.43 else:
1.44 parameters = tuple(parameters)
1.45 - parameter_tables.add(parameters)
1.46 +
1.47 + # Define each table in terms of the members and the minimum
1.48 + # number of arguments.
1.49 +
1.50 + parameter_tables.add((argmin, parameters))
1.51 + signature = self.get_parameter_signature(argmin, parameters)
1.52 +
1.53 + # Record the minimum number of arguments, the maximum number,
1.54 + # and the size of the table.
1.55 +
1.56 + min_parameters[signature] = argmin
1.57 + max_parameters[signature] = argmax
1.58 + size_parameters[signature] = len(parameters)
1.59 +
1.60 + self.write_size_constants(f_consts, "pmin", min_parameters, 0)
1.61 + self.write_size_constants(f_consts, "pmax", max_parameters, 0)
1.62 + self.write_size_constants(f_consts, "psize", size_parameters, 0)
1.63
1.64 # Generate parameter tables for distinct function signatures.
1.65
1.66 - for parameters in parameter_tables:
1.67 - self.make_parameter_table(f_decls, f_defs, parameters)
1.68 + for argmin, parameters in parameter_tables:
1.69 + self.make_parameter_table(f_decls, f_defs, argmin, parameters)
1.70
1.71 # Generate predefined constants.
1.72
1.73 @@ -340,27 +366,6 @@
1.74 for kind, sizes in size_tables:
1.75 self.write_size_constants(f_consts, kind, sizes, 0)
1.76
1.77 - # Generate parameter table size data.
1.78 -
1.79 - min_sizes = {}
1.80 - max_sizes = {}
1.81 -
1.82 - # Determine the minimum number of parameters for each
1.83 -
1.84 - for path in self.optimiser.parameters.keys():
1.85 - argmin, argmax = self.get_argument_limits(path)
1.86 - min_sizes[path] = argmin
1.87 -
1.88 - # Use the parameter table details to define the maximum number.
1.89 - # The context is already present in the collection.
1.90 -
1.91 - for parameters in parameter_tables:
1.92 - signature = self.get_parameter_signature(parameters)
1.93 - max_sizes[signature] = len(parameters)
1.94 -
1.95 - self.write_size_constants(f_consts, "pmin", min_sizes, 0)
1.96 - self.write_size_constants(f_consts, "pmax", max_sizes, 0)
1.97 -
1.98 # Generate parameter codes.
1.99
1.100 self.write_code_constants(f_consts, self.optimiser.all_paramnames, self.optimiser.arg_locations, "pcode", "ppos")
1.101 @@ -535,29 +540,32 @@
1.102 attr_name = encode_path(const_path)
1.103 print >>f_decls, "#define %s ((__attr) {.value=&%s})" % (attr_name, structure_name)
1.104
1.105 - def make_parameter_table(self, f_decls, f_defs, parameters):
1.106 + def make_parameter_table(self, f_decls, f_defs, argmin, parameters):
1.107
1.108 """
1.109 Write parameter table details to 'f_decls' (to declare a table) and to
1.110 - 'f_defs' (to define the contents) for the given 'parameters'.
1.111 + 'f_defs' (to define the contents) for the given 'argmin' and
1.112 + 'parameters'.
1.113 """
1.114
1.115 # Use a signature for the table name instead of a separate name for each
1.116 # function.
1.117
1.118 - signature = self.get_parameter_signature(parameters)
1.119 + signature = self.get_parameter_signature(argmin, parameters)
1.120 table_name = encode_tablename("<function>", signature)
1.121 - structure_size = encode_size("pmax", signature)
1.122 + min_parameters = encode_size("pmin", signature)
1.123 + max_parameters = encode_size("pmax", signature)
1.124 + structure_size = encode_size("psize", signature)
1.125
1.126 table = []
1.127 self.populate_parameter_table(parameters, table)
1.128 - self.write_parameter_table(f_decls, f_defs, table_name, structure_size, table)
1.129 + self.write_parameter_table(f_decls, f_defs, table_name, min_parameters, max_parameters, structure_size, table)
1.130
1.131 - def get_parameter_signature(self, parameters):
1.132 + def get_parameter_signature(self, argmin, parameters):
1.133
1.134 - "Return a signature for the given 'parameters'."
1.135 + "Return a signature for the given 'argmin' and 'parameters'."
1.136
1.137 - l = []
1.138 + l = [str(argmin)]
1.139 for parameter in parameters:
1.140 if parameter is None:
1.141 l.append("")
1.142 @@ -571,8 +579,9 @@
1.143 "Return the signature for the callable with the given 'path'."
1.144
1.145 function_path = self.callables[path]
1.146 + argmin, argmax = self.get_argument_limits(function_path)
1.147 parameters = self.optimiser.parameters[function_path]
1.148 - return self.get_parameter_signature(parameters)
1.149 + return self.get_parameter_signature(argmin, parameters)
1.150
1.151 def write_size_constants(self, f_consts, size_prefix, sizes, padding):
1.152
1.153 @@ -639,19 +648,22 @@
1.154 %s
1.155 }
1.156 };
1.157 -""" % (table_name, structure_size, ",\n ".join(table))
1.158 +""" % (table_name, structure_size,
1.159 + ",\n ".join(table))
1.160
1.161 - def write_parameter_table(self, f_decls, f_defs, table_name, structure_size, table):
1.162 + def write_parameter_table(self, f_decls, f_defs, table_name, min_parameters,
1.163 + max_parameters, structure_size, table):
1.164
1.165 """
1.166 Write the declarations to 'f_decls' and definitions to 'f_defs' for
1.167 - the object having the given 'table_name' and the given 'structure_size',
1.168 - with 'table' details used to populate the definition.
1.169 + the object having the given 'table_name' and the given 'min_parameters',
1.170 + 'max_parameters' and 'structure_size', with 'table' details used to
1.171 + populate the definition.
1.172 """
1.173
1.174 members = []
1.175 for t in table:
1.176 - members.append("{%s, %s}" % t)
1.177 + members.append("{.code=%s, .pos=%s}" % t)
1.178
1.179 print >>f_decls, "extern const __ptable %s;\n" % table_name
1.180
1.181 @@ -659,12 +671,15 @@
1.182
1.183 print >>f_defs, """\
1.184 const __ptable %s = {
1.185 - %s,
1.186 + .min=%s,
1.187 + .max=%s,
1.188 + .size=%s,
1.189 {
1.190 %s
1.191 }
1.192 };
1.193 -""" % (table_name, structure_size, ",\n ".join(members))
1.194 +""" % (table_name, min_parameters, max_parameters, structure_size,
1.195 + ",\n ".join(members))
1.196
1.197 def write_instance_structure(self, f_decls, path, structure_size):
1.198
1.199 @@ -886,7 +901,7 @@
1.200 signature = self.get_signature_for_callable(ref.get_origin())
1.201 ptable = encode_tablename("<function>", signature)
1.202
1.203 - structure.append("{.min=%s, .ptable=&%s}" % (attr, ptable))
1.204 + structure.append("{.ptable=&%s}" % ptable)
1.205 continue
1.206
1.207 # Special internal data member.