1.1 --- a/micropython/__init__.py Fri Dec 12 00:59:44 2008 +0100
1.2 +++ b/micropython/__init__.py Fri Jan 16 00:52:04 2009 +0100
1.3 @@ -5,7 +5,7 @@
1.4 from the simplify package but has had various details related to that package
1.5 removed.
1.6
1.7 -Copyright (C) 2006, 2007, 2008 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2006, 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -45,42 +45,24 @@
1.13 except NameError:
1.14 from sets import Set as set
1.15
1.16 -class Importer:
1.17 +class Program:
1.18
1.19 - """
1.20 - An import machine, searching for and loading modules. In addition, this
1.21 - class supports the generation of a program image.
1.22 - """
1.23 + "This class supports the generation of a program image."
1.24
1.25 supported_optimisations = micropython.opt.Optimiser.supported_optimisations
1.26
1.27 - predefined_constants = {
1.28 - "None" : None,
1.29 - "True" : True,
1.30 - "False" : False,
1.31 - "Ellipsis" : Ellipsis,
1.32 - "NotImplemented" : NotImplemented
1.33 - }
1.34 -
1.35 - def __init__(self, path=None, optimisations=None, verbose=0):
1.36 + def __init__(self, importer, optimisations=None):
1.37
1.38 """
1.39 - Initialise the importer with the given search 'path' - a list of
1.40 - directories to search for Python modules.
1.41 + Initialise the program representation with an 'importer' which is able
1.42 + to locate and load Python modules.
1.43
1.44 The optional 'optimisations' cause certain techniques to be used in
1.45 reducing program size and improving program efficiency.
1.46 -
1.47 - The optional 'verbose' parameter causes output concerning the activities
1.48 - of the object to be produced if set to a true value (not the default).
1.49 """
1.50
1.51 - self.path = path or [os.getcwd()]
1.52 - self.optimisations = optimisations
1.53 - self.verbose = verbose
1.54 - self.modules = {}
1.55 - self.modules_ordered = []
1.56 - self.loading = set()
1.57 + self.importer = importer
1.58 + self.optimisations = optimisations or set()
1.59
1.60 # Remember the tables once generated.
1.61
1.62 @@ -88,113 +70,16 @@
1.63 self.paramtable = None
1.64 self.clstable = None
1.65
1.66 - # Constant records.
1.67 -
1.68 - self.constant_values = {}
1.69 - self.constant_list = None # cache for constants
1.70 - self.init_predefined_constants()
1.71 -
1.72 - # Name records (used to track actual use of names).
1.73 - # Include names which may not be explicitly used in programs.
1.74 -
1.75 - self.names_used = set(["__init__"])
1.76 -
1.77 # Main program information.
1.78
1.79 self.code = None
1.80 self.code_location = None
1.81
1.82 - # Status information.
1.83 -
1.84 - self.vacuumed = 0
1.85 - self.finalised = 0
1.86 -
1.87 - # Name accounting.
1.88 -
1.89 - def use_name(self, name):
1.90 -
1.91 - "Register the given 'name' as being used in the program."
1.92 -
1.93 - self.names_used.add(name)
1.94 -
1.95 - # Constant accounting.
1.96 -
1.97 - def init_predefined_constants(self):
1.98 -
1.99 - "Ensure the predefined constants."
1.100 -
1.101 - for name, value in self.predefined_constants.items():
1.102 - self.make_constant(value)
1.103 -
1.104 - def get_predefined_constant(self, name):
1.105 -
1.106 - "Return the predefined constant for the given 'name'."
1.107 -
1.108 - return self.make_constant(self.predefined_constants[name])
1.109 -
1.110 - def get_constant(self, value):
1.111 -
1.112 - "Return a constant for the given 'value'."
1.113 -
1.114 - return self.constant_values[value]
1.115 -
1.116 - def make_constant(self, value):
1.117 -
1.118 - "Make and return a constant for the given 'value'."
1.119 -
1.120 - if not self.constant_values.has_key(value):
1.121 - const = micropython.data.Const(value)
1.122 - self.constant_values[value] = const
1.123 - return self.constant_values[value]
1.124 -
1.125 - def constants(self):
1.126 -
1.127 - "Return a list of constants."
1.128 -
1.129 - if self.constant_list is None:
1.130 - self.constant_list = list(self.constant_values.values())
1.131 -
1.132 - return self.constant_list
1.133 -
1.134 - # General maintenance.
1.135 -
1.136 - def vacuum(self):
1.137 -
1.138 - "Tidy up the modules."
1.139 -
1.140 - if self.vacuumed:
1.141 - return
1.142 -
1.143 - for name, module in self.modules.items():
1.144 - if module.loaded:
1.145 - module.vacuum()
1.146 - else:
1.147 - del self.modules[name]
1.148 -
1.149 - self.vacuumed = 1
1.150 -
1.151 - def finalise(self):
1.152 -
1.153 - "Finalise the program."
1.154 -
1.155 - if self.finalised:
1.156 - return
1.157 -
1.158 - self.vacuum()
1.159 -
1.160 - for module in self.get_modules():
1.161 - module.finalise()
1.162 -
1.163 - self.finalised = 1
1.164 + def get_importer(self):
1.165 + return self.importer
1.166
1.167 # Access to finalised program information.
1.168
1.169 - def get_modules(self):
1.170 -
1.171 - "Return all modules known to the importer."
1.172 -
1.173 - return self.modules.values()
1.174 -
1.175 def get_image(self, with_builtins=0):
1.176
1.177 "Return a dictionary mapping modules to structures."
1.178 @@ -204,18 +89,18 @@
1.179
1.180 objtable = self.get_object_table()
1.181 paramtable = self.get_parameter_table()
1.182 - self.finalise()
1.183 + self.importer.finalise()
1.184
1.185 self.code = []
1.186
1.187 # Append constants to the image.
1.188
1.189 - for pos, const in enumerate(self.constants()):
1.190 + for pos, const in enumerate(self.importer.constants()):
1.191 self.code.append(const)
1.192
1.193 - last_module = self.modules_ordered[-1]
1.194 + last_module = self.importer.modules_ordered[-1]
1.195
1.196 - for module in self.modules_ordered:
1.197 + for module in self.importer.modules_ordered:
1.198
1.199 if not with_builtins and module.name == "__builtins__":
1.200 continue
1.201 @@ -403,14 +288,14 @@
1.202
1.203 # Fix the module locations.
1.204
1.205 - for module in self.modules_ordered:
1.206 + for module in self.importer.modules_ordered:
1.207
1.208 if not with_builtins and module.name == "__builtins__":
1.209 continue
1.210
1.211 module.code_location = module.blocks[0].location
1.212
1.213 - self.code_location = self.modules["__main__"].code_location
1.214 + self.code_location = self.importer.modules["__main__"].code_location
1.215 return self.raw_code
1.216
1.217 def raw_block(self, block):
1.218 @@ -441,10 +326,10 @@
1.219 "Return a table with details of attributes for classes and modules."
1.220
1.221 if self.objtable is None:
1.222 - self.vacuum()
1.223 + self.importer.vacuum()
1.224
1.225 t = self.objtable = micropython.table.ObjectTable()
1.226 - for module in self.get_modules():
1.227 + for module in self.importer.get_modules():
1.228 t.add(module.full_name(), module.module_attributes())
1.229
1.230 # Add class and instance attributes for all classes, together
1.231 @@ -472,7 +357,7 @@
1.232
1.233 # Visit each module, getting function and method details.
1.234
1.235 - for module in self.get_modules():
1.236 + for module in self.importer.get_modules():
1.237 for obj in module.all_objects:
1.238 if isinstance(obj, micropython.inspect.Function):
1.239 t.add(obj.full_name(), obj.parameters())
1.240 @@ -489,7 +374,7 @@
1.241
1.242 keyword_names = set()
1.243
1.244 - for module in self.get_modules():
1.245 + for module in self.importer.get_modules():
1.246 keyword_names.update(module.keyword_names)
1.247
1.248 for function_name, parameters in t.table.items():
1.249 @@ -501,6 +386,139 @@
1.250
1.251 return self.paramtable
1.252
1.253 +class Importer:
1.254 +
1.255 + "An import machine, searching for and loading modules."
1.256 +
1.257 + predefined_constants = {
1.258 + "None" : None,
1.259 + "True" : True,
1.260 + "False" : False,
1.261 + "Ellipsis" : Ellipsis,
1.262 + "NotImplemented" : NotImplemented
1.263 + }
1.264 +
1.265 + def __init__(self, path=None, verbose=0, optimisations=None):
1.266 +
1.267 + """
1.268 + Initialise the importer with the given search 'path' - a list of
1.269 + directories to search for Python modules.
1.270 +
1.271 + The optional 'verbose' parameter causes output concerning the activities
1.272 + of the object to be produced if set to a true value (not the default).
1.273 +
1.274 + The optional 'optimisations' cause certain techniques to be used in
1.275 + reducing program size and improving program efficiency.
1.276 + """
1.277 +
1.278 + self.path = path or [os.getcwd()]
1.279 + self.verbose = verbose
1.280 + self.optimisations = optimisations or set()
1.281 +
1.282 + self.modules = {}
1.283 + self.modules_ordered = []
1.284 + self.loading = set()
1.285 +
1.286 + # Constant records.
1.287 +
1.288 + self.constant_values = {}
1.289 + self.constant_list = None # cache for constants
1.290 + self.init_predefined_constants()
1.291 +
1.292 + # Name records (used to track actual use of names).
1.293 + # Include names which may not be explicitly used in programs.
1.294 +
1.295 + self.names_used = set(["__init__"])
1.296 +
1.297 + # Status information.
1.298 +
1.299 + self.vacuumed = 0
1.300 + self.finalised = 0
1.301 +
1.302 + def get_modules(self):
1.303 +
1.304 + "Return all modules known to the importer."
1.305 +
1.306 + return self.modules.values()
1.307 +
1.308 + # General maintenance.
1.309 +
1.310 + def vacuum(self):
1.311 +
1.312 + "Tidy up the modules."
1.313 +
1.314 + if self.vacuumed:
1.315 + return
1.316 +
1.317 + for name, module in self.modules.items():
1.318 + if module.loaded:
1.319 + module.vacuum()
1.320 + else:
1.321 + del self.modules[name]
1.322 +
1.323 + self.vacuumed = 1
1.324 +
1.325 + def finalise(self):
1.326 +
1.327 + "Finalise the program."
1.328 +
1.329 + if self.finalised:
1.330 + return
1.331 +
1.332 + self.vacuum()
1.333 +
1.334 + for module in self.get_modules():
1.335 + module.finalise()
1.336 +
1.337 + self.finalised = 1
1.338 +
1.339 + # Name accounting.
1.340 +
1.341 + def use_name(self, name):
1.342 +
1.343 + "Register the given 'name' as being used in the program."
1.344 +
1.345 + self.names_used.add(name)
1.346 +
1.347 + # Constant accounting.
1.348 +
1.349 + def init_predefined_constants(self):
1.350 +
1.351 + "Ensure the predefined constants."
1.352 +
1.353 + for name, value in self.predefined_constants.items():
1.354 + self.make_constant(value)
1.355 +
1.356 + def get_predefined_constant(self, name):
1.357 +
1.358 + "Return the predefined constant for the given 'name'."
1.359 +
1.360 + return self.make_constant(self.predefined_constants[name])
1.361 +
1.362 + def get_constant(self, value):
1.363 +
1.364 + "Return a constant for the given 'value'."
1.365 +
1.366 + return self.constant_values[value]
1.367 +
1.368 + def make_constant(self, value):
1.369 +
1.370 + "Make and return a constant for the given 'value'."
1.371 +
1.372 + if not self.constant_values.has_key(value):
1.373 + const = micropython.data.Const(value)
1.374 + self.constant_values[value] = const
1.375 + return self.constant_values[value]
1.376 +
1.377 + def constants(self):
1.378 +
1.379 + "Return a list of constants."
1.380 +
1.381 + if self.constant_list is None:
1.382 + self.constant_list = list(self.constant_values.values())
1.383 +
1.384 + return self.constant_list
1.385 +
1.386 # Import methods.
1.387
1.388 def find_in_path(self, name):
2.1 --- a/micropython/ast.py Fri Dec 12 00:59:44 2008 +0100
2.2 +++ b/micropython/ast.py Fri Jan 16 00:52:04 2009 +0100
2.3 @@ -3,7 +3,7 @@
2.4 """
2.5 Translate the AST of a Python program into a more interpretable representation.
2.6
2.7 -Copyright (C) 2007, 2008 Paul Boddie <paul@boddie.org.uk>
2.8 +Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
2.9
2.10 This program is free software; you can redistribute it and/or modify it under
2.11 the terms of the GNU General Public License as published by the Free Software
2.12 @@ -42,11 +42,11 @@
2.13 name_load_instructions = (LoadName, LoadAddress)
2.14 name_store_instructions = (StoreName, StoreAddress)
2.15
2.16 - def __init__(self, module, importer):
2.17 + def __init__(self, module, program):
2.18
2.19 """
2.20 - Initialise the translation with an inspected 'module' and the module
2.21 - 'importer'.
2.22 + Initialise the translation with an inspected 'module' and the 'program'
2.23 + container.
2.24 """
2.25
2.26 ASTVisitor.__init__(self)
2.27 @@ -55,14 +55,15 @@
2.28
2.29 # Global program dependencies.
2.30
2.31 - self.importer = importer
2.32 - self.objtable = self.importer.get_object_table()
2.33 - self.paramtable = self.importer.get_parameter_table()
2.34 + self.program = program
2.35 + self.objtable = self.program.get_object_table()
2.36 + self.paramtable = self.program.get_parameter_table()
2.37 + self.importer = self.program.get_importer()
2.38 self.builtins = self.importer.modules.get("__builtins__")
2.39
2.40 # Optimisation.
2.41
2.42 - self.optimiser = Optimiser(self, importer.optimisations)
2.43 + self.optimiser = Optimiser(self, program.optimisations)
2.44
2.45 # The current unit being translated.
2.46
3.1 --- a/test.py Fri Dec 12 00:59:44 2008 +0100
3.2 +++ b/test.py Fri Jan 16 00:52:04 2009 +0100
3.3 @@ -8,16 +8,16 @@
3.4
3.5 code = None
3.6
3.7 -def show(importer, with_builtins=0):
3.8 - make(importer, with_builtins)
3.9 +def show(program, with_builtins=0):
3.10 + make(program, with_builtins)
3.11 show_code(code)
3.12
3.13 -def make(importer, with_builtins=0):
3.14 +def make(program, with_builtins=0):
3.15 global code
3.16 - code = importer.get_image(with_builtins)
3.17 + code = program.get_image(with_builtins)
3.18
3.19 -def raw(importer, with_builtins=0):
3.20 - return importer.get_raw_image()
3.21 +def raw(program, with_builtins=0):
3.22 + return program.get_raw_image()
3.23
3.24 def show_code(code):
3.25 for i, x in enumerate(code):
3.26 @@ -29,21 +29,21 @@
3.27 print "%6d" % (len(table_slice) - table_slice.count(None)), \
3.28 "".join(entry and "#" or "_" for entry in table_slice)
3.29
3.30 -def machine(importer, with_builtins=0, debug=0):
3.31 +def machine(program, with_builtins=0, debug=0):
3.32 print "Making the image..."
3.33 - make(importer, with_builtins)
3.34 + make(program, with_builtins)
3.35 print "Getting raw structures..."
3.36 - ot = importer.get_object_table()
3.37 - pt = importer.get_parameter_table()
3.38 + ot = program.get_object_table()
3.39 + pt = program.get_parameter_table()
3.40 objlist = ot.as_list()
3.41 paramlist = pt.as_list()
3.42 attr_error = objlist.access("__builtins__", "AttributeError").value.location
3.43 type_error = objlist.access("__builtins__", "TypeError").value.location
3.44 print "Getting raw image..."
3.45 - rc = importer.get_raw_image()
3.46 + rc = program.get_raw_image()
3.47 print "Initialising the machine..."
3.48 rm = rsvp.RSVPMachine(rc, objlist.as_raw(), paramlist.as_raw(), attr_error, type_error, debug=debug)
3.49 - rm.pc = importer.code_location
3.50 + rm.pc = program.code_location
3.51 return rm
3.52
3.53 def attrs(obj):
3.54 @@ -61,7 +61,7 @@
3.55 program = None
3.56
3.57 if "-omax" in args:
3.58 - requested_optimisations = micropython.Importer.supported_optimisations
3.59 + requested_optimisations = micropython.Program.supported_optimisations
3.60 else:
3.61 requested_optimisations = []
3.62 for arg in args:
3.63 @@ -69,7 +69,8 @@
3.64 for arg_part in arg[2:].split(","):
3.65 requested_optimisations.append(arg_part)
3.66
3.67 - i = micropython.Importer(path, requested_optimisations, "-v" in args)
3.68 + i = micropython.Importer(path, "-v" in args, requested_optimisations)
3.69 + p = micropython.Program(i, requested_optimisations)
3.70
3.71 try:
3.72 builtins = i.load_from_file("lib/builtins.py", "__builtins__")
3.73 @@ -84,7 +85,7 @@
3.74 if "-tb" in args:
3.75 raise
3.76 else:
3.77 - ot = i.get_object_table()
3.78 - pt = i.get_parameter_table()
3.79 + ot = p.get_object_table()
3.80 + pt = p.get_parameter_table()
3.81
3.82 # vim: tabstop=4 expandtab shiftwidth=4