2.1 --- a/generator.py Tue Mar 21 01:15:38 2017 +0100
2.2 +++ b/generator.py Tue Mar 21 18:08:44 2017 +0100
2.3 @@ -19,7 +19,7 @@
2.4 this program. If not, see <http://www.gnu.org/licenses/>.
2.5 """
2.6
2.7 -from common import CommonOutput, copy
2.8 +from common import CommonOutput, copy, indent
2.9 from encoders import encode_code, \
2.10 encode_function_pointer, \
2.11 encode_instantiator_pointer, \
2.12 @@ -44,6 +44,7 @@
2.13
2.14 function_type = "__builtins__.core.function"
2.15 none_type = "__builtins__.none.NoneType"
2.16 + int_type = "__builtins__.int.int"
2.17 string_type = "__builtins__.str.string"
2.18 type_type = "__builtins__.core.type"
2.19 unicode_type = "__builtins__.unicode.utf8string"
2.20 @@ -359,6 +360,10 @@
2.21 for constant, n in self.optimiser.constants.items():
2.22 self.make_literal_constant(f_decls, f_defs, n, constant)
2.23
2.24 + # Generate pre-allocated objects.
2.25 +
2.26 + self.make_preallocated_objects(f_decls, f_defs)
2.27 +
2.28 # Finish the main source file.
2.29
2.30 self.write_main_program(f_code, f_signatures)
2.31 @@ -494,6 +499,48 @@
2.32 finally:
2.33 f_instancepos.close()
2.34
2.35 + def make_preallocated_objects(self, f_decls, f_defs):
2.36 +
2.37 + """
2.38 + Write pre-allocated object declarations to 'f_decls' and definitions to
2.39 + 'f_defs'.
2.40 + """
2.41 +
2.42 + ref = Reference("<instance>", self.int_type)
2.43 + table_name = encode_tablename(ref.get_kind(), ref.get_origin())
2.44 + attrs = self.get_instance_attributes_for_reference(ref)
2.45 + specific_instance_type = encode_symbol("inst", self.int_type)
2.46 +
2.47 + integers = []
2.48 + integer_cache_size = 256
2.49 + i = 0
2.50 +
2.51 + while i < integer_cache_size:
2.52 + attrs["__data__"] = i
2.53 + structure = []
2.54 + self.populate_structure(ref, attrs, ref.get_kind(), structure)
2.55 + integers.append(indent(" ", self.get_structure_definition(table_name, structure)))
2.56 + i += 1
2.57 +
2.58 + # Generate an array of specific instances.
2.59 +
2.60 + print >>f_defs, """\
2.61 +%s __integer_cache[%d] = {
2.62 +%s
2.63 + };""" % (specific_instance_type, integer_cache_size, ",\n ".join(integers))
2.64 +
2.65 + # Generate a declaration for the specific instance type.
2.66 +
2.67 + structure_size = encode_size("<instance>", self.int_type)
2.68 + self.write_instance_structure(f_decls, self.int_type, structure_size, "inst")
2.69 +
2.70 + # Generate declarations for the size of the array and the array itself.
2.71 +
2.72 + print >>f_decls, """\
2.73 +#define __INTEGER_CACHE_SIZE %d
2.74 +%s __integer_cache[%d];""" % (integer_cache_size, specific_instance_type,
2.75 + integer_cache_size)
2.76 +
2.77 def make_literal_constant(self, f_decls, f_defs, n, constant):
2.78
2.79 """
2.80 @@ -531,8 +578,8 @@
2.81 """
2.82 Write constant details to 'f_decls' (to declare a structure) and to
2.83 'f_defs' (to define the contents) for the constant described by 'ref'
2.84 - having the given 'path' and 'structure_name' (for the constant structure
2.85 - itself).
2.86 + having the given 'const_path' (used to refer to the structure using an
2.87 + attribute) and 'structure_name' (for the constant structure itself).
2.88
2.89 The additional 'data' and 'encoding' are used to describe specific
2.90 values.
2.91 @@ -541,9 +588,7 @@
2.92 # Obtain the attributes.
2.93
2.94 cls = ref.get_origin()
2.95 - indexes = self.optimiser.attr_table[ref]
2.96 - attrnames = self.get_attribute_names(indexes)
2.97 - attrs = self.get_instance_attributes(cls, attrnames)
2.98 + attrs = self.get_instance_attributes_for_reference(ref)
2.99
2.100 # Set the data, if provided.
2.101
2.102 @@ -595,8 +640,9 @@
2.103
2.104 # Define a macro for the constant.
2.105
2.106 - attr_name = encode_path(const_path)
2.107 - print >>f_decls, "#define %s __ATTRVALUE(&%s)" % (attr_name, structure_name)
2.108 + if const_path:
2.109 + print >>f_decls, "#define %s __ATTRVALUE(&%s)" % (
2.110 + encode_path(const_path), structure_name)
2.111
2.112 def make_parameter_table(self, f_decls, f_defs, argmin, parameters):
2.113
2.114 @@ -740,11 +786,12 @@
2.115 """ % (table_name, min_parameters, max_parameters, structure_size,
2.116 ",\n ".join(members))
2.117
2.118 - def write_instance_structure(self, f_decls, path, structure_size):
2.119 + def write_instance_structure(self, f_decls, path, structure_size, prefix="obj"):
2.120
2.121 """
2.122 Write a declaration to 'f_decls' for the object having the given 'path'
2.123 - and the given 'structure_size'.
2.124 + and the given 'structure_size'. The optional 'prefix' can be used to
2.125 + modify the declared type.
2.126 """
2.127
2.128 # Write an instance-specific type definition for instances of classes.
2.129 @@ -756,7 +803,7 @@
2.130 __pos pos;
2.131 __attr attrs[%s];
2.132 } %s;
2.133 -""" % (structure_size, encode_symbol("obj", path))
2.134 +""" % (structure_size, encode_symbol(prefix, path))
2.135
2.136 def write_structure(self, f_decls, f_defs, structure_name, table_name, structure, path=None):
2.137
2.138 @@ -769,19 +816,28 @@
2.139 if f_decls:
2.140 print >>f_decls, "extern __obj %s;\n" % encode_path(structure_name)
2.141
2.142 + structure_details = self.get_structure_definition(table_name, structure, path)
2.143 + print >>f_defs, """\
2.144 +__obj %s = %s;""" % (encode_path(structure_name), structure_details)
2.145 +
2.146 + def get_structure_definition(self, table_name, structure, path=None):
2.147 +
2.148 + """
2.149 + Return a structure employing 'table_name', the given 'structure'
2.150 + members, and any identifying static 'path'.
2.151 + """
2.152 +
2.153 is_class = path and self.importer.get_object(path).has_kind("<class>")
2.154 pos = is_class and encode_pos(encode_type_attribute(path)) or str(self.instancepos)
2.155
2.156 - print >>f_defs, """\
2.157 -__obj %s = {
2.158 + return """\
2.159 +{
2.160 &%s,
2.161 %s,
2.162 {
2.163 %s
2.164 - }};
2.165 -""" % (
2.166 - encode_path(structure_name), table_name, pos,
2.167 - ",\n ".join(structure))
2.168 + }
2.169 +}""" % (table_name, pos, ",\n ".join(structure))
2.170
2.171 def get_argument_limits(self, path):
2.172
2.173 @@ -842,6 +898,18 @@
2.174
2.175 return attrs
2.176
2.177 + def get_instance_attributes_for_reference(self, ref):
2.178 +
2.179 + """
2.180 + Return a mapping of attribute names to references for attributes
2.181 + belonging to instances of the given 'ref' referencing a class.
2.182 + """
2.183 +
2.184 + cls = ref.get_origin()
2.185 + indexes = self.optimiser.attr_table[ref]
2.186 + attrnames = self.get_attribute_names(indexes)
2.187 + return self.get_instance_attributes(cls, attrnames)
2.188 +
2.189 def get_instance_attributes(self, name, attrnames):
2.190
2.191 """