# HG changeset patch # User Paul Boddie # Date 1194563943 -3600 # Node ID 317d342c1c54bb5b08f6db18d8c9f1cbec95fd94 # Parent 53b37a00af29298315848105adc77d1028926fb7 Added a node attribute to Class and Function instances. Ensure that function parameters appear in the locals. Added some code generation support with the micropython.ast and micropython.rsvp modules. diff -r 53b37a00af29 -r 317d342c1c54 micropython/__init__.py --- a/micropython/__init__.py Sun Nov 04 18:27:20 2007 +0100 +++ b/micropython/__init__.py Fri Nov 09 00:19:03 2007 +0100 @@ -33,7 +33,7 @@ functionality of the micropython package may be accessed. """ -#import micropython.ast +import micropython.ast import micropython.inspect import micropython.table import os @@ -84,7 +84,7 @@ # Position the module in the image and make a translation. module.location = pos - #trans = micropython.ast.Translation(module) + trans = micropython.ast.Translation(module) # Append module attributes to the image. @@ -120,9 +120,9 @@ # NOTE: methods and only other attribute-related code being # NOTE: generated here. - #code = trans.get_code(obj) - #image += code - #pos += len(code) + code = trans.get_code(obj) + image += code + pos += len(code) # NOTE: Generate module and function code here. @@ -134,15 +134,15 @@ # Append the function code to the image. - #code = trans.get_code(obj) - #image += code - #pos += len(code) + code = trans.get_code(obj) + image += code + pos += len(code) # Append the module top-level code to the image. - #code = trans.get_module_code() - #image += code - #pos += len(code) + code = trans.get_module_code() + image += code + pos += len(code) return image diff -r 53b37a00af29 -r 317d342c1c54 micropython/ast.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/micropython/ast.py Fri Nov 09 00:19:03 2007 +0100 @@ -0,0 +1,284 @@ +#!/usr/bin/env python + +""" +Translate the AST of a Python program into a more interpretable representation. + +Copyright (C) 2007 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 . +""" + +import micropython.inspect +from micropython.rsvp import * +import compiler.ast +from compiler.visitor import ASTVisitor +try: + set +except NameError: + from sets import Set as set + +class TranslateError(Exception): + + "A translation error." + + pass + +# Program visitors. + +class Translation(ASTVisitor): + + "A translated module." + + def __init__(self, module): + ASTVisitor.__init__(self) + self.visitor = self + self.module = module + self.unit = None + + def get_module_code(self): + + "Return the top-level module code." + + self.unit = self.module + return self.dispatch(self.module.module) + + def get_code(self, unit): + + "Return the code for the given 'unit'." + + self.unit = unit + return self.dispatch(unit.node) + + def __repr__(self): + return "Translation(%r)" % self.module + + def get_scope(self, name): + if self.unit.has_key(name): + return "local" + elif self.module.has_key(name): + return "global" + else: + return "builtins" + + # Visitor methods. + + def default(self, node, *args): + raise TranslateError, node.__class__ + + def dispatch(self, node, *args): + return ASTVisitor.dispatch(self, node, *args) + + def _visitName(self, node, classes): + name = node.name + scope = self.get_scope(name) + NameInstruction, AttrInstruction = classes + + if scope == "local": + unit = self.unit + if isinstance(unit, micropython.inspect.Function): + return [NameInstruction(unit.locals()[name])] + elif isinstance(unit, micropython.inspect.Class): + return [AttrInstruction(unit.all_class_attributes()[name])] + elif isinstance(unit, micropython.inspect.Module): + return [AttrInstruction(unit.module_attributes()[name])] + else: + raise TranslateError, "Program unit %r has no local %r" % (unit, name) + + elif scope == "global": + globals = self.module.module_attributes() + if globals.has_key(name): + return [AttrInstruction(globals[name])] + else: + raise TranslateError, "Module %r has no attribute %r" % (self.module, name) + + else: + builtins = micropython.inspect.builtins.module_attributes() + return [AttrInstruction(builtins[name])] + + def visitAdd(self, node): return [] + + """ + _t1 = node.left + _t2 = node.right + try: + _t1.__add__(_t2) + except AttributeError: + _t2.__radd__(_t1) + """ + + def visitAnd(self, node): return [] + + def visitAssert(self, node): return [] + + def visitAssign(self, node): + results = [] + results += self.dispatch(node.expr) + for n in node.nodes: + results += self.dispatch(n) + return results + + def visitAssAttr(self, node): return [] + + def visitAssList(self, node): return [] + + def visitAssName(self, node): + return self._visitName(node, (StoreName, StoreAttr)) + + visitAssTuple = visitAssList + + def visitAugAssign(self, node): return [] + + def visitBackquote(self, node): return [] + + def visitBitand(self, node): return [] + + def visitBitor(self, node): return [] + + def visitBitxor(self, node): return [] + + def visitBreak(self, node): return [] + + def visitCallFunc(self, node): return [] + + def visitClass(self, node): return [] + + def visitCompare(self, node): return [] + + def visitConst(self, node): return [] + + def visitContinue(self, node): return [] + + def visitDecorators(self, node): return [] + + def visitDict(self, node): return [] + + def visitDiscard(self, node): return [] + + def visitDiv(self, node): return [] + + def visitEllipsis(self, node): return [] + + def visitExec(self, node): return [] + + def visitExpression(self, node): return [] + + def visitFloorDiv(self, node): return [] + + def visitFor(self, node): return [] + + def visitFrom(self, node): return [] + + def visitFunction(self, node): + + # Only store the name when visiting this node from outside. + + if self.unit is self.module: + return self._visitName(node, (StoreName, StoreAttr)) + else: + return self.dispatch(node.code) + + def visitGenExpr(self, node): return [] + + def visitGenExprFor(self, node): return [] + + def visitGenExprIf(self, node): return [] + + def visitGenExprInner(self, node): return [] + + def visitGetattr(self, node): return [] + + def visitGlobal(self, node): return [] + + def visitIf(self, node): + for test, body in node.tests: + self.dispatch(body) + if node.else_ is not None: + self.dispatch(node.else_) + return None + + def visitImport(self, node): return [] + + def visitInvert(self, node): return [] + + def visitKeyword(self, node): return [] + + def visitLambda(self, node): return [] + + def visitLeftShift(self, node): return [] + + def visitList(self, node): return [] + + def visitListComp(self, node): return [] + + def visitListCompFor(self, node): return [] + + def visitListCompIf(self, node): return [] + + def visitMod(self, node): return [] + + def visitModule(self, node): + return self.dispatch(node.node) + + def visitMul(self, node): return [] + + def visitName(self, node): + return self._visitName(node, (LoadName, LoadAttr)) + + def visitNot(self, node): return [] + + def visitOr(self, node): return [] + + def visitPass(self, node): return [] + + def visitPower(self, node): return [] + + def visitPrint(self, node): return [] + + def visitPrintnl(self, node): return [] + + def visitRaise(self, node): return [] + + def visitReturn(self, node): return [] + + def visitRightShift(self, node): return [] + + def visitSlice(self, node): return [] + + def visitStmt(self, node): + result = [] + for n in node.nodes: + result += self.dispatch(n) + return result + + def visitSub(self, node): return [] + + def visitSubscript(self, node): return [] + + def visitTryExcept(self, node): return [] + + def visitTryFinally(self, node): return [] + + def visitTuple(self, node): return [] + + def visitUnaryAdd(self, node): return [] + + def visitUnarySub(self, node): return [] + + def visitWhile(self, node): return [] + + def visitWith(self, node): return [] + + def visitYield(self, node): return [] + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 53b37a00af29 -r 317d342c1c54 micropython/inspect.py --- a/micropython/inspect.py Sun Nov 04 18:27:20 2007 +0100 +++ b/micropython/inspect.py Fri Nov 09 00:19:03 2007 +0100 @@ -101,10 +101,11 @@ "An inspected class." - def __init__(self, name, parent_name): + def __init__(self, name, parent_name, node=None): NamespaceDict.__init__(self) self.name = name self.parent_name = parent_name + self.node = node self.bases = [] self.instattr = set() # instance attributes @@ -241,17 +242,23 @@ "An inspected function." - def __init__(self, name, parent_name, argnames, has_star, has_dstar): + def __init__(self, name, parent_name, argnames, has_star, has_dstar, node=None): NamespaceDict.__init__(self) self.name = name self.parent_name = parent_name self.argnames = argnames self.has_star = has_star self.has_dstar = has_dstar + self.node = node self.localnames = None # cache for locals self.alllocalnames = None # cache for all_locals + # Add parameters to the namespace. + + for name in argnames: + self[name] = None + # Image generation details. self.location = None @@ -511,7 +518,7 @@ if self.namespaces: print "Class %r in %r is not global: ignored." % (node.name, self) else: - cls = Class(node.name, self.get_parent().full_name()) + cls = Class(node.name, self.get_parent().full_name(), node) for base in node.bases: base_ref = self.dispatch(base) if base_ref is None: @@ -583,8 +590,9 @@ node.name, self.get_parent().full_name(), node.argnames, - has_star=(node.flags & 4 != 0), - has_dstar=(node.flags & 8 != 0) + (node.flags & 4 != 0), + (node.flags & 8 != 0), + node ) self.namespaces.append(function) diff -r 53b37a00af29 -r 317d342c1c54 micropython/rsvp.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/micropython/rsvp.py Fri Nov 09 00:19:03 2007 +0100 @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +""" +RSVP instruction classes. + +Copyright (C) 2007 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 Instruction: + + "A generic instruction." + + def __init__(self, attr): + self.attr = attr + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.attr) + +class LoadName(Instruction): pass +class LoadAttr(Instruction): pass +class StoreName(Instruction): pass +class StoreAttr(Instruction): pass + +# vim: tabstop=4 expandtab shiftwidth=4