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 # Annotations. 148 149 if hasattr(self, "accesses"): 150 self._pprint(indent, "", "--------") 151 for ref, attributes in self.accesses.items(): 152 self._pprint(indent + 2, "| ", "%s: %s" % (ref, attributes)) 153 self._pprint(indent, "", "--------") 154 155 class Module(Node): "A Python module." 156 class Subprogram(Node): "A subprogram: functions, methods and loops." 157 class Pass(Node): "A placeholder node corresponding to pass." 158 class Invoke(Node): "A function, method or loop invocation." 159 class Return(Node): "Return an evaluated expression." 160 class Assign(Node): "A grouping node for assignment-related operations." 161 class Keyword(Node): "A grouping node for keyword arguments." 162 class Global(Node): "A global name designator." 163 class Import(Node): "A module import operation." 164 class LoadTemp(Node): "Load a previously-stored temporary value." 165 class LoadName(Node): "Load a named object." 166 class LoadAttr(Node): "Load an object attribute." 167 class LoadRef(Node): "Load a reference, typically a subprogram or a constant." 168 class LoadExc(Node): "Load a handled exception." 169 class StoreTemp(Node): "Store a temporary value." 170 class StoreName(Node): "Associate a name with an object." 171 class StoreAttr(Node): "Associate an object's attribute with a value." 172 class ReleaseTemp(Node): "Release a temporary value." 173 class Conditional(Node): "A conditional node consisting of a test and outcomes." 174 class Try(Node): "A try...except...else...finally grouping node." 175 class Raise(Node): "An exception raising node." 176 class Not(Node): "A negation of an expression." 177 class Choice(Node): "A special node which indicates a choice of expressions." 178 179 # Special non-program nodes. 180 181 class Structure: 182 183 "A non-program node containing some kind of namespace." 184 185 def __init__(self, **kw): 186 for name, value in kw.items(): 187 setattr(self, name, value) 188 189 def __repr__(self): 190 if hasattr(self, "name"): 191 return "%s '%s' (at %x)" % (self.__class__, self.name, id(self)) 192 else: 193 return "%s (at %x)" % (self.__class__, id(self)) 194 195 class Class(Structure): 196 197 "A Python class." 198 199 class Instance(Structure): 200 201 "An instance." 202 203 def __init__(self, **kw): 204 Structure.__init__(self, **kw) 205 self.types = [self] 206 207 class Constant(Instance): 208 209 "A constant initialised with a type name for future processing." 210 211 def __init__(self, **kw): 212 Instance.__init__(self, **kw) 213 self.typename = self.value.__class__.__name__ 214 215 # vim: tabstop=4 expandtab shiftwidth=4