def visit_If(self, node): cond = self.visit(node.cond) if (not issubclass(cond.type, BoolType)): raise exceptions.LambdaPackTypeException("cond of if statement must be BoolType") body = [self.visit(x) for x in node.body] else_body = [self.visit(x) for x in node.elseBody] return If(cond, body, else_body)
def visit_IndexExpr(self, node): if (isinstance(node.indices, list)): idxs = [self.visit(x) for x in node.indices] else: idxs = [self.visit(node.indices)] out_type = unify([x.type for x in idxs]) if (not issubclass(out_type, IntType)): print("out_type", out_type) raise exceptions.LambdaPackTypeException("Indices in IndexExprs must all of type LinearIntType {0}[{1}]".format(node.matrix_name, [str(x) for x in node.indices])) return IndexExpr(node.matrix_name, idxs)
def visit_Assign(self, node): rhs = self.visit(node.rhs) lhs = node.lhs if (lhs.name in self.decl_types): is_subclass = issubclass(rhs.type, self.decl_types[lhs.name]) is_superclass = issubclass(self.decl_types[lhs.name], rhs.type) if ((not is_subclass) and (not is_superclass)): raise exceptions.LambdaPackTypeException("Variables must be of unifiable type, {0} is type {1} but was assigned {2}".format(lhs.name, self.decl_types[lhs.name], rhs.type)) else: self.decl_types[lhs.name] = rhs.type lhs = self.visit(node.lhs) return Assign(lhs, rhs)
def visit_For(self, node): self.decl_types[node.var] = LinearIntType min_idx = self.visit(node.min) max_idx = self.visit(node.max) linear_max = issubclass(min_idx.type, LinearIntType) linear_min = issubclass(min_idx.type, LinearIntType) if ((not linear_max) or (not linear_min)): raise exceptions.LambdaPackTypeException( "Loop bounds must be LinearIntType") step = self.visit(node.step) body = [self.visit(x) for x in node.body] return For(node.var, min_idx, max_idx, step, body)
def unify(type_list): if (len(type_list) == 1): return type_list[0] if (len(type_list) < 3): t0 = type_list[0] t1 = type_list[0] if (issubclass(t0, t1)): return t1 elif (issubclass(t1, t0)): return t0 else: raise exceptions.LambdaPackTypeException("Non unifiable types {0} vs {1}".format(type_list)) else: t0,t1 = type_list[0], type_list[1] t01 = unify([t0, t1]) return unify([t01] + type_list[2:])
def visit_Reduction(self, node): self.decl_types[node.var] = LinearIntType min_idx = self.visit(node.min) max_idx = self.visit(node.max) if (isinstance(node.expr, list)): expr = [self.visit(x) for x in node.expr] else: expr = [self.visit(node.expr)] for expr_i in expr: if (not isinstance(expr_i, IndexExpr)): raise exceptions.LambdaPackTypeException( "Reduction Exprs must be of IndexExpr type") b_fac = self.visit(node.b_fac) remote_call = self.visit(node.remote_call) recursion = [self.visit(x) for x in node.recursion] return Reduction(node.var, min_idx, max_idx, expr, b_fac, remote_call, recursion)
def python_type_to_lp_type(p_type, const=False): if (p_type is None): return NullType if (issubclass(p_type, int)): if (const): return ConstIntType else: return IntType elif (issubclass(p_type, float)): if (const): return ConstFloatType else: return FloatType elif (issubclass(p_type, bool)): return BoolType elif (issubclass(p_type, BigMatrix)): return BigMatrixType else: raise exceptions.LambdaPackTypeException("Unsupported Python type: {0}".format(p_type))
def visit_BinOp(self, node): right = self.visit(node.right) left = self.visit(node.left) r_type = right.type l_type = left.type op = node.op if (op == "Or" or op == "And"): assert(issubclass(left.type, BoolType)) assert(issubclass(right.type, BoolType)) out_type = BoolType else: if ((r_type is None) or (l_type is None)): raise LambdaPackTypeException("BinOp arguments must be typed") type_set = set([r_type, l_type]) for t in type_set: if (not issubclass(t, NumericalType)): raise LambdaPackTypeException("BinOp arguments must be Numerical") if (op == "Add" or op == "Sub"): # arith type algebra if (issubclass(r_type, ConstIntType) and issubclass(l_type, ConstIntType)): out_type = ConstIntType elif (issubclass(r_type, LinearIntType) and issubclass(l_type, LinearIntType)): out_type = LinearIntType elif (issubclass(r_type, IntType) and issubclass(l_type, IntType)): out_type = IntType elif (issubclass(r_type, ConstFloatType) and issubclass(l_type, ConstFloatType)): out_type = ConstFloatType elif (issubclass(r_type, ConstFloatType) and issubclass(l_type, ConstIntType)): out_type = ConstFloatType elif (issubclass(l_type, ConstFloatType) and issubclass(r_type, ConstIntType)): out_type = ConstFloatType elif (issubclass(r_type, FloatType) or issubclass(l_type, FloatType)): out_type = FloatType else: raise exceptions.LambdaPackTypeException("Unsupported type combination for add/sub") elif (op =="Mult"): # mul type algebra if (issubclass(r_type, LinearIntType) and issubclass(l_type, ConstIntType)): out_type = LinearIntType if (issubclass(r_type, LinearIntType) and issubclass(l_type, LinearIntType)): out_type = IntType elif (issubclass(r_type, IntType) and issubclass(l_type, IntType)): out_type = IntType elif (issubclass(r_type, ConstFloatType) and issubclass(l_type, ConstFloatType)): out_type = ConstFloatType elif (issubclass(r_type, ConstFloatType) and issubclass(l_type, ConstIntType)): out_type = ConstFloatType elif (issubclass(r_type, FloatType) or issubclass(l_type, FloatType)): out_type = FloatType else: raise exceptions.LambdaPackTypeException("Unsupported type combination for mul") elif (op =="Div"): # div type algebra if (issubclass(r_type, LinearIntType) and issubclass(l_type, ConstIntType)): out_type = LinearIntType elif (issubclass(r_type, Const) and issubclass(l_type, Const)): out_type = ConstFloatType else: out_type = FloatType elif (op == "Mod"): if (issubclass(r_type, ConstIntType) and issubclass(l_type, ConstIntType)): out_type = ConstIntType elif (issubclass(r_type, IntType) and issubclass(l_type, IntType)): out_type = IntType else: out_type = FloatType elif (op == "Pow"): if (issubclass(r_type, ConstIntType) and issubclass(l_type, ConstIntType)): out_type = ConstIntType elif (issubclass(r_type, IntType) and issubclass(l_type, IntType)): out_type = IntType elif (issubclass(r_type, Const) and issubclass(l_type, Const)): out_type = ConstFloatType else: out_type = FloatType elif (op == "FloorDiv"): if (issubclass(r_type, ConstIntType) and issubclass(l_type, ConstIntType)): out_type = ConstIntType else: out_type = IntType return BinOp(node.op, left, right, out_type)
def visit_Ref(self, node): decl_type = self.decl_types[node.name] if (decl_type is None): raise exceptions.LambdaPackTypeException("Refs must be typed") return Ref(node.name, decl_type)