1.1 --- a/annotate.py Fri Jul 28 00:20:57 2006 +0200
1.2 +++ b/annotate.py Sun Jul 30 02:00:33 2006 +0200
1.3 @@ -46,6 +46,39 @@
1.4
1.5 # Namespaces and related abstractions.
1.6
1.7 +class Namespace:
1.8 +
1.9 + """
1.10 + A local namespace which may either relate to a genuine set of function
1.11 + locals or the initialisation of a structure.
1.12 + """
1.13 +
1.14 + def __init__(self, structure=None):
1.15 + self.structure = structure
1.16 + self.names = {}
1.17 +
1.18 + def store(self, name, types):
1.19 + self.names[name] = types
1.20 +
1.21 + def load(self, name):
1.22 + return self.names[name]
1.23 +
1.24 + def merge(self, name, types):
1.25 + if not self.names.has_key(name):
1.26 + self.names[name] = types
1.27 + else:
1.28 + existing = self.names[name]
1.29 + for type in types:
1.30 + if type not in existing:
1.31 + existing.append(type)
1.32 +
1.33 + def merge_namespace(self, namespace):
1.34 + self.merge_items(namespace.names.items())
1.35 +
1.36 + def merge_items(self, items):
1.37 + for name, types in items:
1.38 + self.merge(name, types)
1.39 +
1.40 class Attribute:
1.41
1.42 """
1.43 @@ -94,7 +127,7 @@
1.44
1.45 self.namespace = Namespace(structure=getattr(node, "structure", None))
1.46 if locals is not None:
1.47 - self.namespace.merge(locals)
1.48 + self.namespace.merge_namespace(locals)
1.49
1.50 # Determine the global namespace.
1.51
1.52 @@ -153,11 +186,6 @@
1.53 def dispatch(self, node, *args):
1.54 return Visitor.dispatch(self, node, *args)
1.55
1.56 - def visitGlobal(self, global_):
1.57 - for name in global_.names:
1.58 - self.namespace.make_global(name)
1.59 - return global_
1.60 -
1.61 def visitLoadRef(self, loadref):
1.62 self.types = [loadref.ref]
1.63 self.annotate(loadref)
1.64 @@ -181,10 +209,7 @@
1.65
1.66 def visitStoreGlobal(self, storeglobal):
1.67 storeglobal.expr = self.dispatch(storeglobal.expr)
1.68 -
1.69 - # NOTE: This may always be a merge operation.
1.70 -
1.71 - self.global_namespace.store(storeglobal.name, self.types)
1.72 + self.global_namespace.merge(storeglobal.name, self.types)
1.73 return storeglobal
1.74
1.75 def visitLoadTemp(self, loadtemp):
2.1 --- a/fixnames.py Fri Jul 28 00:20:57 2006 +0200
2.2 +++ b/fixnames.py Sun Jul 30 02:00:33 2006 +0200
2.3 @@ -98,7 +98,7 @@
2.4 value = getattr(node, attr, None)
2.5 if value is not None:
2.6 setattr(node, attr, self.dispatch(value))
2.7 - for attr in ("body", "else_", "finally_", "code"):
2.8 + for attr in ("body", "else_", "finally_", "code", "choices"):
2.9 value = getattr(node, attr, None)
2.10 if value is not None:
2.11 setattr(node, attr, self.dispatches(value))
2.12 @@ -133,4 +133,48 @@
2.13 self.namespace.store(storename.name)
2.14 return storename
2.15
2.16 +class Namespace:
2.17 +
2.18 + """
2.19 + A local namespace which may either relate to a genuine set of function
2.20 + locals or the initialisation of a structure.
2.21 + """
2.22 +
2.23 + def __init__(self, structure=None):
2.24 + self.structure = structure
2.25 + if structure is not None:
2.26 + self.local = "structure"
2.27 + else:
2.28 + self.local = "local"
2.29 + self.names = {}
2.30 + self.not_local = []
2.31 +
2.32 + def make_global(self, name):
2.33 + if name not in self.not_local:
2.34 + self.not_local.append(name)
2.35 +
2.36 + def find_for_store(self, name):
2.37 + if name not in self.not_local:
2.38 + return self.local
2.39 + else:
2.40 + return "global"
2.41 +
2.42 + def find_for_load(self, name):
2.43 + if name not in self.not_local and self.names.has_key(name):
2.44 + return self.local
2.45 + else:
2.46 + return "global"
2.47 +
2.48 + def store(self, name, types=None):
2.49 + if name not in self.not_local:
2.50 + self.names[name] = types
2.51 + else:
2.52 + raise KeyError, name
2.53 +
2.54 + def load(self, name):
2.55 + if name in self.not_local or not self.names.has_key(name):
2.56 + raise KeyError, name
2.57 + else:
2.58 + return self.names[name]
2.59 +
2.60 # vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/simplified.py Fri Jul 28 00:20:57 2006 +0200
3.2 +++ b/simplified.py Sun Jul 30 02:00:33 2006 +0200
3.3 @@ -75,6 +75,7 @@
3.4 else_ Any conditional code depending on the failure of a test.
3.5 finally_ Any code which will be executed regardless.
3.6 code Any unconditional code.
3.7 + choices Any choices which may be included in the final program.
3.8 """
3.9
3.10 def __init__(self, original=None, **kw):
3.11 @@ -122,7 +123,7 @@
3.12 self._pprint(indent + 2, "( ", "structure '%s'" % self.structure.name)
3.13 if hasattr(self, "test"):
3.14 self.test.pprint(indent + 2, "? ")
3.15 - for attr in "code", "body", "else_", "finally_":
3.16 + for attr in "code", "body", "else_", "finally_", "choices":
3.17 if hasattr(self, attr) and getattr(self, attr):
3.18 self._pprint(indent, "", "{ (%s)" % attr)
3.19 for node in getattr(self, attr):
3.20 @@ -169,6 +170,7 @@
3.21 class Try(Node): "A try...except...else...finally grouping node."
3.22 class Raise(Node): "An exception raising node."
3.23 class Not(Node): "A negation of an expression."
3.24 +class Choice(Node): "A special node which indicates a choice of expressions."
3.25
3.26 # Special non-program nodes.
3.27
3.28 @@ -190,61 +192,4 @@
3.29 class Instance(Structure): "An instance."
3.30 class Constant(Instance): "A constant."
3.31
3.32 -class Namespace:
3.33 -
3.34 - """
3.35 - A local namespace which may either relate to a genuine set of function
3.36 - locals or the initialisation of a structure.
3.37 - """
3.38 -
3.39 - def __init__(self, structure=None):
3.40 - self.structure = structure
3.41 - if structure is not None:
3.42 - self.local = "structure"
3.43 - else:
3.44 - self.local = "local"
3.45 - self.names = {}
3.46 - self.not_local = []
3.47 -
3.48 - def make_global(self, name):
3.49 - if name not in self.not_local:
3.50 - self.not_local.append(name)
3.51 -
3.52 - def find_for_store(self, name):
3.53 - if name not in self.not_local:
3.54 - return self.local
3.55 - else:
3.56 - return "global"
3.57 -
3.58 - def find_for_load(self, name):
3.59 - if name not in self.not_local and self.names.has_key(name):
3.60 - return self.local
3.61 - else:
3.62 - return "global"
3.63 -
3.64 - def store(self, name, types=None):
3.65 - if name not in self.not_local:
3.66 - self.names[name] = types
3.67 - else:
3.68 - raise KeyError, name
3.69 -
3.70 - def load(self, name):
3.71 - if name in self.not_local or not self.names.has_key(name):
3.72 - raise KeyError, name
3.73 - else:
3.74 - return self.names[name]
3.75 -
3.76 - def merge(self, namespace):
3.77 - self.merge_items(namespace.names.items())
3.78 -
3.79 - def merge_items(self, items):
3.80 - for name, types in items:
3.81 - if not self.names.has_key(name):
3.82 - self.names[name] = types
3.83 - else:
3.84 - existing = self.names[name]
3.85 - for type in types:
3.86 - if type not in existing:
3.87 - existing.append(type)
3.88 -
3.89 # vim: tabstop=4 expandtab shiftwidth=4
4.1 --- a/simplify.py Fri Jul 28 00:20:57 2006 +0200
4.2 +++ b/simplify.py Sun Jul 30 02:00:33 2006 +0200
4.3 @@ -415,6 +415,17 @@
4.4 def visitInvert(self, invert):
4.5 return Invoke(invert, expr=LoadAttr(expr=self.dispatch(invert.expr), name="__invert__"), args=[])
4.6
4.7 + def visitAdd(self, add):
4.8 +
4.9 + # NOTE: Strictly one of the choices must be evaluated, never more than one.
4.10 +
4.11 + result = Choice(add)
4.12 + result.choices = [
4.13 + Invoke(expr=LoadAttr(expr=self.dispatch(add.left), name="__add__"), args=[self.dispatch(add.right)]),
4.14 + Invoke(expr=LoadAttr(expr=self.dispatch(add.right), name="__radd__"), args=[self.dispatch(add.left)])
4.15 + ]
4.16 + return result
4.17 +
4.18 # Assignments.
4.19
4.20 augassign_methods = {
4.21 @@ -776,7 +787,7 @@
4.22 # Exception node transformations.
4.23
4.24 def visitTryFinally(self, tryfinally):
4.25 - result = Try(tryfinally, body=[], handlers=[], else_=[], finally_=[])
4.26 + result = Try(tryfinally, body=[], else_=[], finally_=[])
4.27 if tryfinally.body is not None:
4.28 result.body = self.dispatch(tryfinally.body)
4.29 if tryfinally.final is not None:
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/tests/operators.py Sun Jul 30 02:00:33 2006 +0200
5.3 @@ -0,0 +1,2 @@
5.4 +a = 1 + 1.1
5.5 +b = a + 2