changeset 214:c2f5f0ff0501

range_analysis: refactoring, and support for tuples
author Sigurd Meldgaard <stm@daimi.au.dk>
date Wed, 23 Dec 2009 13:02:01 +0100
parents a507d8d0c6ab
children 98957794e778
files pysmcl/range_analysis.py
diffstat 1 files changed, 42 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/pysmcl/range_analysis.py	Tue Dec 22 17:10:47 2009 +0100
+++ b/pysmcl/range_analysis.py	Wed Dec 23 13:02:01 2009 +0100
@@ -7,7 +7,7 @@
 """
 import pysmcl.ast_wrapper as ast
 from pysmcl import flow
-
+import pysmcl.setup as setup
 
 # Switch to True for debug output printed to std. out.
 debug = False
@@ -109,6 +109,9 @@
         end (dict) A dictionary with variables and their current range.
           May be None if the env is uninitialized.
         """
+
+        prime = self.prime
+
         if debug:
             print "========= Combining ==========="
             print "Node, env", node, env
@@ -117,15 +120,25 @@
             env = {}
         class Visitor(ast.NodeVisitor):
             """Visitor for Python statements."""
-            def __init__(self, prime):
-                """prime (integer) defines the field of computation, Zp."""
-                self.prime = prime
 
             def visit_Assign(self, node):
-                r = range(self.prime, node.value, env)
-                targetVisitor = TargetVisitor(env, r)
-                for target in node.targets:
-                    targetVisitor.visit(target)
+                target = node.targets[0]
+                r = range(prime, node.value, env)
+                if(isinstance(target, ast.Name)):
+                    env[target.id] = r
+                elif(isinstance(target, ast.Subscript)):
+                    env[target.value.id] = combine_range(env[target.value.id], r)
+                else:
+                    raise RuntimeError("Unsupported target of assignment")
+                return env
+
+            def visit_For(self, node):
+                target = node.target
+                r = range(prime, node.iter, env)
+                if(isinstance(target, ast.Name)):
+                    env[target.id] = r
+                else:
+                    raise RuntimeError("Unsupported target of for loop")
                 return env
 
             def visit_FunctionDef(self, node):
@@ -138,7 +151,7 @@
                             break
                 for arg in node.args.args:
                     if not arg.id in param_range:
-                        env[arg.id] = full_range(self.prime)
+                        env[arg.id] = full_range(prime)
                     else:
                         env[arg.id] = param_range[arg.id]
                 return env
@@ -164,7 +177,7 @@
             def generic_visit(self, node):
                 assert False, "Not implemented: "+str(type(node))
 
-        r = Visitor(self.prime).visit(node)
+        r = Visitor().visit(node)
         if debug:
             print "Result of combination", r
             print ""
@@ -204,6 +217,19 @@
             return self.env[node.id]
         return full_range(self.prime)
 
+    def visit_Subscript(self, node):
+        if node.value.id in self.env.keys():
+            return self.env[node.value.id]
+        return full_range(self.prime)
+
+    def visit_List(self, node):
+        if node.elts == []:
+            return full_range(self.prime)
+        else:
+            r = self.visit(node.elts[0])
+            for i in node.elts[1:]:
+                r = combine_range(r, self.visit(node.elts[0]))
+            return r
     def visit_BinOp(self, node):
         # operator = Add | Sub | Mult | Div | Mod | Pow | LShift
         #          | RShift | BitOr | BitXor | BitAnd | FloorDiv
@@ -240,6 +266,12 @@
     def visit_Call(self, node):
         # TODO: Check that random and random_bit are bound to the
         # expected functions
+        if node.func.id == "num_players":
+            return (setup.num_players, setup.num_players)
+        if node.func.id == "players":
+            return (1, setup.num_players)
+        if node.func.id == "id":
+            return (1, setup.nr_of_players)
         if node.func.id == "random":
             return full_range(self.prime)
         if node.func.id == "open":
@@ -248,38 +280,6 @@
             return (0, 1)
         return full_range(self.prime)
 
-class TargetVisitor(ast.NodeVisitor):
-    """TargetVisitor update range of target of an assignment in the
-    given environment.
-
-    The following expression can appear in assignment contexts:
-    Attribute, Subscript, Name, List, Tuple.
-    """
-
-    def __init__(self, env, range):
-        self.env = env
-        self.range = range
-
-    def visit_Attribute(self, value, attr, ctx):
-        raise Exception("NYI, attribute targets")
-
-    def visit_Subscript(self, value, slice, ctx):
-        raise Exception("NYI, subscript targets")
-
-    def visit_Name(self, id):
-        if isinstance(id.parent, ast.Call) and id is id.parent.func:
-            # function names are not considered.
-            return
-        if id in self.env.keys():
-            self.env[id.id] = combine_range(self.env[id.id], self.range)
-        else:
-            self.env[id.id] = self.range
-
-    def visit_List(self, elts, ctx):
-        raise Exception("NYI, list targets")
-
-    def visit_Tuple(self, elts, ctx):
-        raise Exception("NYI, tuple targets")
 
 def combine_env(env1, env2):
     """Combine the two environments env1 and env2.