# HG changeset patch # User Paul Boddie # Date 1232063524 -3600 # Node ID 839a5b14e2636769b17a9608515ed6520ff3d255 # Parent e38b8757fabcb5712829f8dc4854a347f8d44ed6 Separated functionality in Importer into distinct Importer and Program classes. diff -r e38b8757fabc -r 839a5b14e263 micropython/__init__.py --- a/micropython/__init__.py Fri Dec 12 00:59:44 2008 +0100 +++ b/micropython/__init__.py Fri Jan 16 00:52:04 2009 +0100 @@ -5,7 +5,7 @@ from the simplify package but has had various details related to that package removed. -Copyright (C) 2006, 2007, 2008 Paul Boddie +Copyright (C) 2006, 2007, 2008, 2009 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -45,42 +45,24 @@ except NameError: from sets import Set as set -class Importer: +class Program: - """ - An import machine, searching for and loading modules. In addition, this - class supports the generation of a program image. - """ + "This class supports the generation of a program image." supported_optimisations = micropython.opt.Optimiser.supported_optimisations - predefined_constants = { - "None" : None, - "True" : True, - "False" : False, - "Ellipsis" : Ellipsis, - "NotImplemented" : NotImplemented - } - - def __init__(self, path=None, optimisations=None, verbose=0): + def __init__(self, importer, optimisations=None): """ - Initialise the importer with the given search 'path' - a list of - directories to search for Python modules. + Initialise the program representation with an 'importer' which is able + to locate and load Python modules. The optional 'optimisations' cause certain techniques to be used in reducing program size and improving program efficiency. - - The optional 'verbose' parameter causes output concerning the activities - of the object to be produced if set to a true value (not the default). """ - self.path = path or [os.getcwd()] - self.optimisations = optimisations - self.verbose = verbose - self.modules = {} - self.modules_ordered = [] - self.loading = set() + self.importer = importer + self.optimisations = optimisations or set() # Remember the tables once generated. @@ -88,113 +70,16 @@ self.paramtable = None self.clstable = None - # Constant records. - - self.constant_values = {} - self.constant_list = None # cache for constants - self.init_predefined_constants() - - # Name records (used to track actual use of names). - # Include names which may not be explicitly used in programs. - - self.names_used = set(["__init__"]) - # Main program information. self.code = None self.code_location = None - # Status information. - - self.vacuumed = 0 - self.finalised = 0 - - # Name accounting. - - def use_name(self, name): - - "Register the given 'name' as being used in the program." - - self.names_used.add(name) - - # Constant accounting. - - def init_predefined_constants(self): - - "Ensure the predefined constants." - - for name, value in self.predefined_constants.items(): - self.make_constant(value) - - def get_predefined_constant(self, name): - - "Return the predefined constant for the given 'name'." - - return self.make_constant(self.predefined_constants[name]) - - def get_constant(self, value): - - "Return a constant for the given 'value'." - - return self.constant_values[value] - - def make_constant(self, value): - - "Make and return a constant for the given 'value'." - - if not self.constant_values.has_key(value): - const = micropython.data.Const(value) - self.constant_values[value] = const - return self.constant_values[value] - - def constants(self): - - "Return a list of constants." - - if self.constant_list is None: - self.constant_list = list(self.constant_values.values()) - - return self.constant_list - - # General maintenance. - - def vacuum(self): - - "Tidy up the modules." - - if self.vacuumed: - return - - for name, module in self.modules.items(): - if module.loaded: - module.vacuum() - else: - del self.modules[name] - - self.vacuumed = 1 - - def finalise(self): - - "Finalise the program." - - if self.finalised: - return - - self.vacuum() - - for module in self.get_modules(): - module.finalise() - - self.finalised = 1 + def get_importer(self): + return self.importer # Access to finalised program information. - def get_modules(self): - - "Return all modules known to the importer." - - return self.modules.values() - def get_image(self, with_builtins=0): "Return a dictionary mapping modules to structures." @@ -204,18 +89,18 @@ objtable = self.get_object_table() paramtable = self.get_parameter_table() - self.finalise() + self.importer.finalise() self.code = [] # Append constants to the image. - for pos, const in enumerate(self.constants()): + for pos, const in enumerate(self.importer.constants()): self.code.append(const) - last_module = self.modules_ordered[-1] + last_module = self.importer.modules_ordered[-1] - for module in self.modules_ordered: + for module in self.importer.modules_ordered: if not with_builtins and module.name == "__builtins__": continue @@ -403,14 +288,14 @@ # Fix the module locations. - for module in self.modules_ordered: + for module in self.importer.modules_ordered: if not with_builtins and module.name == "__builtins__": continue module.code_location = module.blocks[0].location - self.code_location = self.modules["__main__"].code_location + self.code_location = self.importer.modules["__main__"].code_location return self.raw_code def raw_block(self, block): @@ -441,10 +326,10 @@ "Return a table with details of attributes for classes and modules." if self.objtable is None: - self.vacuum() + self.importer.vacuum() t = self.objtable = micropython.table.ObjectTable() - for module in self.get_modules(): + for module in self.importer.get_modules(): t.add(module.full_name(), module.module_attributes()) # Add class and instance attributes for all classes, together @@ -472,7 +357,7 @@ # Visit each module, getting function and method details. - for module in self.get_modules(): + for module in self.importer.get_modules(): for obj in module.all_objects: if isinstance(obj, micropython.inspect.Function): t.add(obj.full_name(), obj.parameters()) @@ -489,7 +374,7 @@ keyword_names = set() - for module in self.get_modules(): + for module in self.importer.get_modules(): keyword_names.update(module.keyword_names) for function_name, parameters in t.table.items(): @@ -501,6 +386,139 @@ return self.paramtable +class Importer: + + "An import machine, searching for and loading modules." + + predefined_constants = { + "None" : None, + "True" : True, + "False" : False, + "Ellipsis" : Ellipsis, + "NotImplemented" : NotImplemented + } + + def __init__(self, path=None, verbose=0, optimisations=None): + + """ + Initialise the importer with the given search 'path' - a list of + directories to search for Python modules. + + The optional 'verbose' parameter causes output concerning the activities + of the object to be produced if set to a true value (not the default). + + The optional 'optimisations' cause certain techniques to be used in + reducing program size and improving program efficiency. + """ + + self.path = path or [os.getcwd()] + self.verbose = verbose + self.optimisations = optimisations or set() + + self.modules = {} + self.modules_ordered = [] + self.loading = set() + + # Constant records. + + self.constant_values = {} + self.constant_list = None # cache for constants + self.init_predefined_constants() + + # Name records (used to track actual use of names). + # Include names which may not be explicitly used in programs. + + self.names_used = set(["__init__"]) + + # Status information. + + self.vacuumed = 0 + self.finalised = 0 + + def get_modules(self): + + "Return all modules known to the importer." + + return self.modules.values() + + # General maintenance. + + def vacuum(self): + + "Tidy up the modules." + + if self.vacuumed: + return + + for name, module in self.modules.items(): + if module.loaded: + module.vacuum() + else: + del self.modules[name] + + self.vacuumed = 1 + + def finalise(self): + + "Finalise the program." + + if self.finalised: + return + + self.vacuum() + + for module in self.get_modules(): + module.finalise() + + self.finalised = 1 + + # Name accounting. + + def use_name(self, name): + + "Register the given 'name' as being used in the program." + + self.names_used.add(name) + + # Constant accounting. + + def init_predefined_constants(self): + + "Ensure the predefined constants." + + for name, value in self.predefined_constants.items(): + self.make_constant(value) + + def get_predefined_constant(self, name): + + "Return the predefined constant for the given 'name'." + + return self.make_constant(self.predefined_constants[name]) + + def get_constant(self, value): + + "Return a constant for the given 'value'." + + return self.constant_values[value] + + def make_constant(self, value): + + "Make and return a constant for the given 'value'." + + if not self.constant_values.has_key(value): + const = micropython.data.Const(value) + self.constant_values[value] = const + return self.constant_values[value] + + def constants(self): + + "Return a list of constants." + + if self.constant_list is None: + self.constant_list = list(self.constant_values.values()) + + return self.constant_list + # Import methods. def find_in_path(self, name): diff -r e38b8757fabc -r 839a5b14e263 micropython/ast.py --- a/micropython/ast.py Fri Dec 12 00:59:44 2008 +0100 +++ b/micropython/ast.py Fri Jan 16 00:52:04 2009 +0100 @@ -3,7 +3,7 @@ """ Translate the AST of a Python program into a more interpretable representation. -Copyright (C) 2007, 2008 Paul Boddie +Copyright (C) 2007, 2008, 2009 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -42,11 +42,11 @@ name_load_instructions = (LoadName, LoadAddress) name_store_instructions = (StoreName, StoreAddress) - def __init__(self, module, importer): + def __init__(self, module, program): """ - Initialise the translation with an inspected 'module' and the module - 'importer'. + Initialise the translation with an inspected 'module' and the 'program' + container. """ ASTVisitor.__init__(self) @@ -55,14 +55,15 @@ # Global program dependencies. - self.importer = importer - self.objtable = self.importer.get_object_table() - self.paramtable = self.importer.get_parameter_table() + self.program = program + self.objtable = self.program.get_object_table() + self.paramtable = self.program.get_parameter_table() + self.importer = self.program.get_importer() self.builtins = self.importer.modules.get("__builtins__") # Optimisation. - self.optimiser = Optimiser(self, importer.optimisations) + self.optimiser = Optimiser(self, program.optimisations) # The current unit being translated. diff -r e38b8757fabc -r 839a5b14e263 test.py --- a/test.py Fri Dec 12 00:59:44 2008 +0100 +++ b/test.py Fri Jan 16 00:52:04 2009 +0100 @@ -8,16 +8,16 @@ code = None -def show(importer, with_builtins=0): - make(importer, with_builtins) +def show(program, with_builtins=0): + make(program, with_builtins) show_code(code) -def make(importer, with_builtins=0): +def make(program, with_builtins=0): global code - code = importer.get_image(with_builtins) + code = program.get_image(with_builtins) -def raw(importer, with_builtins=0): - return importer.get_raw_image() +def raw(program, with_builtins=0): + return program.get_raw_image() def show_code(code): for i, x in enumerate(code): @@ -29,21 +29,21 @@ print "%6d" % (len(table_slice) - table_slice.count(None)), \ "".join(entry and "#" or "_" for entry in table_slice) -def machine(importer, with_builtins=0, debug=0): +def machine(program, with_builtins=0, debug=0): print "Making the image..." - make(importer, with_builtins) + make(program, with_builtins) print "Getting raw structures..." - ot = importer.get_object_table() - pt = importer.get_parameter_table() + ot = program.get_object_table() + pt = program.get_parameter_table() objlist = ot.as_list() paramlist = pt.as_list() attr_error = objlist.access("__builtins__", "AttributeError").value.location type_error = objlist.access("__builtins__", "TypeError").value.location print "Getting raw image..." - rc = importer.get_raw_image() + rc = program.get_raw_image() print "Initialising the machine..." rm = rsvp.RSVPMachine(rc, objlist.as_raw(), paramlist.as_raw(), attr_error, type_error, debug=debug) - rm.pc = importer.code_location + rm.pc = program.code_location return rm def attrs(obj): @@ -61,7 +61,7 @@ program = None if "-omax" in args: - requested_optimisations = micropython.Importer.supported_optimisations + requested_optimisations = micropython.Program.supported_optimisations else: requested_optimisations = [] for arg in args: @@ -69,7 +69,8 @@ for arg_part in arg[2:].split(","): requested_optimisations.append(arg_part) - i = micropython.Importer(path, requested_optimisations, "-v" in args) + i = micropython.Importer(path, "-v" in args, requested_optimisations) + p = micropython.Program(i, requested_optimisations) try: builtins = i.load_from_file("lib/builtins.py", "__builtins__") @@ -84,7 +85,7 @@ if "-tb" in args: raise else: - ot = i.get_object_table() - pt = i.get_parameter_table() + ot = p.get_object_table() + pt = p.get_parameter_table() # vim: tabstop=4 expandtab shiftwidth=4