1.1 --- a/generator.py Tue Mar 21 01:15:38 2017 +0100
1.2 +++ b/generator.py Tue Mar 21 18:08:44 2017 +0100
1.3 @@ -19,7 +19,7 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 -from common import CommonOutput, copy
1.8 +from common import CommonOutput, copy, indent
1.9 from encoders import encode_code, \
1.10 encode_function_pointer, \
1.11 encode_instantiator_pointer, \
1.12 @@ -44,6 +44,7 @@
1.13
1.14 function_type = "__builtins__.core.function"
1.15 none_type = "__builtins__.none.NoneType"
1.16 + int_type = "__builtins__.int.int"
1.17 string_type = "__builtins__.str.string"
1.18 type_type = "__builtins__.core.type"
1.19 unicode_type = "__builtins__.unicode.utf8string"
1.20 @@ -359,6 +360,10 @@
1.21 for constant, n in self.optimiser.constants.items():
1.22 self.make_literal_constant(f_decls, f_defs, n, constant)
1.23
1.24 + # Generate pre-allocated objects.
1.25 +
1.26 + self.make_preallocated_objects(f_decls, f_defs)
1.27 +
1.28 # Finish the main source file.
1.29
1.30 self.write_main_program(f_code, f_signatures)
1.31 @@ -494,6 +499,48 @@
1.32 finally:
1.33 f_instancepos.close()
1.34
1.35 + def make_preallocated_objects(self, f_decls, f_defs):
1.36 +
1.37 + """
1.38 + Write pre-allocated object declarations to 'f_decls' and definitions to
1.39 + 'f_defs'.
1.40 + """
1.41 +
1.42 + ref = Reference("<instance>", self.int_type)
1.43 + table_name = encode_tablename(ref.get_kind(), ref.get_origin())
1.44 + attrs = self.get_instance_attributes_for_reference(ref)
1.45 + specific_instance_type = encode_symbol("inst", self.int_type)
1.46 +
1.47 + integers = []
1.48 + integer_cache_size = 256
1.49 + i = 0
1.50 +
1.51 + while i < integer_cache_size:
1.52 + attrs["__data__"] = i
1.53 + structure = []
1.54 + self.populate_structure(ref, attrs, ref.get_kind(), structure)
1.55 + integers.append(indent(" ", self.get_structure_definition(table_name, structure)))
1.56 + i += 1
1.57 +
1.58 + # Generate an array of specific instances.
1.59 +
1.60 + print >>f_defs, """\
1.61 +%s __integer_cache[%d] = {
1.62 +%s
1.63 + };""" % (specific_instance_type, integer_cache_size, ",\n ".join(integers))
1.64 +
1.65 + # Generate a declaration for the specific instance type.
1.66 +
1.67 + structure_size = encode_size("<instance>", self.int_type)
1.68 + self.write_instance_structure(f_decls, self.int_type, structure_size, "inst")
1.69 +
1.70 + # Generate declarations for the size of the array and the array itself.
1.71 +
1.72 + print >>f_decls, """\
1.73 +#define __INTEGER_CACHE_SIZE %d
1.74 +%s __integer_cache[%d];""" % (integer_cache_size, specific_instance_type,
1.75 + integer_cache_size)
1.76 +
1.77 def make_literal_constant(self, f_decls, f_defs, n, constant):
1.78
1.79 """
1.80 @@ -531,8 +578,8 @@
1.81 """
1.82 Write constant details to 'f_decls' (to declare a structure) and to
1.83 'f_defs' (to define the contents) for the constant described by 'ref'
1.84 - having the given 'path' and 'structure_name' (for the constant structure
1.85 - itself).
1.86 + having the given 'const_path' (used to refer to the structure using an
1.87 + attribute) and 'structure_name' (for the constant structure itself).
1.88
1.89 The additional 'data' and 'encoding' are used to describe specific
1.90 values.
1.91 @@ -541,9 +588,7 @@
1.92 # Obtain the attributes.
1.93
1.94 cls = ref.get_origin()
1.95 - indexes = self.optimiser.attr_table[ref]
1.96 - attrnames = self.get_attribute_names(indexes)
1.97 - attrs = self.get_instance_attributes(cls, attrnames)
1.98 + attrs = self.get_instance_attributes_for_reference(ref)
1.99
1.100 # Set the data, if provided.
1.101
1.102 @@ -595,8 +640,9 @@
1.103
1.104 # Define a macro for the constant.
1.105
1.106 - attr_name = encode_path(const_path)
1.107 - print >>f_decls, "#define %s __ATTRVALUE(&%s)" % (attr_name, structure_name)
1.108 + if const_path:
1.109 + print >>f_decls, "#define %s __ATTRVALUE(&%s)" % (
1.110 + encode_path(const_path), structure_name)
1.111
1.112 def make_parameter_table(self, f_decls, f_defs, argmin, parameters):
1.113
1.114 @@ -740,11 +786,12 @@
1.115 """ % (table_name, min_parameters, max_parameters, structure_size,
1.116 ",\n ".join(members))
1.117
1.118 - def write_instance_structure(self, f_decls, path, structure_size):
1.119 + def write_instance_structure(self, f_decls, path, structure_size, prefix="obj"):
1.120
1.121 """
1.122 Write a declaration to 'f_decls' for the object having the given 'path'
1.123 - and the given 'structure_size'.
1.124 + and the given 'structure_size'. The optional 'prefix' can be used to
1.125 + modify the declared type.
1.126 """
1.127
1.128 # Write an instance-specific type definition for instances of classes.
1.129 @@ -756,7 +803,7 @@
1.130 __pos pos;
1.131 __attr attrs[%s];
1.132 } %s;
1.133 -""" % (structure_size, encode_symbol("obj", path))
1.134 +""" % (structure_size, encode_symbol(prefix, path))
1.135
1.136 def write_structure(self, f_decls, f_defs, structure_name, table_name, structure, path=None):
1.137
1.138 @@ -769,19 +816,28 @@
1.139 if f_decls:
1.140 print >>f_decls, "extern __obj %s;\n" % encode_path(structure_name)
1.141
1.142 + structure_details = self.get_structure_definition(table_name, structure, path)
1.143 + print >>f_defs, """\
1.144 +__obj %s = %s;""" % (encode_path(structure_name), structure_details)
1.145 +
1.146 + def get_structure_definition(self, table_name, structure, path=None):
1.147 +
1.148 + """
1.149 + Return a structure employing 'table_name', the given 'structure'
1.150 + members, and any identifying static 'path'.
1.151 + """
1.152 +
1.153 is_class = path and self.importer.get_object(path).has_kind("<class>")
1.154 pos = is_class and encode_pos(encode_type_attribute(path)) or str(self.instancepos)
1.155
1.156 - print >>f_defs, """\
1.157 -__obj %s = {
1.158 + return """\
1.159 +{
1.160 &%s,
1.161 %s,
1.162 {
1.163 %s
1.164 - }};
1.165 -""" % (
1.166 - encode_path(structure_name), table_name, pos,
1.167 - ",\n ".join(structure))
1.168 + }
1.169 +}""" % (table_name, pos, ",\n ".join(structure))
1.170
1.171 def get_argument_limits(self, path):
1.172
1.173 @@ -842,6 +898,18 @@
1.174
1.175 return attrs
1.176
1.177 + def get_instance_attributes_for_reference(self, ref):
1.178 +
1.179 + """
1.180 + Return a mapping of attribute names to references for attributes
1.181 + belonging to instances of the given 'ref' referencing a class.
1.182 + """
1.183 +
1.184 + cls = ref.get_origin()
1.185 + indexes = self.optimiser.attr_table[ref]
1.186 + attrnames = self.get_attribute_names(indexes)
1.187 + return self.get_instance_attributes(cls, attrnames)
1.188 +
1.189 def get_instance_attributes(self, name, attrnames):
1.190
1.191 """