1.1 --- a/generator.py Thu Mar 02 23:57:55 2017 +0100
1.2 +++ b/generator.py Fri Mar 03 13:25:11 2017 +0100
1.3 @@ -79,21 +79,27 @@
1.4 self.optimiser = optimiser
1.5 self.output = output
1.6
1.7 - def to_output(self, debug=False, gc_sections=False):
1.8 + # The special instance indicator.
1.9 +
1.10 + self.instancepos = self.optimiser.attr_locations["__class__"]
1.11 +
1.12 + def to_output(self, reset=False, debug=False, gc_sections=False):
1.13
1.14 "Write the generated code."
1.15
1.16 self.check_output("debug=%r gc_sections=%r" % (debug, gc_sections))
1.17 self.write_structures()
1.18 self.write_scripts(debug, gc_sections)
1.19 - self.copy_templates()
1.20 + self.copy_templates(reset)
1.21
1.22 - def copy_templates(self):
1.23 + def copy_templates(self, reset=False):
1.24
1.25 "Copy template files to the generated output directory."
1.26
1.27 templates = join(split(__file__)[0], "templates")
1.28
1.29 + only_if_newer = not reset
1.30 +
1.31 for filename in listdir(templates):
1.32 target = self.output
1.33 pathname = join(templates, filename)
1.34 @@ -101,7 +107,7 @@
1.35 # Copy files into the target directory.
1.36
1.37 if not isdir(pathname):
1.38 - copy(pathname, target)
1.39 + copy(pathname, target, only_if_newer)
1.40
1.41 # Copy directories (such as the native code directory).
1.42
1.43 @@ -132,7 +138,7 @@
1.44 # Copy needed files.
1.45
1.46 for filename in needed:
1.47 - copy(join(pathname, filename), target)
1.48 + copy(join(pathname, filename), target, only_if_newer)
1.49
1.50 # Remove superfluous files.
1.51
1.52 @@ -429,8 +435,8 @@
1.53
1.54 "Write scripts used to build the program."
1.55
1.56 - f_native = open(join(self.output, "native.mk"), "w")
1.57 - f_modules = open(join(self.output, "modules.mk"), "w")
1.58 + # Options affect compiling and linking.
1.59 +
1.60 f_options = open(join(self.output, "options.mk"), "w")
1.61 try:
1.62 if debug:
1.63 @@ -439,6 +445,15 @@
1.64 if gc_sections:
1.65 print >>f_options, "include gc_sections.mk"
1.66
1.67 + finally:
1.68 + f_options.close()
1.69 +
1.70 + # Native and module definitions divide the program modules into native
1.71 + # and generated code.
1.72 +
1.73 + f_native = open(join(self.output, "native.mk"), "w")
1.74 + f_modules = open(join(self.output, "modules.mk"), "w")
1.75 + try:
1.76 # Identify modules used by the program.
1.77
1.78 native_modules = [join("native", "common.c")]
1.79 @@ -460,7 +475,22 @@
1.80 finally:
1.81 f_native.close()
1.82 f_modules.close()
1.83 - f_options.close()
1.84 +
1.85 + # Instance position configuration uses the position of the ubiquitous
1.86 + # __class__ attribute as a means of indicating that an object is an
1.87 + # instance. Classes employ special identifying attributes that are
1.88 + # positioned elsewhere and thus cannot be in the same location as the
1.89 + # __class__ attribute.
1.90 +
1.91 + f_instancepos = open(join(self.output, "instancepos.h"), "w")
1.92 + try:
1.93 + print >>f_instancepos, """\
1.94 +#ifndef __INSTANCEPOS
1.95 +#define __INSTANCEPOS %d
1.96 +#endif
1.97 +""" % self.instancepos
1.98 + finally:
1.99 + f_instancepos.close()
1.100
1.101 def make_literal_constant(self, f_decls, f_defs, n, constant):
1.102
1.103 @@ -738,7 +768,7 @@
1.104 print >>f_decls, "extern __obj %s;\n" % encode_path(structure_name)
1.105
1.106 is_class = path and self.importer.get_object(path).has_kind("<class>")
1.107 - pos = is_class and encode_pos(encode_type_attribute(path)) or "0"
1.108 + pos = is_class and encode_pos(encode_type_attribute(path)) or str(self.instancepos)
1.109
1.110 print >>f_defs, """\
1.111 __obj %s = {