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 66 Invocation and subprogram attributes: 67 68 args Any collection of argument nodes. 69 params Any collection of parameter nodes and defaults. 70 71 Statement-grouping attributes: 72 73 body Any conditional code depending on the success of a test. 74 else_ Any conditional code depending on the failure of a test. 75 handler Any exception handler code. 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_", "handler", "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, "expr"): 133 self.expr.pprint(indent + 2, "- ") 134 if hasattr(self, "nodes"): 135 for node in self.nodes: 136 node.pprint(indent + 2, "- ") 137 if hasattr(self, "lvalue"): 138 self.lvalue.pprint(indent + 2, "= ") 139 if hasattr(self, "args"): 140 for arg in self.args: 141 arg.pprint(indent + 2, "( ") 142 if hasattr(self, "star") and self.star: 143 self.star.pprint(indent + 2, "( ") 144 if hasattr(self, "dstar") and self.dstar: 145 self.dstar.pprint(indent + 2, "( ") 146 147 class Module(Node): "A Python module." 148 class Subprogram(Node): "A subprogram: functions, methods and loops." 149 class Pass(Node): "A placeholder node corresponding to pass." 150 class Invoke(Node): "A function, method or loop invocation." 151 class Return(Node): "Return an evaluated expression." 152 class Assign(Node): "A grouping node for assignment-related operations." 153 class Keyword(Node): "A grouping node for keyword arguments." 154 class Global(Node): "A global name designator." 155 class Import(Node): "A module import operation." 156 class LoadTemp(Node): "Load a previously-stored temporary value." 157 class LoadName(Node): "Load a named object." 158 class LoadGlobal(Node): "Load a named global object." 159 class LoadAttr(Node): "Load an object attribute." 160 class LoadRef(Node): "Load a reference, typically a subprogram or a constant." 161 class LoadExc(Node): "Load a handled exception." 162 class StoreTemp(Node): "Store a temporary value." 163 class StoreName(Node): "Associate a name with an object." 164 class StoreGlobal(Node): "Associate a name with an object in the global namespace." 165 class StoreAttr(Node): "Associate an object's attribute with a value." 166 class ReleaseTemp(Node): "Release a temporary value." 167 class Conditional(Node): "A conditional node consisting of a test and outcomes." 168 class Try(Node): "A try...except...else...finally grouping node." 169 class Raise(Node): "An exception raising node." 170 class Not(Node): "A negation of an expression." 171 class Choice(Node): "A special node which indicates a choice of expressions." 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): 190 191 "A Python class." 192 193 class Instance(Structure): 194 195 "An instance." 196 197 def __init__(self, **kw): 198 Structure.__init__(self, **kw) 199 self.types = [self] 200 201 class Constant(Instance): 202 203 "A constant initialised with a type name for future processing." 204 205 def __init__(self, **kw): 206 Instance.__init__(self, **kw) 207 self.typename = self.value.__class__.__name__ 208 209 # vim: tabstop=4 expandtab shiftwidth=4