# HG changeset patch # User Paul Boddie # Date 1202674838 -3600 # Node ID f20efed959271fca77b4aff71f5699add1987377 # Parent 88cac9d8f47e4f2b447248062d7305973f3990f8 Fixed method code generation so that methods are not inappropriately generated more than one. Added support for the invocation of classes where the initialiser definition is retrieved. Improved exception handling. diff -r 88cac9d8f47e -r f20efed95927 micropython/__init__.py --- a/micropython/__init__.py Sat Feb 09 19:37:38 2008 +0100 +++ b/micropython/__init__.py Sun Feb 10 21:20:38 2008 +0100 @@ -5,7 +5,7 @@ from the simplify package but has had various details related to that package removed. -Copyright (C) 2006, 2007 Paul Boddie +Copyright (C) 2006, 2007, 2008 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 @@ -33,6 +33,7 @@ functionality of the micropython package may be accessed. """ +from micropython.common import * import micropython.ast import micropython.inspect import micropython.table @@ -42,11 +43,12 @@ except NameError: from sets import Set as set -InspectError = micropython.inspect.InspectError - class Importer: - "An import machine, searching for and loading modules." + """ + An import machine, searching for and loading modules. In addition, this + class supports the generation of a program image. + """ def __init__(self, path=None, verbose=0): diff -r 88cac9d8f47e -r f20efed95927 micropython/ast.py --- a/micropython/ast.py Sat Feb 09 19:37:38 2008 +0100 +++ b/micropython/ast.py Sun Feb 10 21:20:38 2008 +0100 @@ -3,7 +3,7 @@ """ Translate the AST of a Python program into a more interpretable representation. -Copyright (C) 2007 Paul Boddie +Copyright (C) 2007, 2008 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 @@ -21,6 +21,7 @@ import micropython.inspect from micropython.rsvp import * +from micropython.common import * import compiler.ast from compiler.visitor import ASTVisitor try: @@ -28,11 +29,7 @@ except NameError: from sets import Set as set -class TranslateError(Exception): - - "A translation error." - - pass +class TranslateError(ProcessingError): pass class Label: @@ -128,7 +125,7 @@ # Visitor methods. def default(self, node, *args): - raise TranslateError, node.__class__ + raise TranslateError(self.module.full_name(), node, "Node class %r is not supported." % node.__class__) def dispatch(self, node, *args): return ASTVisitor.dispatch(self, node, *args) @@ -148,14 +145,14 @@ elif isinstance(unit, micropython.inspect.Module): self.new_op(AttrInstruction(unit.module_attributes()[name])) else: - raise TranslateError, "Program unit %r has no local %r" % (unit, name) + raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r" % (unit, name)) elif scope == "global": globals = self.module.module_attributes() if globals.has_key(name): self.new_op(AttrInstruction(globals[name])) else: - raise TranslateError, "Module %r has no attribute %r" % (self.module, name) + raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r" % (self.module, name)) else: builtins = micropython.inspect.builtins.module_attributes() @@ -240,7 +237,26 @@ # Optimise where the target is known now. if target is not None: - pos = self.paramtable.table[target.full_name()][arg.name] + + # Find the parameter table entry for the target. + + target_name = target.full_name() + + # Look for a callable with the precise target name. + + try: + table_entry = self.paramtable.table[target_name] + + # Where no callable is present, check to see if it is a + # class name and find the initialiser instead. + + except KeyError: + if self.objtable.table.has_key(target_name): + table_entry = self.paramtable.table[target_name + ".__init__"] + else: + raise + + pos = table_entry[arg.name] self.new_op(StoreFrame(pos)) # Otherwise, generate the code needed to obtain the details of @@ -251,7 +267,10 @@ # Combine the target details with the name to get the location. # See the access method on the List class. - paramindex = self.paramtable.get_index(arg.name) + try: + paramindex = self.paramtable.get_index(arg.name) + except ValueError: + raise TranslateError(self.module.full_name(), node, "No parameter definition exists for %r." % arg.name) self.new_op(StoreFrameIndex(paramindex)) @@ -271,7 +290,7 @@ def visitClass(self, node): unit = self.unit - self.unit = node.cls + self.unit = node.unit self.dispatch(node.code) self.unit = unit @@ -319,8 +338,8 @@ # Only store the name when visiting this node from outside. - if self.unit is self.module: - self.new_op(LoadConst(node.function)) + if self.unit is not node.unit: + self.new_op(LoadConst(node.unit)) self._visitName(node, (StoreName, StoreAttr)) # Visiting of the code occurs when get_code is invoked on this node. diff -r 88cac9d8f47e -r f20efed95927 micropython/common.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/micropython/common.py Sun Feb 10 21:20:38 2008 +0100 @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +""" +Common classes. + +Copyright (C) 2007, 2008 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 +Foundation; either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +""" + +class ProcessingError(Exception): + + "A processing error." + + def __init__(self, unit_name, node, message): + self.unit_name = unit_name + self.node = node + self.message = message + + def __repr__(self): + return "ProcessingError in %r at line %d: %s" % (self.unit_name, self.node.lineno, self.message) + + def __str__(self): + return repr(self) + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 88cac9d8f47e -r f20efed95927 micropython/inspect.py --- a/micropython/inspect.py Sat Feb 09 19:37:38 2008 +0100 +++ b/micropython/inspect.py Sun Feb 10 21:20:38 2008 +0100 @@ -45,6 +45,7 @@ each such object is defined. """ +from micropython.common import * import compiler.ast from compiler.visitor import ASTVisitor try: @@ -52,13 +53,7 @@ except NameError: from sets import Set as set -class InspectError(Exception): - - "An inspection error." - - def __init__(self, node, message): - self.node = node - self.message = message +class InspectError(ProcessingError): pass class AtLeast: @@ -166,7 +161,7 @@ if not self.namespace.has_key(name): self.globals.add(name) else: - raise InspectError, "Name %r is global and local in %r" % (name, self) + raise InspectError(self.full_name(), self.node, "Name %r is global and local in %r" % (name, self)) def get_assignments(self, name): if self.assignments.has_key(name): @@ -425,7 +420,7 @@ if name not in self.argnames and not self.has_key(name): self.globals.add(name) else: - raise InspectError, "Name %r is global and local in %r" % (name, self) + raise InspectError(self.full_name(), self.node, "Name %r is global and local in %r" % (name, self)) def parameters(self): @@ -624,7 +619,7 @@ # Visitor methods. def default(self, node, *args): - raise InspectError, node.__class__ + raise InspectError(self.full_name(), node, "Node class %r is not supported." % node.__class__) def dispatch(self, node, *args): return ASTVisitor.dispatch(self, node, *args) @@ -693,15 +688,17 @@ expr = self.dispatch(base) if isinstance(expr, Attr): if expr.assignments != 1: - raise InspectError(node, "Base class %r for %r in %r is not constant." % (base, cls, self)) + raise InspectError(self.full_name(), node, + "Base class %r for %r in %r is not constant." % (base, cls, self)) else: cls.add_base(expr.value) else: # if expr is None: - raise InspectError(node, "Base class %r for %r in %r is not found: it may be hidden in some way." % (base, cls, self)) + raise InspectError(self.full_name(), node, + "Base class %r for %r in %r is not found: it may be hidden in some way." % (base, cls, self)) # Make a back reference from the node for code generation. - node.cls = cls + node.unit = cls # Make an entry for the class. @@ -745,7 +742,8 @@ def visitFrom(self, node): if self.importer is None: - raise InspectError(node, "Please use the micropython.Importer class for code which uses the 'from' statement.") + raise InspectError(self.full_name(), node, + "Please use the micropython.Importer class for code which uses the 'from' statement.") module = self.importer.load(node.modname, 1) @@ -787,7 +785,7 @@ # Make a back reference from the node for code generation. - node.function = function + node.unit = function self.namespaces.append(function) @@ -843,7 +841,8 @@ def visitImport(self, node): if self.importer is None: - raise InspectError(node, "Please use the micropython.Importer class for code which uses the 'import' statement.") + raise InspectError(self.full_name(), node, + "Please use the micropython.Importer class for code which uses the 'import' statement.") for name, alias in node.names: if alias is not None: diff -r 88cac9d8f47e -r f20efed95927 test.py --- a/test.py Sat Feb 09 19:37:38 2008 +0100 +++ b/test.py Sun Feb 10 21:20:38 2008 +0100 @@ -14,9 +14,8 @@ #m = i.load_from_file("micropython/__init__.py") else: m = i.load_from_file(sys.argv[1]) -except micropython.InspectError, exc: - print "At line", exc.node.lineno, "the following error occurred:" - print exc.message +except micropython.ProcessingError, exc: + print repr(exc) else: i.vacuum() ot = i.get_object_table()