# HG changeset patch # User Paul Boddie # Date 1481069136 -3600 # Node ID 61776a5a0e16de99ffdeab64d2f381dfea704e06 # Parent d6b253d49e991e3b01f76e63445310435b07f110 Associate constant name information with references so that structure members such as function instance default members can be generated statically, thus eliminating unnecessary structure initialisation in the translated code. Improved the determination of dynamic functions in the importer to consider only non-constant defaults. diff -r d6b253d49e99 -r 61776a5a0e16 common.py --- a/common.py Tue Dec 06 22:58:16 2016 +0100 +++ b/common.py Wed Dec 07 01:05:36 2016 +0100 @@ -227,7 +227,7 @@ # Return a reference for the constant. objpath = self.get_object_path(constant_name) - name_ref = ConstantValueRef(constant_name, ref.instance_of(), value) + name_ref = ConstantValueRef(constant_name, ref.instance_of(objpath), value) # Record the value and type for the constant. diff -r d6b253d49e99 -r 61776a5a0e16 generator.py --- a/generator.py Tue Dec 06 22:58:16 2016 +0100 +++ b/generator.py Wed Dec 07 01:05:36 2016 +0100 @@ -833,13 +833,13 @@ # References to constant literals. - if kind == "": - attr_path = "%s.%s" % (path, name) + if kind == "" and ref.is_constant_alias(): + alias = ref.get_name() # Obtain a constant value directly assigned to the attribute. - if self.optimiser.constant_numbers.has_key(attr_path): - constant_number = self.optimiser.constant_numbers[attr_path] + if self.optimiser.constant_numbers.has_key(alias): + constant_number = self.optimiser.constant_numbers[alias] constant_value = "__const%d" % constant_number return "%s /* %s */" % (constant_value, name) diff -r d6b253d49e99 -r 61776a5a0e16 importer.py --- a/importer.py Tue Dec 06 22:58:16 2016 +0100 +++ b/importer.py Wed Dec 07 01:05:36 2016 +0100 @@ -477,8 +477,28 @@ need initialising before the callable can be used. """ - return ref.has_kind("") and self.function_defaults.get(ref.get_origin()) or \ - ref.has_kind("") and self.function_defaults.get("%s.__init__" % ref.get_origin()) + # Find the function or method associated with the reference. + + if ref.has_kind(""): + origin = ref.get_origin() + elif ref.has_kind(""): + origin = "%s.__init__" % ref.get_origin() + else: + return False + + # Find any defaults for the function or method. + + defaults = self.function_defaults.get(origin) + if not defaults: + return False + + # Identify non-constant defaults. + + for name, ref in defaults: + if not ref.is_constant_alias(): + return True + + return False def order_modules(self): diff -r d6b253d49e99 -r 61776a5a0e16 referencing.py --- a/referencing.py Tue Dec 06 22:58:16 2016 +0100 +++ b/referencing.py Wed Dec 07 01:05:36 2016 +0100 @@ -125,11 +125,14 @@ static = self.static() return static and static.origin or None - def instance_of(self): + def instance_of(self, alias=None): - "Return a reference to an instance of the referenced class." + """ + Return a reference to an instance of the referenced class, indicating an + 'alias' for the instance if specified. + """ - return self.has_kind("") and Reference("", self.origin) or None + return self.has_kind("") and Reference("", self.origin, alias) or None def as_var(self): @@ -196,6 +199,13 @@ return ancestors + def is_constant_alias(self): + + "Return whether this reference is an alias for a constant." + + name = self.get_name() + return name and name.rsplit(".")[-1].startswith("$c") + def get_types(self): "Return class, instance-only and module types for this reference." diff -r d6b253d49e99 -r 61776a5a0e16 results.py --- a/results.py Tue Dec 06 22:58:16 2016 +0100 +++ b/results.py Wed Dec 07 01:05:36 2016 +0100 @@ -130,6 +130,9 @@ def has_kind(self, kinds): return self.ref and self.ref.has_kind(kinds) + def is_constant_alias(self): + return self.ref and self.ref.is_constant_alias() + class ResolvedNameRef(ResolvedRef, NameRef): "A resolved name-based reference." diff -r d6b253d49e99 -r 61776a5a0e16 translator.py --- a/translator.py Tue Dec 06 22:58:16 2016 +0100 +++ b/translator.py Wed Dec 07 01:05:36 2016 +0100 @@ -98,9 +98,9 @@ # Determine whether a qualified name is involved. - t = (self.get_name() or self.name).rsplit(".", 1) + t = (not self.is_constant_alias() and self.get_name() or self.name).rsplit(".", 1) parent = len(t) > 1 and t[0] or None - attrname = encode_path(t[-1]) + attrname = t[-1] and encode_path(t[-1]) # Assignments. @@ -1021,7 +1021,10 @@ else: continue - if name_ref: + # Generate default initialisers except when constants are employed. + # Constants should be used when populating the function structures. + + if name_ref and not isinstance(name_ref, TrConstantValueRef): defaults.append("__SETDEFAULT(%s, %s, %s)" % (instance_name, i, name_ref)) return defaults