1.1 --- a/generator.py Wed Jul 11 23:53:09 2018 +0200
1.2 +++ b/generator.py Thu Jul 12 00:15:16 2018 +0200
1.3 @@ -29,6 +29,7 @@
1.4 encode_path, encode_pcode, encode_pos, encode_ppos, \
1.5 encode_predefined_reference, encode_size, \
1.6 encode_symbol, encode_tablename, \
1.7 + encode_trailing_area, \
1.8 encode_type_attribute, decode_type_attribute, \
1.9 is_type_attribute
1.10 from os import listdir, mkdir, remove
1.11 @@ -42,6 +43,7 @@
1.12 # NOTE: These must be synchronised with the library.
1.13
1.14 dict_type = "__builtins__.dict.dict"
1.15 + float_type = "__builtins__.float.float"
1.16 function_type = "__builtins__.core.function"
1.17 int_type = "__builtins__.int.int"
1.18 list_type = "__builtins__.list.list"
1.19 @@ -64,6 +66,12 @@
1.20 dict_type, list_type, tuple_type
1.21 )
1.22
1.23 + # Data types with a trailing data member of the given native types.
1.24 +
1.25 + trailing_data_types = {
1.26 + float_type : "double",
1.27 + }
1.28 +
1.29 def __init__(self, importer, optimiser, output):
1.30
1.31 """
1.32 @@ -219,6 +227,7 @@
1.33
1.34 if kind != "<instance>":
1.35 structure = []
1.36 + trailing = []
1.37 attrs = self.get_static_attributes(kind, path, attrnames)
1.38
1.39 # Set a special instantiator on the class.
1.40 @@ -244,12 +253,13 @@
1.41 attrs["__args__"] = path
1.42
1.43 self.populate_structure(Reference(kind, path), attrs, kind, structure)
1.44 + self.populate_trailing(Reference(kind, path), attrs, trailing)
1.45
1.46 if kind == "<class>":
1.47 self.write_instance_structure(f_decls, path, structure_size)
1.48
1.49 - self.write_structure(f_decls, f_defs, path, table_name, structure,
1.50 - kind == "<class>" and path)
1.51 + self.write_structure(f_decls, f_defs, path, table_name,
1.52 + structure, trailing, ref)
1.53
1.54 # Record function instance details for function generation below.
1.55
1.56 @@ -297,7 +307,7 @@
1.57 function_instance_attrs["__args__"] = path
1.58
1.59 structure = self.populate_function(path, function_instance_attrs)
1.60 - self.write_structure(f_decls, f_defs, path, table_name, structure)
1.61 + self.write_structure(f_decls, f_defs, path, table_name, structure, [], Reference("<function>", path))
1.62
1.63 # Functions with defaults need to declare instance structures.
1.64
1.65 @@ -411,6 +421,12 @@
1.66 self.optimiser.locations,
1.67 "code", "pos", encode_code, encode_pos)
1.68
1.69 + # Generate trailing data macros of the form...
1.70 + # #define __TRAILING_typename nativetype trailing;
1.71 +
1.72 + for name, member_type in self.trailing_data_types.items():
1.73 + print >>f_consts, "#define %s %s trailing;" % (encode_symbol("TRAILING", name), member_type)
1.74 +
1.75 # Generate macros for calls.
1.76
1.77 all_max_parameters = list(all_max_parameters)
1.78 @@ -617,7 +633,16 @@
1.79 # Set the data, if provided.
1.80
1.81 if data is not None:
1.82 - attrs["__data__"] = data
1.83 +
1.84 + # Data retained by special attribute.
1.85 +
1.86 + if attrs.has_key("__data__"):
1.87 + attrs["__data__"] = data
1.88 +
1.89 + # Data retained by a trailing data area.
1.90 +
1.91 + elif attrs.has_key("__trailing__"):
1.92 + attrs["__trailing__"] = data
1.93
1.94 # Also set a key for dynamic attribute lookup, if a string.
1.95
1.96 @@ -658,9 +683,12 @@
1.97 # the constant in the program.
1.98
1.99 structure = []
1.100 + trailing = []
1.101 table_name = encode_tablename("<instance>", cls)
1.102 self.populate_structure(ref, attrs, ref.get_kind(), structure)
1.103 - self.write_structure(f_decls, f_defs, structure_name, table_name, structure)
1.104 + self.populate_trailing(ref, attrs, trailing)
1.105 + self.write_structure(f_decls, f_defs, structure_name, table_name,
1.106 + structure, trailing, ref)
1.107
1.108 # Define a macro for the constant.
1.109
1.110 @@ -819,38 +847,51 @@
1.111 # Write an instance-specific type definition for instances of classes.
1.112 # See: templates/types.h
1.113
1.114 + trailing_area = path in self.trailing_data_types and encode_trailing_area(path) or ""
1.115 +
1.116 print >>f_decls, """\
1.117 typedef struct {
1.118 const __table * table;
1.119 __pos pos;
1.120 __attr attrs[%s];
1.121 +%s
1.122 } %s;
1.123 -""" % (structure_size, encode_symbol("obj", path))
1.124 +""" % (structure_size, trailing_area, encode_symbol("obj", path))
1.125
1.126 - def write_structure(self, f_decls, f_defs, structure_name, table_name, structure, path=None):
1.127 + def write_structure(self, f_decls, f_defs, structure_name, table_name,
1.128 + structure, trailing, ref):
1.129
1.130 """
1.131 Write the declarations to 'f_decls' and definitions to 'f_defs' for
1.132 the object having the given 'structure_name', the given 'table_name',
1.133 - and the given 'structure' details used to populate the definition.
1.134 + the given 'structure' details and any 'trailing' member details, used to
1.135 + populate the definition.
1.136 """
1.137
1.138 + origin = ref.get_origin()
1.139 + pos = ref.has_kind("<class>") and encode_pos(encode_type_attribute(origin)) or str(self.instancepos)
1.140 +
1.141 + obj_type = ref.has_kind("<instance>") and encode_symbol("obj", origin) or "__obj"
1.142 + obj_name = encode_path(structure_name)
1.143 +
1.144 if f_decls:
1.145 - print >>f_decls, "extern __obj %s;\n" % encode_path(structure_name)
1.146 -
1.147 - is_class = path and self.importer.get_object(path).has_kind("<class>")
1.148 - pos = is_class and encode_pos(encode_type_attribute(path)) or str(self.instancepos)
1.149 + print >>f_decls, "extern %s %s;\n" % (obj_type, obj_name)
1.150
1.151 print >>f_defs, """\
1.152 -__obj %s = {
1.153 +%s %s = {
1.154 &%s,
1.155 %s,
1.156 {
1.157 %s
1.158 - }};
1.159 + },
1.160 + %s
1.161 + };
1.162 """ % (
1.163 - encode_path(structure_name), table_name, pos,
1.164 - ",\n ".join(structure))
1.165 + obj_type, obj_name,
1.166 + table_name,
1.167 + pos,
1.168 + ",\n ".join(structure),
1.169 + trailing and ",\n ".join(trailing) or "")
1.170
1.171 def get_argument_limits(self, path):
1.172
1.173 @@ -910,6 +951,12 @@
1.174 continue
1.175 const = consts.get(attrname)
1.176 attrs[attrname] = const or Reference("<var>", "%s.%s" % (name, attrname))
1.177 +
1.178 + # Instances with trailing data.
1.179 +
1.180 + if name in self.trailing_data_types:
1.181 + attrs["__trailing__"] = Reference("<var>", "%s.__trailing__" % name)
1.182 +
1.183 return attrs
1.184
1.185 def populate_table(self, path, table):
1.186 @@ -1101,6 +1148,21 @@
1.187
1.188 structure.append(self.encode_member(origin, attrname, attr, kind))
1.189
1.190 + def populate_trailing(self, ref, attrs, trailing):
1.191 +
1.192 + """
1.193 + For the structure having the given 'ref', whose members are provided by
1.194 + the 'attrs' mapping, adding entries to the 'trailing' member collection.
1.195 + """
1.196 +
1.197 + structure_ref = self.get_target_structure(ref)
1.198 +
1.199 + # Instances with trailing data.
1.200 +
1.201 + if structure_ref.get_kind() == "<instance>" and \
1.202 + structure_ref.get_origin() in self.trailing_data_types:
1.203 + trailing.append(encode_literal_constant_value(attrs["__trailing__"]))
1.204 +
1.205 def get_target_structure(self, ref):
1.206
1.207 "Return the target structure type and reference for 'ref'."
1.208 @@ -1154,22 +1216,22 @@
1.209
1.210 if kind == "<instance>" and origin == self.none_type:
1.211 attr_path = encode_predefined_reference(self.none_value)
1.212 - return "{.value=&%s} /* %s */" % (attr_path, name)
1.213 + return "{.value=(__ref) &%s} /* %s */" % (attr_path, name)
1.214
1.215 # Predefined constant members.
1.216
1.217 if (path, name) in self.predefined_constant_members:
1.218 attr_path = encode_predefined_reference("%s.%s" % (path, name))
1.219 - return "{.value=&%s} /* %s */" % (attr_path, name)
1.220 + return "{.value=(__ref) &%s} /* %s */" % (attr_path, name)
1.221
1.222 # General undetermined members.
1.223
1.224 if kind in ("<var>", "<instance>"):
1.225 attr_path = encode_predefined_reference(self.none_value)
1.226 - return "{.value=&%s} /* %s */" % (attr_path, name)
1.227 + return "{.value=(__ref) &%s} /* %s */" % (attr_path, name)
1.228
1.229 else:
1.230 - return "{.value=&%s}" % encode_path(origin)
1.231 + return "{.value=(__ref) &%s}" % encode_path(origin)
1.232
1.233 def append_defaults(self, path, structure):
1.234