1 #!/usr/bin/env python 2 3 """ 4 Simplified AST nodes for easier type propagation and analysis. 5 6 Copyright (C) 2006 Paul Boddie <paul@boddie.org.uk> 7 8 This software is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of 11 the License, or (at your option) any later version. 12 13 This software is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public 19 License along with this library; see the file LICENCE.txt 20 If not, write to the Free Software Foundation, Inc., 21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 22 """ 23 24 from compiler.visitor import ASTVisitor 25 26 class Node: 27 28 """ 29 A result node with common attributes: 30 31 original The original node from which this node was created. 32 name Any name involved (variable or attribute). 33 index Any index involved (temporary variable name). 34 value Any constant value. 35 ref Any reference to (for example) subprograms. 36 37 Expression-related attributes: 38 39 expr Any contributing expression. 40 lvalue Any target expression. 41 test Any test expression in a conditional instruction. 42 handler Any exception handler selector expression. 43 44 Invocation and subprogram attributes: 45 46 args Any collection of argument nodes. 47 params Any collection of parameter nodes and defaults. 48 49 Statement-grouping attributes: 50 51 body Any conditional code depending on the success of a test. 52 else_ Any conditional code depending on the failure of a test. 53 finally_ Any code which will be executed regardless. 54 code Any unconditional code. 55 """ 56 57 def __init__(self, original=None, **kw): 58 self.original = original 59 if self.original is not None: 60 self.original._node = self 61 for name, value in kw.items(): 62 setattr(self, name, value) 63 64 def __repr__(self): 65 if hasattr(self, "name"): 66 return "%s '%s' (at %x)" % (self.__class__, self.name, id(self)) 67 if hasattr(self, "index"): 68 return "%s (%s) (at %x)" % (self.__class__, self.index, id(self)) 69 elif hasattr(self, "value"): 70 return "%s %s (at %x)" % (self.__class__, repr(self.value), id(self)) 71 elif hasattr(self, "ref"): 72 return "%s '%s' (at %x)" % (self.__class__, self.ref.name, id(self)) 73 else: 74 return "%s (at %x)" % (self.__class__, id(self)) 75 76 def _pprint(self, indent, continuation, s): 77 if continuation: 78 print (" " * max(0, indent - len(continuation))) + continuation + s 79 else: 80 print (" " * indent) + s 81 82 def pprint(self, indent=0, continuation=None): 83 self._pprint(indent, continuation, repr(self)) 84 85 # Show other details. 86 87 if hasattr(self, "params"): 88 for name, default in self.params: 89 self._pprint(indent + 2, "( ", "%s -> %s" % (name, default)) 90 if getattr(self, "acquire_locals", 0): 91 self._pprint(indent + 2, "( ", "acquiring locals") 92 if getattr(self, "structure", 0): 93 self._pprint(indent + 2, "( ", "structure '%s'" % self.structure.name) 94 if hasattr(self, "test"): 95 self.test.pprint(indent + 2, "? ") 96 for attr in "code", "body", "else_", "finally_": 97 if hasattr(self, attr) and getattr(self, attr): 98 self._pprint(indent, "", "{ (%s)" % attr) 99 for node in getattr(self, attr): 100 node.pprint(indent + 2) 101 self._pprint(indent, "", "}") 102 if hasattr(self, "handler"): 103 self.handler.pprint(indent + 2, "! ") 104 if hasattr(self, "expr"): 105 self.expr.pprint(indent + 2, "- ") 106 if hasattr(self, "nodes"): 107 for node in self.nodes: 108 node.pprint(indent + 2, "- ") 109 if hasattr(self, "lvalue"): 110 self.lvalue.pprint(indent + 2, "= ") 111 if hasattr(self, "args"): 112 for arg in self.args: 113 arg.pprint(indent + 2, "( ") 114 115 class Module(Node): "A Python module." 116 class Subprogram(Node): "A subprogram: functions, methods and loops." 117 class Class(Node): "A Python class." 118 class Pass(Node): "A placeholder node corresponding to pass." 119 class Invoke(Node): "A function, method or loop invocation." 120 class Return(Node): "Return an evaluated expression." 121 class Assign(Node): "A grouping node for assignment-related operations." 122 class Keyword(Node): "A grouping node for keyword arguments." 123 class Global(Node): "A global name designator." 124 class Import(Node): "A module import operation." 125 class LoadTemp(Node): "Load a previously-stored temporary value." 126 class LoadName(Node): "Load a named object." 127 class LoadAttr(Node): "Load an object attribute." 128 class LoadConst(Node): "Load a constant." 129 class LoadRef(Node): "Load a reference, typically a subprogram." 130 class LoadExc(Node): "Load a handled exception." 131 class StoreTemp(Node): "Store a temporary value." 132 class StoreName(Node): "Associate a name with an object." 133 class StoreAttr(Node): "Associate an object's attribute with a value." 134 class ReleaseTemp(Node): "Release a temporary value." 135 class Conditional(Node): "A conditional node consisting of a test and outcomes." 136 class Try(Node): "A try...except...else...finally grouping node." 137 class Raise(Node): "An exception raising node." 138 class Not(Node): "A negation of an expression." 139 140 class Visitor(ASTVisitor): 141 def __init__(self): 142 ASTVisitor.__init__(self) 143 144 def default(self, node, *args): 145 raise ValueError, node.__class__ 146 147 def dispatch(self, node, *args): 148 return ASTVisitor.dispatch(self, node, *args) 149 150 def dispatches(self, nodes, *args): 151 results = [] 152 for node in nodes: 153 results.append(self.dispatch(node, *args)) 154 return results 155 156 # vim: tabstop=4 expandtab shiftwidth=4