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 # Elementary visitor support. 27 28 class Visitor(ASTVisitor): 29 30 "A visitor base class." 31 32 def __init__(self): 33 ASTVisitor.__init__(self) 34 35 def default(self, node, *args): 36 raise ValueError, node.__class__ 37 38 def dispatch(self, node, *args): 39 return ASTVisitor.dispatch(self, node, *args) 40 41 def dispatches(self, nodes, *args): 42 results = [] 43 for node in nodes: 44 results.append(self.dispatch(node, *args)) 45 return results 46 47 # Simplified program nodes. 48 49 class Node: 50 51 """ 52 A result node with common attributes: 53 54 original The original node from which this node was created. 55 name Any name involved (variable or attribute). 56 index Any index involved (temporary variable name). 57 value Any constant value. 58 ref Any reference to (for example) subprograms. 59 60 Expression-related attributes: 61 62 expr Any contributing expression. 63 lvalue Any target expression. 64 test Any test expression in a conditional instruction. 65 handler Any exception handler selector expression. 66 67 Invocation and subprogram attributes: 68 69 args Any collection of argument nodes. 70 params Any collection of parameter nodes and defaults. 71 72 Statement-grouping attributes: 73 74 body Any conditional code depending on the success of a test. 75 else_ Any conditional code depending on the failure of a test. 76 finally_ Any code which will be executed regardless. 77 code Any unconditional code. 78 """ 79 80 def __init__(self, original=None, **kw): 81 self.original = original 82 if self.original is not None: 83 self.original._node = self 84 for name, value in kw.items(): 85 setattr(self, name, value) 86 87 def __repr__(self): 88 if hasattr(self, "name"): 89 return "%s '%s' (at %x)" % (self.__class__, self.name, id(self)) 90 if hasattr(self, "index"): 91 return "%s (%s) (at %x)" % (self.__class__, self.index, id(self)) 92 elif hasattr(self, "value"): 93 return "%s %s (at %x)" % (self.__class__, repr(self.value), id(self)) 94 elif hasattr(self, "ref"): 95 return "%s '%x' (at %x)" % (self.__class__, id(self.ref), id(self)) 96 else: 97 return "%s (at %x)" % (self.__class__, id(self)) 98 99 def _pprint(self, indent, continuation, s): 100 if continuation: 101 print (" " * max(0, indent - len(continuation))) + continuation + s 102 else: 103 print (" " * indent) + s 104 105 def pprint(self, indent=0, continuation=None): 106 self._pprint(indent, continuation, repr(self)) 107 108 # Show other details. 109 110 if hasattr(self, "params"): 111 for name, default in self.params: 112 self._pprint(indent + 2, "( ", "%s -> %s" % (name, default)) 113 if hasattr(self, "star") and self.star: 114 name, default = self.star 115 self._pprint(indent + 2, "( ", "%s -> %s" % (name, default)) 116 if hasattr(self, "dstar") and self.dstar: 117 name, default = self.dstar 118 self._pprint(indent + 2, "( ", "%s -> %s" % (name, default)) 119 if getattr(self, "acquire_locals", 0): 120 self._pprint(indent + 2, "( ", "acquiring locals") 121 if getattr(self, "structure", 0): 122 self._pprint(indent + 2, "( ", "structure '%s'" % self.structure.name) 123 if hasattr(self, "test"): 124 self.test.pprint(indent + 2, "? ") 125 for attr in "code", "body", "else_", "finally_": 126 if hasattr(self, attr) and getattr(self, attr): 127 self._pprint(indent, "", "{ (%s)" % attr) 128 for node in getattr(self, attr): 129 node.pprint(indent + 2) 130 self._pprint(indent, "", "}") 131 if hasattr(self, "handler"): 132 self.handler.pprint(indent + 2, "! ") 133 if hasattr(self, "expr"): 134 self.expr.pprint(indent + 2, "- ") 135 if hasattr(self, "nodes"): 136 for node in self.nodes: 137 node.pprint(indent + 2, "- ") 138 if hasattr(self, "lvalue"): 139 self.lvalue.pprint(indent + 2, "= ") 140 if hasattr(self, "args"): 141 for arg in self.args: 142 arg.pprint(indent + 2, "( ") 143 if hasattr(self, "star") and self.star: 144 self.star.pprint(indent + 2, "( ") 145 if hasattr(self, "dstar") and self.dstar: 146 self.dstar.pprint(indent + 2, "( ") 147 148 class Module(Node): "A Python module." 149 class Subprogram(Node): "A subprogram: functions, methods and loops." 150 class Pass(Node): "A placeholder node corresponding to pass." 151 class Invoke(Node): "A function, method or loop invocation." 152 class Return(Node): "Return an evaluated expression." 153 class Assign(Node): "A grouping node for assignment-related operations." 154 class Keyword(Node): "A grouping node for keyword arguments." 155 class Global(Node): "A global name designator." 156 class Import(Node): "A module import operation." 157 class LoadTemp(Node): "Load a previously-stored temporary value." 158 class LoadName(Node): "Load a named object." 159 class LoadGlobal(Node): "Load a named global object." 160 class LoadAttr(Node): "Load an object attribute." 161 class LoadRef(Node): "Load a reference, typically a subprogram." 162 class LoadExc(Node): "Load a handled exception." 163 class StoreTemp(Node): "Store a temporary value." 164 class StoreName(Node): "Associate a name with an object." 165 class StoreGlobal(Node): "Associate a name with an object in the global namespace." 166 class StoreAttr(Node): "Associate an object's attribute with a value." 167 class ReleaseTemp(Node): "Release a temporary value." 168 class Conditional(Node): "A conditional node consisting of a test and outcomes." 169 class Try(Node): "A try...except...else...finally grouping node." 170 class Raise(Node): "An exception raising node." 171 class Not(Node): "A negation of an expression." 172 173 # Special non-program nodes. 174 175 class Structure: 176 177 "A non-program node containing some kind of namespace." 178 179 def __init__(self, **kw): 180 for name, value in kw.items(): 181 setattr(self, name, value) 182 183 def __repr__(self): 184 if hasattr(self, "name"): 185 return "%s '%s' (at %x)" % (self.__class__, self.name, id(self)) 186 else: 187 return "%s (at %x)" % (self.__class__, id(self)) 188 189 class Class(Structure): "A Python class." 190 class Instance(Structure): "An instance." 191 class Constant(Instance): "A constant." 192 193 # vim: tabstop=4 expandtab shiftwidth=4