Mercurial > pysmcl
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.