def testComputeWP(self): Q = Var("Q", TFun(natFunT, BoolType)) test_data = [ (Assign(zero, Lambda(s, one)), Lambda(s, Q(mk_fun_upd(s, zero, one)))), (Seq(Assign(zero, Lambda(s, one)), Assign(one, Lambda(s, Nat(2)))), Lambda(s, Q(mk_fun_upd(s, zero, one, one, Nat(2))))), ] for c, P in test_data: prf = imp.compute_wp(natFunT, c, Q).export() self.assertEqual(theory.check_proof(prf), Thm([], Valid(P, c, Q)))
def testMkAssign(self): a, b = Var("a", TFun(NatType, NatType)), Var("b", BoolType) var_map = {a: 0, b: 1} s = Var("s", gcl.stateT) test_data = [ ({ a(one): zero }, function.mk_fun_upd(s, Para(Ident(zero), one), NatV(zero))), ({ b: one }, function.mk_fun_upd(s, Ident(one), NatV(one))), ] for assign, res in test_data: self.assertEqual(gcl.mk_assign(var_map, s, assign), res)
def testPrintFunction(self): f = Var("f", TFun(Ta, Ta)) Tb = TVar('b') Tc = TVar('c') g = Var('g', TFun(Tb, Tc)) h = Var('h', TFun(Ta, Tb)) test_data = [ (function.mk_fun_upd(f, a, b), "(f)(a := b)"), (function.mk_fun_upd(f, a, b, b, a), "(f)(a := b, b := a)"), (function.mk_comp(g, h), "g O h"), (function.mk_comp(g, h)(a), "(g O h) a"), (function.mk_const_fun(NatType, nat.zero), "%x::nat. (0::nat)"), ] basic.load_theory('function') with global_setting(unicode=False): for t, s in test_data: self.assertEqual(printer.print_term(t), s)
def process_file(input, output): basic.load_theory('hoare') dn = os.path.dirname(os.path.realpath(__file__)) with open(os.path.join(dn, 'examples/' + input + '.json'), encoding='utf-8') as a: data = json.load(a) output = json_output.JSONTheory(output, ["hoare"], "Generated from " + input) content = data['content'] eval_count = 0 vcg_count = 0 for run in content[:5]: if run['ty'] == 'eval': com = parse_com(run['com']) st1 = mk_const_fun(NatType, nat.zero) for k, v in sorted(run['init'].items()): st1 = mk_fun_upd(st1, Nat(str_to_nat(k)), Nat(v)) st2 = mk_const_fun(NatType, nat.zero) for k, v in sorted(run['final'].items()): st2 = mk_fun_upd(st2, Nat(str_to_nat(k)), Nat(v)) Sem = imp.Sem(natFunT) goal = Sem(com, st1, st2) prf = ProofTerm("eval_Sem", goal, []).export() rpt = ProofReport() th = theory.check_proof(prf, rpt) output.add_theorem("eval" + str(eval_count), th, prf) eval_count += 1 elif run['ty'] == 'vcg': com = parse_com(run['com']) pre = Lambda(st, parse_cond(run['pre'])) post = Lambda(st, parse_cond(run['post'])) Valid = imp.Valid(natFunT) goal = Valid(pre, com, post) prf = imp.vcg_solve(goal).export() rpt = ProofReport() th = theory.check_proof(prf, rpt) output.add_theorem("vcg" + str(vcg_count), th, prf) vcg_count += 1 else: raise TypeError output.export_json()
def testProveAvalIFail(self): s = fun_upd_of_seq(1, 7) s2 = Var("s2", TFun(NatType, NatType)) s3 = function.mk_fun_upd(s2, zero, one) macro = expr.prove_avalI_macro() # Value does not match self.assertFalse(macro.can_eval(expr.avalI(s, V(one), Nat(5)))) # State cannot be evaluated self.assertFalse(macro.can_eval(expr.avalI(s2, V(one), Nat(5)))) self.assertFalse(macro.can_eval(expr.avalI(s3, V(one), Nat(5)))) # Goal is not avalI self.assertFalse(macro.can_eval(Eq(V(one), N(zero))))
def mk_assign(var_map, s, assigns): """Given a dictionary of assignments, form the corresponding term. Example: given var_map {a: 0, b: 1}, where a is a function and b is a scalar. mk_assign(var_map, s, {a(i): 2}) = (s)(Para (Ident 0) i := 2) mk_assign(var_map, s, {b: 1}) = (s)(Ident 1 := 1) """ assign_args = [] for k, v in assigns.items(): k2 = convert_term(var_map, s, k) assert k2.fun == s, "mk_assign: key is not an identifer." assign_args.append(k2.arg) assign_args.append(convert_term(var_map, s, v)) return function.mk_fun_upd(s, *assign_args)
def compute_wp(T, c, Q): """Compute the weakest precondition for the given command and postcondition. Here c is the program and Q is the postcondition. The computation is by case analysis on the form of c. The function returns a proof term showing [...] |- Valid P c Q, where P is the computed precondition, and [...] contains the additional subgoals. """ if c.is_const("Skip"): # Skip return apply_theorem("skip_rule", concl=Valid(T)(Q, c, Q)) elif c.is_comb("Assign", 2): # Assign a b a, b = c.args s = Var("s", T) P2 = Lambda(s, Q(function.mk_fun_upd(s, a, b(s).beta_conv()))) return apply_theorem("assign_rule", inst=Inst(b=b), concl=Valid(T)(P2, c, Q)) elif c.is_comb("Seq", 2): # Seq c1 c2 c1, c2 = c.args wp1 = compute_wp(T, c2, Q) # Valid Q' c2 Q wp2 = compute_wp(T, c1, wp1.prop.args[0]) # Valid Q'' c1 Q' return apply_theorem("seq_rule", wp2, wp1) elif c.is_comb("Cond", 3): # Cond b c1 c2 b, c1, c2 = c.args wp1 = compute_wp(T, c1, Q) wp2 = compute_wp(T, c2, Q) res = apply_theorem("if_rule", wp1, wp2, inst=Inst(b=b)) return res elif c.is_comb("While", 3): # While b I c _, I, _ = c.args pt = apply_theorem("while_rule", concl=Valid(T)(I, c, Q)) pt0 = ProofTerm.assume(pt.assums[0]) pt1 = vcg(T, pt.assums[1]) return pt.implies_elim(pt0, pt1) else: raise NotImplementedError
def testStripFunUpd(self): self.assertEqual(strip_fun_upd(f), (f, [])) self.assertEqual(strip_fun_upd(mk_fun_upd(f, a1, b1)), (f, [(a1, b1)])) self.assertEqual(strip_fun_upd(mk_fun_upd(f, a1, b1, a2, b2)), (f, [(a1, b1), (a2, b2)]))
def testMkFunUpd(self): self.assertEqual(mk_fun_upd(f, a1, b1, a2, b2), mk_fun_upd(mk_fun_upd(f, a1, b1), a2, b2))
def fun_upd_of_seq(*ns): return mk_fun_upd(function.mk_const_fun(NatType, zero), *[Nat(n) for n in ns])