1 #!/usr/bin/env python 2 3 """ 4 Traverse and annotate simplified AST structures. 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 simplified import * 25 import compiler 26 27 class Namespace: 28 def __init__(self, local_is_structure=0, parent=None): 29 if local_is_structure: 30 self.local = "structure" 31 else: 32 self.local = "local" 33 self.parent = parent 34 self.names = {} 35 self.not_local = [] 36 37 def make_global(self, name): 38 if name not in self.not_local: 39 self.not_local.append(name) 40 41 def find(self, name): 42 if name not in self.not_local: 43 return self.local 44 else: 45 return "global" 46 47 def store(self, name, types): 48 if name not in self.not_local: 49 self.names[name] = types 50 else: 51 self.parent.store(name, types) 52 53 def load(self, name): 54 if name in self.not_local or not self.names.has_key(name): 55 return self.parent.load(name) 56 else: 57 return self.names[name] 58 59 def merge(self, namespace): 60 for name, types in namespace.names.items(): 61 if not self.names.has_key(name): 62 self.names[name] = types 63 else: 64 existing = self.names[name] 65 for type in types: 66 if type not in existing: 67 existing.append(type) 68 69 class System: 70 def __init__(self): 71 self.count = 0 72 def init(self, node): 73 if not hasattr(node, "types"): 74 node.types = [] 75 def annotate(self, node, types): 76 for type in types: 77 if type not in node.types: 78 node.types.append(type) 79 self.count += 1 80 81 class Annotator(Visitor): 82 def __init__(self): 83 Visitor.__init__(self) 84 self.system = System() 85 self.types = None 86 self.temp = {} 87 88 def process(self, node): 89 if hasattr(node, "structure"): 90 self.structure = node.structure 91 has_structure = 1 92 else: 93 self.structure = None 94 has_structure = 0 95 96 self.namespace = Namespace(self.structure is not None) 97 if has_structure: 98 node.structure.namespace = self.namespace 99 100 self.visitor = self 101 result = self.dispatch(node) 102 103 return result 104 105 def default(self, node): 106 for attr in ("args", "params"): 107 value = getattr(node, attr, None) 108 if value is not None: 109 setattr(node, attr, self.dispatches(value)) 110 for attr in ("expr", "lvalue", "test", "handler", "star", "dstar"): 111 value = getattr(node, attr, None) 112 if value is not None: 113 setattr(node, attr, self.dispatch(value)) 114 for attr in ("body", "else_", "finally_", "code"): 115 value = getattr(node, attr, None) 116 if value is not None: 117 setattr(node, attr, self.dispatches(value)) 118 return node 119 120 def dispatch(self, node, *args): 121 return Visitor.dispatch(self, node, *args) 122 123 def visitGlobal(self, global_): 124 for name in global_.names: 125 self.make_global(name) 126 return global_ 127 128 def visitLoadRef(self, loadref): 129 self.types = [loadref.ref] 130 return loadref 131 132 def visitLoadName(self, loadname): 133 if self.namespace.find(loadname.name) == "structure": 134 return self.dispatch(LoadAttr(expr=LoadRef(ref=self.structure), name=loadname.name)) 135 else: 136 self.types = self.namespace.load(loadname, loadname.name) 137 return loadname 138 139 def visitStoreName(self, storename): 140 if self.namespace.find(storename.name) == "structure": 141 return self.dispatch(StoreAttr(lvalue=LoadRef(ref=self.structure), name=storename.name, expr=storename.expr)) 142 else: 143 self.namespace.store(storename, storename.name, self.types) 144 return storename 145 146 def visitLoadTemp(self, loadtemp): 147 index = getattr(loadtemp, "index", None) 148 self.types = self.temp[index] 149 return loadtemp 150 151 def visitStoreTemp(self, storetemp): 152 index = getattr(storetemp, "index", None) 153 self.temp[index] = self.types 154 return storetemp 155 156 def visitReleaseTemp(self, releasetemp): 157 index = getattr(releasetemp, "index", None) 158 del self.temp[index] 159 return releasetemp 160 161 def visitLoadAttr(self, loadattr): 162 self.dispatch(loadattr.expr) 163 types = [] 164 for ref in self.types: 165 types += ref.namespace.load(loadattr.name) 166 self.types = types 167 return loadattr 168 169 def visitStoreAttr(self, storeattr): 170 self.dispatch(storeattr.expr) 171 expr = self.types 172 self.dispatch(storeattr.lvalue) 173 for ref in self.types: 174 ref.namespace.store(storeattr.name, expr) 175 return storeattr 176 177 # vim: tabstop=4 expandtab shiftwidth=4