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 choices Any choices which may be included in the final program. 79 """ 80 81 def __init__(self, original=None, **kw): 82 self.original = original 83 if self.original is not None: 84 self.original._node = self 85 for name, value in kw.items(): 86 setattr(self, name, value) 87 88 def __repr__(self): 89 if hasattr(self, "name"): 90 return "%s '%s' (at %x)" % (self.__class__, self.name, id(self)) 91 if hasattr(self, "index"): 92 return "%s (%s) (at %x)" % (self.__class__, self.index, id(self)) 93 elif hasattr(self, "value"): 94 return "%s %s (at %x)" % (self.__class__, repr(self.value), id(self)) 95 elif hasattr(self, "ref"): 96 return "%s '%x' (at %x)" % (self.__class__, id(self.ref), id(self)) 97 else: 98 return "%s (at %x)" % (self.__class__, id(self)) 99 100 def _pprint(self, indent, continuation, s): 101 if continuation: 102 print (" " * max(0, indent - len(continuation))) + continuation + s 103 else: 104 print (" " * indent) + s 105 106 def pprint(self, indent=0, continuation=None): 107 self._pprint(indent, continuation, repr(self)) 108 109 # Show other details. 110 111 if hasattr(self, "params"): 112 for name, default in self.params: 113 self._pprint(indent + 2, "( ", "%s -> %s" % (name, default)) 114 if hasattr(self, "star") and self.star: 115 name, default = self.star 116 self._pprint(indent + 2, "( ", "%s -> %s" % (name, default)) 117 if hasattr(self, "dstar") and self.dstar: 118 name, default = self.dstar 119 self._pprint(indent + 2, "( ", "%s -> %s" % (name, default)) 120 if getattr(self, "acquire_locals", 0): 121 self._pprint(indent + 2, "( ", "acquiring locals") 122 if getattr(self, "structure", 0): 123 self._pprint(indent + 2, "( ", "structure '%s'" % self.structure.name) 124 if hasattr(self, "test"): 125 self.test.pprint(indent + 2, "? ") 126 for attr in "code", "body", "else_", "finally_", "choices": 127 if hasattr(self, attr) and getattr(self, attr): 128 self._pprint(indent, "", "{ (%s)" % attr) 129 for node in getattr(self, attr): 130 node.pprint(indent + 2) 131 self._pprint(indent, "", "}") 132 if hasattr(self, "handler"): 133 self.handler.pprint(indent + 2, "! ") 134 if hasattr(self, "expr"): 135 self.expr.pprint(indent + 2, "- ") 136 if hasattr(self, "nodes"): 137 for node in self.nodes: 138 node.pprint(indent + 2, "- ") 139 if hasattr(self, "lvalue"): 140 self.lvalue.pprint(indent + 2, "= ") 141 if hasattr(self, "args"): 142 for arg in self.args: 143 arg.pprint(indent + 2, "( ") 144 if hasattr(self, "star") and self.star: 145 self.star.pprint(indent + 2, "( ") 146 if hasattr(self, "dstar") and self.dstar: 147 self.dstar.pprint(indent + 2, "( ") 148 149 class Module(Node): "A Python module." 150 class Subprogram(Node): "A subprogram: functions, methods and loops." 151 class Pass(Node): "A placeholder node corresponding to pass." 152 class Invoke(Node): "A function, method or loop invocation." 153 class Return(Node): "Return an evaluated expression." 154 class Assign(Node): "A grouping node for assignment-related operations." 155 class Keyword(Node): "A grouping node for keyword arguments." 156 class Global(Node): "A global name designator." 157 class Import(Node): "A module import operation." 158 class LoadTemp(Node): "Load a previously-stored temporary value." 159 class LoadName(Node): "Load a named object." 160 class LoadGlobal(Node): "Load a named global object." 161 class LoadAttr(Node): "Load an object attribute." 162 class LoadRef(Node): "Load a reference, typically a subprogram." 163 class LoadExc(Node): "Load a handled exception." 164 class StoreTemp(Node): "Store a temporary value." 165 class StoreName(Node): "Associate a name with an object." 166 class StoreGlobal(Node): "Associate a name with an object in the global namespace." 167 class StoreAttr(Node): "Associate an object's attribute with a value." 168 class ReleaseTemp(Node): "Release a temporary value." 169 class Conditional(Node): "A conditional node consisting of a test and outcomes." 170 class Try(Node): "A try...except...else...finally grouping node." 171 class Raise(Node): "An exception raising node." 172 class Not(Node): "A negation of an expression." 173 class Choice(Node): "A special node which indicates a choice of expressions." 174 175 # Special non-program nodes. 176 177 class Structure: 178 179 "A non-program node containing some kind of namespace." 180 181 def __init__(self, **kw): 182 for name, value in kw.items(): 183 setattr(self, name, value) 184 185 def __repr__(self): 186 if hasattr(self, "name"): 187 return "%s '%s' (at %x)" % (self.__class__, self.name, id(self)) 188 else: 189 return "%s (at %x)" % (self.__class__, id(self)) 190 191 class Class(Structure): "A Python class." 192 class Instance(Structure): "An instance." 193 class Constant(Instance): "A constant." 194 195 # vim: tabstop=4 expandtab shiftwidth=4