1.1 --- a/importer.py Tue Sep 06 17:18:11 2016 +0200
1.2 +++ b/importer.py Tue Sep 06 23:38:05 2016 +0200
1.3 @@ -336,32 +336,51 @@
1.4
1.5 "Resolve dependencies between modules."
1.6
1.7 - for d in [self.objects, self.all_name_references]:
1.8 - resolved = {}
1.9 + self.waiting = {}
1.10 +
1.11 + for module in self.modules.values():
1.12 +
1.13 + # Resolve all deferred references in each module.
1.14
1.15 - for name, ref in d.items():
1.16 - if ref.has_kind("<depends>"):
1.17 - found = self.find_dependency(ref)
1.18 - if found:
1.19 - resolved[name] = found
1.20 - else:
1.21 - print >>sys.stderr, "Name %s references an unknown object: %s" % (name, ref.get_origin())
1.22 + for ref in module.deferred:
1.23 + found = self.find_dependency(ref)
1.24 + if not found:
1.25 + print >>sys.stderr, "Module %s references an unknown object: %s" % (module.name, ref.get_origin())
1.26 +
1.27 + # Record the resolved names and identify required modules.
1.28
1.29 - # Record the resolved names and identify required modules.
1.30 + else:
1.31 + ref.mutate(found)
1.32 +
1.33 + # Find the providing module of this reference.
1.34 +
1.35 + provider = self.get_module_provider(ref)
1.36 + if provider:
1.37
1.38 - for name, ref in resolved.items():
1.39 - d[name] = ref
1.40 + module.required.add(provider)
1.41 + self.accessing_modules[provider].add(module.name)
1.42 +
1.43 + # Postpone any inclusion of the provider until this
1.44 + # module becomes required.
1.45
1.46 - # Find the providing module of this reference.
1.47 + if module.name not in self.required:
1.48 + init_item(self.waiting, module.name, set)
1.49 + self.waiting[module.name].add(provider)
1.50 +
1.51 + # Make this module required in the accessing module.
1.52
1.53 - module_name = self.get_module_provider(ref)
1.54 - if module_name:
1.55 - self.required.add(module_name)
1.56 + else:
1.57 + self.required.add(provider)
1.58 +
1.59 + for module_name in self.waiting.keys():
1.60 + self.require_providers(module_name)
1.61
1.62 - # Make this module required in all accessing modules.
1.63 -
1.64 - for accessor_name in self.accessing_modules[module_name]:
1.65 - self.modules[accessor_name].required.add(module_name)
1.66 + def require_providers(self, module_name):
1.67 + if module_name in self.required and self.waiting.has_key(module_name):
1.68 + for provider in self.waiting[module_name]:
1.69 + if provider not in self.required:
1.70 + self.required.add(provider)
1.71 + self.require_providers(provider)
1.72
1.73 def find_dependency(self, ref):
1.74
1.75 @@ -370,7 +389,7 @@
1.76 found = set()
1.77 while ref and ref.has_kind("<depends>") and not ref in found:
1.78 found.add(ref)
1.79 - ref = self.objects.get(ref.get_origin())
1.80 + ref = self.identify(ref.get_origin())
1.81 return ref
1.82
1.83 def get_module_provider(self, ref):
2.1 --- a/inspector.py Tue Sep 06 17:18:11 2016 +0200
2.2 +++ b/inspector.py Tue Sep 06 23:38:05 2016 +0200
2.3 @@ -130,12 +130,12 @@
2.4 if name in predefined_constants or in_function and name in self.function_locals[path]:
2.5 continue
2.6
2.7 - # Find local definitions (within static namespaces).
2.8 + # Find local definitions (within dynamic namespaces).
2.9
2.10 key = "%s.%s" % (path, name)
2.11 ref = self.get_resolved_object(key)
2.12 if ref:
2.13 - self.importer.all_name_references[key] = self.name_references[key] = ref.alias(key)
2.14 + self.importer.all_name_references[key] = self.name_references[key] = ref
2.15 continue
2.16
2.17 # Find global or built-in definitions.
2.18 @@ -789,6 +789,7 @@
2.19 # Attempt to get a reference.
2.20
2.21 ref = self.import_name_from_module(op, "operator")
2.22 + self.add_deferred(ref)
2.23
2.24 # Record the imported name and provide the resolved name reference.
2.25
3.1 --- a/modules.py Tue Sep 06 17:18:11 2016 +0200
3.2 +++ b/modules.py Tue Sep 06 23:38:05 2016 +0200
3.3 @@ -37,6 +37,7 @@
3.4
3.5 self.imports = set()
3.6 self.required = set()
3.7 + self.deferred = []
3.8
3.9 # Global name information.
3.10
3.11 @@ -207,7 +208,17 @@
3.12
3.13 "Set an object with the given 'name' and the given 'value'."
3.14
3.15 + # Decode any string value, with a new reference being returned even
3.16 + # given a provided reference.
3.17 +
3.18 ref = decode_reference(value, name)
3.19 + self.add_deferred(ref)
3.20 + self._set_object(name, ref)
3.21 +
3.22 + def _set_object(self, name, ref):
3.23 +
3.24 + # Determine how the object properties will be defined.
3.25 +
3.26 multiple = self.objects.has_key(name) and self.objects[name].get_kind() != ref.get_kind()
3.27 self.importer.objects[name] = self.objects[name] = multiple and ref.as_var() or ref
3.28
3.29 @@ -266,7 +277,9 @@
3.30 "Return a reference to the built-in with the given 'name'."
3.31
3.32 self.queue_module("__builtins__")
3.33 - return Reference("<depends>", "__builtins__.%s" % name)
3.34 + ref = Reference("<depends>", "__builtins__.%s" % name)
3.35 + self.deferred.append(ref)
3.36 + return ref
3.37
3.38 def get_builtin_class(self, name):
3.39
3.40 @@ -289,7 +302,9 @@
3.41 if self.objects.has_key(path):
3.42 return self.objects[path]
3.43 else:
3.44 - return Reference("<depends>", path)
3.45 + ref = Reference("<depends>", path)
3.46 + self.deferred.append(ref)
3.47 + return ref
3.48
3.49 def import_name_from_module(self, name, module_name):
3.50
3.51 @@ -299,6 +314,13 @@
3.52 self.queue_module(module_name)
3.53 return Reference("<depends>", "%s.%s" % (module_name, name))
3.54
3.55 + def add_deferred(self, ref):
3.56 +
3.57 + "Record 'ref' as a deferred reference."
3.58 +
3.59 + if ref.has_kind("<depends>"):
3.60 + self.deferred.append(ref)
3.61 +
3.62 class CachedModule(BasicModule):
3.63
3.64 "A cached module."
3.65 @@ -306,6 +328,16 @@
3.66 def __repr__(self):
3.67 return "CachedModule(%r, %r)" % (self.name, self.importer)
3.68
3.69 + def set_object(self, name, value=None):
3.70 +
3.71 + "Set an object with the given 'name' and the given 'value'."
3.72 +
3.73 + # Decode any string value, with a new reference being returned even
3.74 + # given a provided reference.
3.75 +
3.76 + ref = decode_reference(value, name)
3.77 + self._set_object(name, ref)
3.78 +
3.79 def to_cache(self, filename):
3.80
3.81 "Not actually writing the module back to 'filename'."
4.1 --- a/referencing.py Tue Sep 06 17:18:11 2016 +0200
4.2 +++ b/referencing.py Tue Sep 06 23:38:05 2016 +0200
4.3 @@ -137,6 +137,14 @@
4.4
4.5 return Reference(self.get_kind(), self.get_origin(), name)
4.6
4.7 + def mutate(self, ref):
4.8 +
4.9 + "Mutate this reference to have the same details as 'ref'."
4.10 +
4.11 + self.kind = ref.kind
4.12 + self.origin = ref.origin
4.13 + self.name = ref.name
4.14 +
4.15 def ancestors(self):
4.16
4.17 """
5.1 --- a/resolving.py Tue Sep 06 17:18:11 2016 +0200
5.2 +++ b/resolving.py Tue Sep 06 23:38:05 2016 +0200
5.3 @@ -35,7 +35,6 @@
5.4
5.5 "Resolve dependencies and complete definitions."
5.6
5.7 - self.resolve_members()
5.8 self.resolve_class_bases()
5.9 self.check_special()
5.10 self.check_names_used()
5.11 @@ -44,27 +43,6 @@
5.12 self.resolve_literals()
5.13 self.remove_redundant_accessors()
5.14
5.15 - def resolve_members(self):
5.16 -
5.17 - """
5.18 - Resolve any members referring to deferred references, using information
5.19 - stored in the importer. This updates stored object and external name
5.20 - records in this module.
5.21 - """
5.22 -
5.23 - for impd, d in [
5.24 - (self.importer.objects, self.objects),
5.25 - (self.importer.all_name_references, self.name_references)
5.26 - ]:
5.27 -
5.28 - for name, ref in d.items():
5.29 -
5.30 - # Obtain resolved names from the importer.
5.31 -
5.32 - if ref.has_kind("<depends>"):
5.33 - ref = self.importer.identify(name)
5.34 - d[name] = ref
5.35 -
5.36 def resolve_class_bases(self):
5.37
5.38 "Resolve all class bases since some of them may have been deferred."