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, parent=None): 29 self.names = {} 30 self.not_local = [] 31 self.parent = parent 32 33 def make_global(self, name): 34 if name not in self.not_local: 35 self.not_local.append(name) 36 37 def store(self, name, types): 38 if name not in self.not_local: 39 self.names[name] = types 40 else: 41 self.parent.store(name, types) 42 43 def load(self, name): 44 if name in self.not_local or not self.names.has_key(name): 45 return self.parent.load(name) 46 else: 47 return self.names[name] 48 49 def merge(self, namespace): 50 for name, types in namespace.names.items(): 51 if not self.names.has_key(name): 52 self.names[name] = types 53 else: 54 existing = self.names[name] 55 for type in types: 56 if type not in existing: 57 existing.append(type) 58 59 class System: 60 def __init__(self): 61 self.count = 0 62 def init(self, node): 63 if not hasattr(node, "types"): 64 node.types = [] 65 def annotate(self, node, types): 66 for type in types: 67 if type not in node.types: 68 node.types.append(type) 69 self.count += 1 70 71 class Traverser(Visitor): 72 def __init__(self): 73 Visitor.__init__(self) 74 self.system = System() 75 self.types = None 76 self.temp = {} 77 78 def traverse(self, node): 79 self.namespace = Namespace() 80 compiler.walk(node, self, self) 81 if hasattr(node, "structure"): 82 node.structure.namespace = self.namespace 83 84 def default(self, node): 85 for attr in ("args", "params"): 86 value = getattr(node, attr, None) 87 if value is not None: 88 self.dispatches(value) 89 for attr in ("expr", "lvalue", "test", "handler", "star", "dstar"): 90 value = getattr(node, attr, None) 91 if value is not None: 92 self.dispatch(value) 93 for attr in ("body", "else_", "finally_", "code"): 94 value = getattr(node, attr, None) 95 if value is not None: 96 for n in value: 97 self.dispatch(n) 98 print node 99 100 def visitGlobal(self, global_): 101 for name in global_.names: 102 self.make_global(name) 103 104 def visitLoadRef(self, loadref): 105 self.types = [loadref.ref] 106 107 def visitLoadName(self, loadname): 108 self.types = self.namespace.load(loadname.name) 109 110 def visitStoreName(self, storename): 111 self.namespace.store(storename.name, self.types) 112 113 def visitLoadTemp(self, loadtemp): 114 index = getattr(loadtemp, "index", None) 115 self.types = self.temp[index] 116 117 def visitStoreTemp(self, storetemp): 118 index = getattr(storetemp, "index", None) 119 self.temp[index] = self.types 120 121 def visitReleaseTemp(self, releasetemp): 122 index = getattr(releasetemp, "index", None) 123 del self.temp[index] 124 125 # vim: tabstop=4 expandtab shiftwidth=4