# HG changeset patch # User paulb@jeremy # Date 1153347943 -7200 # Node ID 2cb628fe771d4fc5528b7a2f1e0dcc82fd2bfceb # Parent 8b5735c2af54ba37f15719d532d478f4f89c744e Added some global name support: transformation of loads and stores to explicit global operations; a test of global declarations. Fixed dispatching in the annotator so that replaced nodes are incorporated. Removed the parent namespace in annotate.Namespace, adding also specific find methods for loads and stores. Added some support for parameters in the annotator, although actual namespace population will only take place in the context of an active invocation. diff -r 8b5735c2af54 -r 2cb628fe771d annotate.py --- a/annotate.py Wed Jul 19 00:21:49 2006 +0200 +++ b/annotate.py Thu Jul 20 00:25:43 2006 +0200 @@ -25,12 +25,11 @@ import compiler class Namespace: - def __init__(self, local_is_structure=0, parent=None): + def __init__(self, local_is_structure=0): if local_is_structure: self.local = "structure" else: self.local = "local" - self.parent = parent self.names = {} self.not_local = [] @@ -38,21 +37,27 @@ if name not in self.not_local: self.not_local.append(name) - def find(self, name): + def find_for_store(self, name): if name not in self.not_local: return self.local else: return "global" + def find_for_load(self, name): + if name not in self.not_local and self.names.has_key(name): + return self.local + else: + return "global" + def store(self, name, types): if name not in self.not_local: self.names[name] = types else: - self.parent.store(name, types) + raise KeyError, name def load(self, name): if name in self.not_local or not self.names.has_key(name): - return self.parent.load(name) + raise KeyError, name else: return self.names[name] @@ -85,7 +90,7 @@ self.types = None self.temp = {} - def process(self, node): + def process(self, node, global_namespace=None): if hasattr(node, "structure"): self.structure = node.structure has_structure = 1 @@ -94,8 +99,11 @@ has_structure = 0 self.namespace = Namespace(self.structure is not None) + self.global_namespace = global_namespace or self.namespace # NOTE: Improve this. + if has_structure: node.structure.namespace = self.namespace + node.namespace = self.namespace self.visitor = self result = self.dispatch(node) @@ -103,10 +111,26 @@ return result def default(self, node): - for attr in ("args", "params"): + for attr in ("args",): value = getattr(node, attr, None) if value is not None: setattr(node, attr, self.dispatches(value)) + + # NOTE: This will eventually use both defaults and supplied arguments. + + for attr in ("params",): + value = getattr(node, attr, None) + if value is not None: + params = [] + for name, default in value: + if default is not None: + n = self.dispatch(default) + self.namespace.store(name, self.types) + else: + n = None + self.namespace.store(name, []) + params.append((name, n)) + setattr(node, attr, params) for attr in ("expr", "lvalue", "test", "handler", "star", "dstar"): value = getattr(node, attr, None) if value is not None: @@ -122,7 +146,7 @@ def visitGlobal(self, global_): for name in global_.names: - self.make_global(name) + self.namespace.make_global(name) return global_ def visitLoadRef(self, loadref): @@ -130,25 +154,47 @@ return loadref def visitLoadName(self, loadname): - if self.namespace.find(loadname.name) == "structure": + scope = self.namespace.find_for_load(loadname.name) + print "LoadName", scope + if scope == "structure": return self.dispatch(LoadAttr(expr=LoadRef(ref=self.structure), name=loadname.name)) + elif scope == "global": + return self.dispatch(LoadGlobal(name=loadname.name)) else: - self.types = self.namespace.load(loadname, loadname.name) + self.types = self.namespace.load(loadname.name) return loadname def visitStoreName(self, storename): - if self.namespace.find(storename.name) == "structure": + scope = self.namespace.find_for_store(storename.name) + print "StoreName", scope + if scope == "structure": return self.dispatch(StoreAttr(lvalue=LoadRef(ref=self.structure), name=storename.name, expr=storename.expr)) + elif scope == "global": + return self.dispatch(StoreGlobal(name=storename.name, expr=storename.expr)) else: - self.namespace.store(storename, storename.name, self.types) + storename.expr = self.dispatch(storename.expr) + self.namespace.store(storename.name, self.types) return storename + def visitLoadGlobal(self, loadglobal): + self.types = self.global_namespace.load(loadglobal.name) + return loadglobal + + def visitStoreGlobal(self, storeglobal): + storeglobal.expr = self.dispatch(storeglobal.expr) + + # NOTE: This may always be a merge operation. + + self.global_namespace.store(storeglobal.name, self.types) + return storeglobal + def visitLoadTemp(self, loadtemp): index = getattr(loadtemp, "index", None) self.types = self.temp[index] return loadtemp def visitStoreTemp(self, storetemp): + storetemp.expr = self.dispatch(storetemp.expr) index = getattr(storetemp, "index", None) self.temp[index] = self.types return storetemp @@ -159,7 +205,7 @@ return releasetemp def visitLoadAttr(self, loadattr): - self.dispatch(loadattr.expr) + loadattr.expr = self.dispatch(loadattr.expr) types = [] for ref in self.types: types += ref.namespace.load(loadattr.name) @@ -167,9 +213,9 @@ return loadattr def visitStoreAttr(self, storeattr): - self.dispatch(storeattr.expr) + storeattr.expr = self.dispatch(storeattr.expr) expr = self.types - self.dispatch(storeattr.lvalue) + storeattr.lvalue = self.dispatch(storeattr.lvalue) for ref in self.types: ref.namespace.store(storeattr.name, expr) return storeattr diff -r 8b5735c2af54 -r 2cb628fe771d simplified.py --- a/simplified.py Wed Jul 19 00:21:49 2006 +0200 +++ b/simplified.py Thu Jul 20 00:25:43 2006 +0200 @@ -124,12 +124,14 @@ class Import(Node): "A module import operation." class LoadTemp(Node): "Load a previously-stored temporary value." class LoadName(Node): "Load a named object." +class LoadGlobal(Node): "Load a named global object." class LoadAttr(Node): "Load an object attribute." class LoadConst(Node): "Load a constant." class LoadRef(Node): "Load a reference, typically a subprogram." class LoadExc(Node): "Load a handled exception." class StoreTemp(Node): "Store a temporary value." class StoreName(Node): "Associate a name with an object." +class StoreGlobal(Node): "Associate a name with an object in the global namespace." class StoreAttr(Node): "Associate an object's attribute with a value." class ReleaseTemp(Node): "Release a temporary value." class Conditional(Node): "A conditional node consisting of a test and outcomes." diff -r 8b5735c2af54 -r 2cb628fe771d tests/global.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/global.py Thu Jul 20 00:25:43 2006 +0200 @@ -0,0 +1,10 @@ +a = 123 +def f(x): + global a + a = x +def g(a): + b = a +class A: + x = a + global a + y = a