# HG changeset patch # User Paul Boddie # Date 1478989772 -3600 # Node ID 052e4264d8b7c34aa196e152bc5a70c3036ac07d # Parent 67edffe846e38547f763f5c39924a5af12c61bf2 Changed the "from" statement to introduce name references instead of assigning names in the current namespace. This avoids module import sequencing issues but will eventually require restrictions on the kinds of objects being imported. The identification of objects also needs to favour name references in modules over conflicting submodules. diff -r 67edffe846e3 -r 052e4264d8b7 importer.py --- a/importer.py Sat Nov 12 23:27:04 2016 +0100 +++ b/importer.py Sat Nov 12 23:29:32 2016 +0100 @@ -187,7 +187,10 @@ "Identify 'name' using stored object and external name records." - return self.objects.get(name) or self.all_name_references.get(name) + ref = self.objects.get(name) + if not ref or ref.has_kind(""): + ref = self.all_name_references.get(name) or ref + return ref # Indirect object retrieval. @@ -342,7 +345,7 @@ # Record the type of all classes. - self.type_ref = self.get_object("__builtins__.type") + self.type_ref = self.get_object("__builtins__.core.type") # Resolve dependencies within the program. diff -r 67edffe846e3 -r 052e4264d8b7 inspector.py --- a/inspector.py Sat Nov 12 23:27:04 2016 +0100 +++ b/inspector.py Sat Nov 12 23:29:32 2016 +0100 @@ -134,7 +134,12 @@ # Find predefined constant names before anything else. if name in predefined_constants: - ref = self.get_builtin(name) + + # Predefined constants are imported within the built-ins. + + ref = self.get_imported_name(key) + if not ref: + ref = self.get_builtin(name) self.set_name_reference(key, ref) continue @@ -152,6 +157,13 @@ self.set_name_reference(key, ref) continue + # Find imported name. + + ref = self.get_imported_name(key) + if ref: + self.set_name_reference(key, ref) + continue + # Find presumed built-in definitions. ref = self.get_builtin(name) @@ -550,11 +562,11 @@ if name == "*": raise InspectError("Only explicitly specified names can be imported from modules.", path, n) - # Explicit names. + # Reference names instead of setting them as locals. ref = self.import_name_from_module(name, module_name) - value = ResolvedNameRef(alias or name, ref) - self.set_general_local(alias or name, value) + self.set_imported_name(alias or name, ref) + self.record_name(alias or name) def process_function_node(self, n, name): @@ -857,10 +869,14 @@ access_number = self.record_access_details(n.name, None, False, False) return LocalNameRef(n.name, access_number) - # Possible global or built-in name. + # Possible imported, global or built-in name. else: - return NameRef(n.name) + ref = self.get_imported_name(n.name) + if ref: + return ResolvedNameRef(n.name, ref) + else: + return NameRef(n.name) def process_operator_chain(self, nodes, fn): @@ -1281,8 +1297,19 @@ ref = None if not self.in_function and name not in predefined_constants: + + # Search for class namespace members. + if self.in_class: ref = self.get_object(self.get_object_path(name), False) + + # Search for imported names. + + if not ref: + ref = self.get_imported_name(name) + + # Search for globals or built-in names. + if not ref: ref = self.get_global_or_builtin(name) diff -r 67edffe846e3 -r 052e4264d8b7 modules.py --- a/modules.py Sat Nov 12 23:27:04 2016 +0100 +++ b/modules.py Sat Nov 12 23:29:32 2016 +0100 @@ -38,6 +38,7 @@ self.imports = set() self.required = set() self.deferred = [] + self.imported = {} # Global name information. @@ -338,6 +339,26 @@ if ref.has_kind(""): self.deferred.append(ref) + def get_imported_name(self, name): + + "Return a reference for 'name', imported from another module." + + if "." in name: + path = name + name = path.rsplit(".", 1)[-1] + else: + path = self.get_object_path(name) + + global_path = self.get_global_path(name) + return self.imported.get(path) or self.imported.get(global_path) + + def set_imported_name(self, name, ref): + + "Establish a reference for 'name' given by 'ref'." + + path = self.get_object_path(name) + self.imported[path] = ref + class CachedModule(BasicModule): "A cached module."