2.1 --- a/generator.py Tue Oct 25 23:06:37 2016 +0200
2.2 +++ b/generator.py Tue Oct 25 23:10:29 2016 +0200
2.3 @@ -21,7 +21,11 @@
2.4
2.5 from common import CommonOutput
2.6 from encoders import encode_bound_reference, encode_function_pointer, \
2.7 - encode_instantiator_pointer, encode_path, encode_symbol, \
2.8 + encode_instantiator_pointer, \
2.9 + encode_literal_constant, encode_literal_constant_member, \
2.10 + encode_literal_constant_value, encode_literal_reference, \
2.11 + encode_path, \
2.12 + encode_predefined_reference, encode_symbol, \
2.13 encode_type_attribute
2.14 from os import listdir
2.15 from os.path import isdir, join, split
2.16 @@ -59,6 +63,13 @@
2.17 "<instance>" : "i"
2.18 }
2.19
2.20 + predefined_constant_members = (
2.21 + ("__builtins__.bool", "False"),
2.22 + ("__builtins__.bool", "True"),
2.23 + ("__builtins__.none", "None"),
2.24 + ("__builtins__.notimplemented", "NotImplemented"),
2.25 + )
2.26 +
2.27 def __init__(self, importer, optimiser, output):
2.28 self.importer = importer
2.29 self.optimiser = optimiser
2.30 @@ -212,7 +223,12 @@
2.31 self.make_parameter_table(f_decls, f_defs, path, init_ref.get_origin())
2.32
2.33 self.populate_structure(Reference(kind, path), attrs, kind, structure)
2.34 - self.write_structure(f_decls, f_defs, path, table_name, structure_size, structure)
2.35 +
2.36 + if kind == "<class>":
2.37 + self.write_instance_structure(f_decls, path, structure_size)
2.38 +
2.39 + self.write_structure(f_decls, f_defs, path, table_name, structure_size, structure,
2.40 + kind == "<class>" and path)
2.41
2.42 # Record function instance details for function generation below.
2.43
2.44 @@ -261,8 +277,7 @@
2.45 # A bound version of a method.
2.46
2.47 structure = self.populate_function(path, function_instance_attrs, False)
2.48 - self.write_structure(f_decls, f_defs, path, table_name, structure_size, structure,
2.49 - encode_bound_reference(path))
2.50 + self.write_structure(f_decls, f_defs, encode_bound_reference(path), table_name, structure_size, structure)
2.51
2.52 # An unbound version of a method.
2.53
2.54 @@ -284,6 +299,16 @@
2.55
2.56 self.make_parameter_table(f_decls, f_defs, path, path)
2.57
2.58 + # Generate predefined constants.
2.59 +
2.60 + for path, name in self.predefined_constant_members:
2.61 + self.make_predefined_constant(f_decls, f_defs, path, name)
2.62 +
2.63 + # Generate literal constants.
2.64 +
2.65 + for value, n in self.optimiser.constants.items():
2.66 + self.make_literal_constant(f_decls, f_defs, n, value)
2.67 +
2.68 # Output more boilerplate.
2.69
2.70 print >>f_consts, """\
2.71 @@ -311,6 +336,76 @@
2.72 f_signatures.close()
2.73 f_code.close()
2.74
2.75 + def make_literal_constant(self, f_decls, f_defs, n, value):
2.76 +
2.77 + """
2.78 + Write literal constant details to 'f_decls' (to declare a structure) and
2.79 + to 'f_defs' (to define the contents) for the constant with the number
2.80 + 'n' with the given literal 'value'.
2.81 + """
2.82 +
2.83 + const_path = encode_literal_constant(n)
2.84 + structure_name = encode_literal_reference(n)
2.85 +
2.86 + # NOTE: This makes assumptions about the __builtins__ structure.
2.87 +
2.88 + typename = value.__class__.__name__
2.89 + ref = Reference("<instance>", "__builtins__.%s.%s" % (typename, typename))
2.90 +
2.91 + self.make_constant(f_decls, f_defs, ref, const_path, structure_name, value)
2.92 +
2.93 + def make_predefined_constant(self, f_decls, f_defs, path, name):
2.94 +
2.95 + """
2.96 + Write predefined constant details to 'f_decls' (to declare a structure)
2.97 + and to 'f_defs' (to define the contents) for the constant located in
2.98 + 'path' with the given 'name'.
2.99 + """
2.100 +
2.101 + # Determine the details of the constant.
2.102 +
2.103 + attr_path = "%s.%s" % (path, name)
2.104 + structure_name = encode_predefined_reference(attr_path)
2.105 + ref = self.importer.get_object(attr_path)
2.106 +
2.107 + self.make_constant(f_decls, f_defs, ref, attr_path, structure_name)
2.108 +
2.109 + def make_constant(self, f_decls, f_defs, ref, const_path, structure_name, data=None):
2.110 +
2.111 + """
2.112 + Write constant details to 'f_decls' (to declare a structure) and to
2.113 + 'f_defs' (to define the contents) for the constant described by 'ref'
2.114 + having the given 'path' and 'structure_name' (for the constant structure
2.115 + itself).
2.116 + """
2.117 +
2.118 + # Obtain the attributes.
2.119 +
2.120 + cls = ref.get_origin()
2.121 + indexes = self.optimiser.attr_table[ref]
2.122 + attrnames = self.get_attribute_names(indexes)
2.123 + attrs = self.get_instance_attributes(cls, attrnames)
2.124 +
2.125 + # Set the data, if provided.
2.126 +
2.127 + if data is not None:
2.128 + attrs["__data__"] = data
2.129 +
2.130 + # Define the structure details. An object is created for the constant,
2.131 + # but an attribute is provided, referring to the object, for access to
2.132 + # the constant in the program.
2.133 +
2.134 + structure = []
2.135 + table_name = encode_tablename("Instance", cls)
2.136 + structure_size = encode_size(self.structure_size_prefixes["<instance>"], cls)
2.137 + self.populate_structure(ref, attrs, ref.get_kind(), structure)
2.138 + self.write_structure(f_decls, f_defs, structure_name, table_name, structure_size, structure)
2.139 +
2.140 + # Define a macro for the constant.
2.141 +
2.142 + attr_name = encode_path(const_path)
2.143 + print >>f_decls, "#define %s ((__attr) {&%s, &%s})" % (attr_name, structure_name, structure_name)
2.144 +
2.145 def make_parameter_table(self, f_decls, f_defs, path, function_path):
2.146
2.147 """
2.148 @@ -405,17 +500,13 @@
2.149 table_name, structure_size,
2.150 ",\n ".join([("{%s, %s}" % t) for t in table]))
2.151
2.152 - def write_structure(self, f_decls, f_defs, path, table_name, structure_size, structure, copy=None):
2.153 + def write_instance_structure(self, f_decls, path, structure_size):
2.154
2.155 """
2.156 - Write the declarations to 'f_decls' and definitions to 'f_defs' for
2.157 - the object having the given 'path', the given 'table_name', and the
2.158 - given 'structure_size', with 'structure' details used to populate the
2.159 - definition.
2.160 + Write a declaration to 'f_decls' for the object having the given 'path'
2.161 + and the given 'structure_size'.
2.162 """
2.163
2.164 - print >>f_decls, "extern __obj %s;\n" % encode_path(path)
2.165 -
2.166 # Write an instance-specific type definition for instances of classes.
2.167 # See: templates/types.h
2.168
2.169 @@ -425,11 +516,21 @@
2.170 unsigned int pos;
2.171 __attr attrs[%s];
2.172 } %s;
2.173 -""" % (structure_size, encode_symbol("obj", copy or path))
2.174 +""" % (structure_size, encode_symbol("obj", path))
2.175 +
2.176 + def write_structure(self, f_decls, f_defs, structure_name, table_name, structure_size, structure, path=None):
2.177
2.178 - # Write the corresponding definition.
2.179 + """
2.180 + Write the declarations to 'f_decls' and definitions to 'f_defs' for
2.181 + the object having the given 'structure_name', the given 'table_name',
2.182 + and the given 'structure_size', with 'structure' details used to
2.183 + populate the definition.
2.184 + """
2.185
2.186 - is_class = self.importer.get_object(path).has_kind("<class>")
2.187 + if f_decls:
2.188 + print >>f_decls, "extern __obj %s;\n" % encode_path(structure_name)
2.189 +
2.190 + is_class = path and self.importer.get_object(path).has_kind("<class>")
2.191 pos = is_class and encode_symbol("pos", encode_type_attribute(path)) or "0"
2.192
2.193 print >>f_defs, """\
2.194 @@ -440,7 +541,7 @@
2.195 %s
2.196 }};
2.197 """ % (
2.198 - encode_path(copy or path), table_name, pos,
2.199 + encode_path(structure_name), table_name, pos,
2.200 ",\n ".join(structure))
2.201
2.202 def get_argument_limits(self, path):
2.203 @@ -595,6 +696,8 @@
2.204 else:
2.205 attr = attrs[attrname]
2.206
2.207 + # Special function pointer member.
2.208 +
2.209 if attrname == "__fn__":
2.210
2.211 # Provide bound method references and the unbound function
2.212 @@ -622,10 +725,19 @@
2.213 structure.append("{%s, .fn=%s}" % (bound_attr and ".b=&%s" % bound_attr or "0", attr))
2.214 continue
2.215
2.216 + # Special argument specification member.
2.217 +
2.218 elif attrname == "__args__":
2.219 structure.append("{.min=%s, .ptable=&%s}" % (attr, encode_tablename("Function", origin)))
2.220 continue
2.221
2.222 + # Special internal data member.
2.223 +
2.224 + elif attrname == "__data__":
2.225 + structure.append("{0, .%s=%s}" % (encode_literal_constant_member(attr),
2.226 + encode_literal_constant_value(attr)))
2.227 + continue
2.228 +
2.229 structure.append(self.encode_member(origin, attrname, attr, kind))
2.230
2.231 def encode_member(self, path, name, ref, structure_type):
2.232 @@ -650,6 +762,12 @@
2.233 constant_value = "const%d" % constant_number
2.234 return "{&%s, &%s} /* %s */" % (constant_value, constant_value, name)
2.235
2.236 + # Predefined constant references.
2.237 +
2.238 + if (path, name) in self.predefined_constant_members:
2.239 + attr_path = encode_predefined_reference("%s.%s" % (path, name))
2.240 + return "{&%s, &%s} /* %s */" % (attr_path, attr_path, name)
2.241 +
2.242 # General undetermined members.
2.243
2.244 if kind in ("<var>", "<instance>"):
4.1 --- a/translator.py Tue Oct 25 23:06:37 2016 +0200
4.2 +++ b/translator.py Tue Oct 25 23:10:29 2016 +0200
4.3 @@ -108,7 +108,7 @@
4.4 "A constant value reference in the translation."
4.5
4.6 def __str__(self):
4.7 - return "const%d" % self.number
4.8 + return encode_literal_constant(self.number)
4.9
4.10 class TrLiteralSequenceRef(results.LiteralSequenceRef, TranslationResult):
4.11
4.12 @@ -137,7 +137,7 @@
4.13 return False
4.14
4.15 def __repr__(self):
4.16 - return "AttrResult(%r, %r)" % (self.s, self.origin)
4.17 + return "AttrResult(%r, %r)" % (self.s, self.get_origin())
4.18
4.19 class PredefinedConstantRef(AttrResult):
4.20
4.21 @@ -147,7 +147,14 @@
4.22 self.value = value
4.23
4.24 def __str__(self):
4.25 - return self.value
4.26 + if self.value in ("False", "True"):
4.27 + return encode_path("__builtins__.bool.%s" % self.value)
4.28 + elif self.value == "None":
4.29 + return encode_path("__builtins__.none.%s" % self.value)
4.30 + elif self.value == "NotImplemented":
4.31 + return encode_path("__builtins__.notimplemented.%s" % self.value)
4.32 + else:
4.33 + return self.value
4.34
4.35 def __repr__(self):
4.36 return "PredefinedConstantRef(%r)" % self.value
4.37 @@ -831,13 +838,6 @@
4.38 if not args[argnum+1]:
4.39 args[argnum+1] = "__GETDEFAULT(%s, %d)" % (target, i)
4.40
4.41 - if None in args:
4.42 - print self.get_namespace_path()
4.43 - print n
4.44 - print expr
4.45 - print target
4.46 - print args
4.47 -
4.48 argstr = "__ARGS(%s)" % ", ".join(args)
4.49 kwargstr = kwargs and ("__ARGS(%s)" % ", ".join(kwargs)) or "0"
4.50 kwcodestr = kwcodes and ("__KWARGS(%s)" % ", ".join(kwcodes)) or "0"
4.51 @@ -845,13 +845,13 @@
4.52 # The callable is then obtained.
4.53
4.54 if target:
4.55 - callable = "__tmp_target"
4.56 + callable = target
4.57
4.58 elif self.always_callable:
4.59 - callable = "__load_via_object(__tmp_target, %s)" % \
4.60 + callable = "__load_via_object(__tmp_target.value, %s).fn" % \
4.61 encode_symbol("pos", "__fn__")
4.62 else:
4.63 - callable = "__check_and_load_via_object(__tmp_target, %s, %s)" % (
4.64 + callable = "__check_and_load_via_object(__tmp_target.value, %s, %s).fn" % (
4.65 encode_symbol("pos", "__fn__"), encode_symbol("code", "__fn__"))
4.66
4.67 stages.append(callable)
4.68 @@ -859,7 +859,7 @@
4.69 # With a known target, the function is obtained directly and called.
4.70
4.71 if target:
4.72 - output = "(\n%s.fn\n)(%s)" % (",\n".join(stages), argstr)
4.73 + output = "(\n%s\n)(%s)" % (",\n".join(stages), argstr)
4.74
4.75 # With unknown targets, the generic invocation function is applied to
4.76 # the callable and argument collections.
4.77 @@ -942,8 +942,7 @@
4.78 # Convert operator function names to references.
4.79
4.80 elif n.name.startswith("$op"):
4.81 - opname = n.name[len("$op"):]
4.82 - ref = self.importer.get_object("operator.%s" % opname)
4.83 + ref = self.importer.get_module(self.name).special.get(n.name)
4.84 return TrResolvedNameRef(n.name, ref)
4.85
4.86 # Get the appropriate name for the name reference, using the same method
4.87 @@ -1095,7 +1094,8 @@
4.88 print >>self.out, "__attr %s(__attr __args[])" % encode_function_pointer(name)
4.89 print >>self.out, "{"
4.90 self.indent += 1
4.91 - self.writeline("__attr __tmp_context, __tmp_target, __tmp_value;")
4.92 + self.writeline("__ref __tmp_context, __tmp_value;")
4.93 + self.writeline("__attr __tmp_target;")
4.94
4.95 # Obtain local names from parameters.
4.96