def value_at(m, k): """Make an AST node for m[k].""" if isinstance(m, target_syntax.EMakeMap2): return syntax.ECond(syntax.EIn(k, m.e), m.value.apply_to(k), construct_value(m.type.v)).with_type(m.type.v) if isinstance(m, syntax.ECond): return syntax.ECond(m.cond, value_at(m.then_branch, k), value_at(m.else_branch, k)).with_type(m.type.v) return target_syntax.EMapGet(m, k).with_type(m.type.v)
def visit_EGetField(self, e): ee = self.visit(e.e) res = syntax.EGetField(ee, e.f).with_type(e.type) if e.e.type == t and e.f == "val": res = syntax.ECond(syntax.EEq(ee, ptr), new_value, res).with_type(e.type) return res
def value_at(m, k): """ Assuming k is in EMapKeys(m), produce the value at k. """ if isinstance(m, target_syntax.EMakeMap2): return m.value.apply_to(k) if isinstance(m, syntax.ECond): return syntax.ECond(m.cond, value_at(m.then_branch, k), value_at(m.else_branch, k)).with_type(m.type.v) return target_syntax.EMapGet(m, k).with_type(m.type.v)
def mutate(e: syntax.Exp, op: syntax.Stm) -> syntax.Exp: """Return the new value of `e` after executing `op`.""" if isinstance(op, syntax.SNoOp): return e elif isinstance(op, syntax.SAssign): return _do_assignment(op.lhs, op.rhs, e) elif isinstance(op, syntax.SCall): if op.func == "add": return mutate( e, syntax.SCall(op.target, "add_all", (syntax.ESingleton( op.args[0]).with_type(op.target.type), ))) elif op.func == "add_all": return mutate( e, syntax.SAssign( op.target, syntax.EBinOp(op.target, "+", op.args[0]).with_type(op.target.type))) elif op.func == "remove": return mutate( e, syntax.SCall(op.target, "remove_all", (syntax.ESingleton( op.args[0]).with_type(op.target.type), ))) elif op.func == "remove_all": return mutate( e, syntax.SAssign( op.target, syntax.EBinOp(op.target, "-", op.args[0]).with_type(op.target.type))) else: raise Exception("Unknown func: {}".format(op.func)) elif isinstance(op, syntax.SIf): then_branch = mutate(e, op.then_branch) else_branch = mutate(e, op.else_branch) if alpha_equivalent(then_branch, else_branch): return then_branch return syntax.ECond(op.cond, then_branch, else_branch).with_type(e.type) elif isinstance(op, syntax.SSeq): if isinstance(op.s1, syntax.SSeq): return mutate(e, syntax.SSeq(op.s1.s1, syntax.SSeq(op.s1.s2, op.s2))) e2 = mutate(mutate(e, op.s2), op.s1) if isinstance(op.s1, syntax.SDecl): e2 = subst(e2, {op.s1.id: op.s1.val}) return e2 elif isinstance(op, syntax.SDecl): return e else: raise NotImplementedError(type(op))
def _update_handle(e: syntax.Exp, handle: syntax.EVar, change): if isinstance(e.type, syntax.TBag) or isinstance(e.type, syntax.TList): return target_syntax.EMap( e, mk_lambda( e.type.t, lambda x: _update_handle(x, handle, change))).with_type(e.type) elif isinstance(e.type, syntax.THandle): if e.type == handle.type: return syntax.ECond(syntax.EEq(e, handle), change(e), e).with_type(e.type) else: return e elif isinstance(e.type, syntax.TTuple): return syntax.ETuple( tuple( _update_handle( syntax.ETupleGet(e, i).with_type(e.type.ts[i]), handle, change) for i in range(len(e.type.ts)))).with_type(e.type) elif e.type == syntax.INT or e.type == syntax.LONG or e.type == syntax.BOOL or e.type == syntax.STRING or isinstance( e.type, syntax.TNative) or isinstance(e.type, syntax.TEnum): return e else: raise NotImplementedError(repr(e.type))
def p_exp(p): """exp : NUM | FLOAT | WORD | WORD OP_OPEN_PAREN exp_list OP_CLOSE_PAREN | KW_TRUE | KW_FALSE | exp OP_PLUS exp | exp OP_MINUS exp | exp OP_TIMES exp | exp OP_EQ exp | exp OP_NE exp | exp OP_LT exp | exp OP_LE exp | exp OP_GT exp | exp OP_GE exp | exp KW_AND exp | exp KW_OR exp | exp OP_IMPLIES exp | exp OP_QUESTION exp OP_COLON exp | exp OP_OPEN_BRACKET slice OP_CLOSE_BRACKET | KW_NOT exp | OP_MINUS exp | exp KW_IN exp | KW_UNIQUE exp | KW_DISTINCT exp | KW_EMPTY exp | KW_THE exp | KW_MIN exp | KW_MAX exp | KW_ARGMIN lambda exp | KW_ARGMAX lambda exp | KW_SUM exp | KW_LEN exp | KW_ANY exp | KW_ALL exp | KW_EXISTS exp | KW_REVERSED exp | exp OP_DOT NUM | exp OP_DOT WORD | OP_OPEN_PAREN exp_list OP_CLOSE_PAREN | OP_OPEN_BRACE record_fields OP_CLOSE_BRACE | OP_OPEN_BRACKET exp OP_CLOSE_BRACKET | OP_OPEN_BRACKET exp OP_VBAR comprehension_body OP_CLOSE_BRACKET""" if len(p) == 2: if type(p[1]) is syntax.ENum: p[0] = p[1] elif p[1] == "true": p[0] = syntax.EBool(True) elif p[1] == "false": p[0] = syntax.EBool(False) else: p[0] = syntax.EVar(p[1]) elif len(p) == 3: if p[1] == "min": p[0] = syntax.EArgMin( p[2], syntax.ELambda(syntax.EVar("x"), syntax.EVar("x"))) elif p[1] == "max": p[0] = syntax.EArgMax( p[2], syntax.ELambda(syntax.EVar("x"), syntax.EVar("x"))) else: p[0] = syntax.EUnaryOp(p[1], p[2]) elif len(p) == 4: if p[1] == "(": exps = p[2] if len(exps) == 0: raise Exception("illegal ()") elif len(exps) == 1: p[0] = exps[0] elif len(exps) > 1: p[0] = syntax.ETuple(tuple(exps)) elif p[1] == "[": p[0] = syntax.ESingleton(p[2]) elif p[1] == "{": p[0] = syntax.EMakeRecord(p[2]) elif p[2] == ".": if isinstance(p[3], syntax.ENum): p[0] = syntax.ETupleGet(p[1], p[3].val) else: p[0] = syntax.EGetField(p[1], p[3]) elif p[1] == "argmin": p[0] = syntax.EArgMin(p[3], p[2]) elif p[1] == "argmax": p[0] = syntax.EArgMax(p[3], p[2]) else: p[0] = syntax.EBinOp(p[1], p[2], p[3]) else: if p[2] == "?": p[0] = syntax.ECond(p[1], p[3], p[5]) elif p[2] == "[": if isinstance(p[3], syntax.Exp): p[0] = syntax.EListGet(p[1], p[3]) elif isinstance(p[3], tuple): start = p[3][0] end = p[3][1] if start is None: start = syntax.ZERO if end is None: end = syntax.ELen(p[1]) p[0] = syntax.EListSlice(p[1], start, end) elif p[1] == "[": p[0] = syntax.EListComprehension(p[2], p[4]) elif p[2] == "(": p[0] = syntax.ECall(p[1], p[3]) else: assert False, "unknown case: {}".format(repr(p[1:]))
def _delta_form(res: {str: syntax.Exp}, op: syntax.Stm) -> {str: syntax.Exp}: if isinstance(op, syntax.SNoOp): pass elif isinstance(op, syntax.SCall): update = _rewriter(op.target) if op.func == "add": update( res, lambda old: syntax.EBinOp( old, "+", syntax.ESingleton(op.args[0]).with_type(old.type)). with_type(old.type)) elif op.func == "add_back": update( res, lambda old: syntax.EBinOp( old, "+", syntax.ESingleton(op.args[0]).with_type(old.type)). with_type(old.type)) elif op.func == "add_front": update( res, lambda old: syntax.EBinOp( syntax.ESingleton(op.args[0]).with_type(old.type), "+", old ).with_type(old.type)) elif op.func == "remove_back": update( res, lambda old: target_syntax.EDropBack(old).with_type(old.type)) elif op.func == "remove_front": update( res, lambda old: target_syntax.EDropFront(old).with_type(old.type)) elif op.func == "remove": update( res, lambda old: syntax.EBinOp( old, "-", syntax.ESingleton(op.args[0]).with_type(old.type)). with_type(old.type)) elif op.func == "remove_all": update( res, lambda old: syntax.EBinOp(old, "-", op.args[0]).with_type( old.type)) else: raise Exception("Unknown func: {}".format(op.func)) elif isinstance(op, syntax.SAssign): update = _rewriter(op.lhs) update(res, lambda old: op.rhs) elif isinstance(op, syntax.SIf): res_then = res.copy() _delta_form(res_then, op.then_branch) res_else = res.copy() _delta_form(res_else, op.else_branch) for key in res: then_val = res_then[key] else_val = res_else[key] if then_val == else_val: res[key] = then_val else: # Substatements differ; need to defer to ECond evaluation. res[key] = syntax.ECond(op.cond, then_val, else_val).with_type(then_val.type) elif isinstance(op, syntax.SSeq): _delta_form(res, op.s1) _delta_form(res, subst(op.s2, res)) else: raise NotImplementedError(type(op)) return res