# HG changeset patch # User Paul Boddie # Date 1479415706 -3600 # Node ID 653ac525f897a52afbd098619a4938d5558eb06c # Parent e9b03527f13204f1b086102f1a39bfeffbf24e95 Record module relationships involving non-static objects in order to detect problematic module interdependencies, also generating a module initialisation sequence from the more general relationships already defined. diff -r e9b03527f132 -r 653ac525f897 generator.py --- a/generator.py Thu Nov 17 21:45:25 2016 +0100 +++ b/generator.py Thu Nov 17 21:48:26 2016 +0100 @@ -910,19 +910,17 @@ __Try {""" - for name in self.importer.modules.keys(): + for name in self.importer.order_modules(): function_name = "__main_%s" % encode_path(name) print >>f_signatures, "void %s();" % function_name - # Emit the main module's function last. # Omit the native module. - if name not in ("__main__", "native"): + if name != "native": print >>f_code, """\ %s();""" % function_name print >>f_code, """\ - __main___main__(); return 0; } __Catch_anonymous diff -r e9b03527f132 -r 653ac525f897 importer.py --- a/importer.py Thu Nov 17 21:45:25 2016 +0100 +++ b/importer.py Thu Nov 17 21:48:26 2016 +0100 @@ -397,6 +397,7 @@ "Resolve dependencies between modules." self.waiting = {} + self.depends = {} for module in self.modules.values(): @@ -418,7 +419,11 @@ provider = self.get_module_provider(found.unresolved() and ref or found) ref.mutate(found) - if provider: + # Record any external dependency. + + if provider and provider != module.name: + + # Record the provider dependency. module.required.add(provider) self.accessing_modules[provider].add(module.name) @@ -437,6 +442,12 @@ if self.verbose: print >>sys.stderr, "Requiring", provider, "for", ref + # Record a module ordering dependency. + + if not found.static(): + init_item(self.depends, module.name, set) + self.depends[module.name].add(provider) + # Check modules again to see if they are now required and should now # cause the inclusion of other modules providing objects to the program. @@ -458,6 +469,43 @@ print >>sys.stderr, "Requiring", provider self.require_providers(provider) + def order_modules(self): + + "Produce a module initialisation ordering." + + self.check_ordering() + return self.order_modules_for_module("__main__", set()) + + def order_modules_for_module(self, module_name, visited): + + """ + Order the modules required by 'module_name', using 'visited' to track + visited modules. + """ + + if module_name in visited: + return [] + + module = self.modules[module_name] + visited.add(module_name) + ordered = [module_name] + + for module_name in module.required: + modules = self.order_modules_for_module(module_name, visited) + ordered[:0] = modules + visited.update(modules) + + return ordered + + def check_ordering(self): + + "Check the ordering dependencies." + + for module_name, modules in self.depends.items(): + for provider in modules: + if self.depends.has_key(provider) and module_name in self.depends[provider]: + raise ProgramError, "Modules %s and %s may not depend on each other for non-static objects." % (module_name, provider) + def find_dependency(self, ref): "Find the ultimate dependency for 'ref'." diff -r e9b03527f132 -r 653ac525f897 lib/__builtins__/io.py --- a/lib/__builtins__/io.py Thu Nov 17 21:45:25 2016 +0100 +++ b/lib/__builtins__/io.py Thu Nov 17 21:48:26 2016 +0100 @@ -61,9 +61,9 @@ 'nl' is given as a true value. """ - # Import locally to ensure that the object is initialised. - # Otherwise, if imported at the module level, the sys module may not have - # been set up. + # If imported at the module level, the sys module must be set up first, + # which should be ensured by the module ordering activity, and a module + # attribute will be employed to hold a reference to sys.stdout. from sys import stdout