Skip to content

Commit 2436896

Browse files
authored
Merge pull request #58 from harp-project/gergo_symbolic
Property Verification for the frame stack semantics
2 parents ca4dbcd + b234b41 commit 2436896

4 files changed

Lines changed: 1361 additions & 0 deletions

File tree

_CoqProject

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ src/Interpreter/Scheduler.v
5656
src/Interpreter/Equivalences.v
5757
src/Interpreter/ExampleASTs
5858

59+
src/Symbolic/SymbTheorems.v
60+
src/Symbolic/SymbTactics.v
61+
src/Symbolic/SymbExamples.v
62+
5963
src/BigStep/Syntax.v
6064
src/BigStep/Induction.v
6165
src/BigStep/Equalities.v

src/Symbolic/SymbExamples.v

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
From CoreErlang.FrameStack Require Import SubstSemantics SubstSemanticsLemmas.
2+
From CoreErlang.Interpreter Require Import StepFunctions Equivalences.
3+
From CoreErlang.Symbolic Require Import SymbTheorems SymbTactics.
4+
5+
Import ListNotations.
6+
7+
(** This file gives some examples for the "solve_symbolically" tactic.
8+
*)
9+
10+
Definition fact_frameStack (e : Exp) : Exp :=
11+
ELetRec
12+
[(1, °ECase (˝VVar 1) [
13+
([PLit 0%Z], ˝ttrue, (˝VLit 1%Z));
14+
([PVar], ˝ttrue,
15+
°ELet 1 (EApp (˝VFunId (1, 1))
16+
[°ECall (˝VLit "erlang"%string) (˝VLit "-"%string) [˝VVar 0; ˝VLit 1%Z]])
17+
(°ECall (˝VLit "erlang"%string) (˝VLit "*"%string) [˝VVar 1; ˝VVar 0])
18+
)
19+
])]
20+
(EApp (˝VFunId (0, 1)) [e])
21+
.
22+
23+
(* Proving that fact_frameStack is equivalent to Coq's factorial.
24+
This requires some manual work for proving the postcondition in the inductive case.
25+
*)
26+
Theorem fact_eval_ex:
27+
forall (z : Z), (0 <= z)%Z ->
28+
exists (y : Z),
29+
⟨ [], (fact_frameStack (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ (y = Z.of_nat (Factorial.fact (Z.to_nat z))%Z).
30+
Proof.
31+
solve_symbolically z.
32+
33+
destruct PreCond0. subst.
34+
destruct H. subst. clear H.
35+
rewrite Z2Nat.inj_sub;[|lia].
36+
assert (Z.to_nat 1%Z = 1). { lia. }
37+
rewrite H. clear H.
38+
rewrite Z2Nat.inj_pos.
39+
rewrite <- positive_nat_Z at 1.
40+
rewrite <- Nat2Z.inj_mul. f_equal.
41+
remember (Pos.to_nat p) as k.
42+
destruct k.
43+
* lia.
44+
* simpl. rewrite Nat.sub_0_r. reflexivity.
45+
Qed.
46+
47+
Definition tailrec_fact (e d : Exp) : Exp :=
48+
ELetRec [
49+
(2, °ECase (˝VVar 1) [
50+
([PLit (Integer 0%Z)], ˝ttrue, ˝VVar 2);
51+
([PVar], ˝ttrue,
52+
(°EApp (˝VFunId (1, 2))
53+
[°ECall (˝erlang) (˝VLit "-"%string) [˝VVar 0; ˝VLit 1%Z];
54+
°ECall (˝erlang) (˝VLit "*"%string) [˝VVar 0; ˝VVar 3]
55+
]))
56+
]
57+
)
58+
] (EApp (˝VFunId (0, 2)) [e; d])
59+
.
60+
61+
(* Proving that tailrec_fact works equivalently to Coq's factorial.
62+
This also requires some manual work for the postcondition, and also when stating
63+
the theorem itself it needs to be proven for a general second argument.
64+
*)
65+
Theorem fact_tailrec_eval_ex:
66+
forall (z : Z) (z' : Z), (0 <= z)%Z ->
67+
exists (y : Z),
68+
⟨ [], (tailrec_fact (˝VLit z) (˝VLit z')) ⟩ -->* RValSeq [VLit y] /\ (y = Z.of_nat (Factorial.fact (Z.to_nat z)) * z')%Z.
69+
Proof.
70+
solve_symbolically z z'.
71+
72+
destruct PreCond0. subst.
73+
rewrite Z.mul_assoc. f_equal.
74+
rewrite <- positive_nat_Z.
75+
rewrite <- Nat2Z.inj_mul. f_equal.
76+
assert (1%Z = Z.of_nat (Z.to_nat 1%Z))%Z by lia. rewrite H0. clear H0.
77+
rewrite <- Nat2Z.inj_sub;[|lia].
78+
do 2 rewrite Nat2Z.id.
79+
remember (Pos.to_nat p) as k.
80+
pose proof Pos2Nat.is_pos p.
81+
destruct k; try lia.
82+
simpl.
83+
rewrite Nat.sub_0_r. lia.
84+
Qed.
85+
86+
Definition timestwo (e : Exp) : Exp :=
87+
ELetRec [
88+
(1, °ECall (˝erlang) (˝VLit "*"%string) [˝VVar 1; ˝VLit 2%Z]
89+
90+
)
91+
] (EApp (˝VFunId (0, 1)) [e]).
92+
93+
Definition timestwo' (e : Exp) : Exp :=
94+
°ECall (˝erlang) (˝VLit "*"%string) [e; ˝VLit 2%Z].
95+
96+
(* The tactic works with functions that are defined to be recursive, but actually are not. *)
97+
Theorem timestwo_ex:
98+
forall (z : Z), True ->
99+
exists (y : Z),
100+
⟨ [], (timestwo (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ (y = z * 2)%Z.
101+
Proof.
102+
solve_symbolically z.
103+
Qed.
104+
105+
(* The tactic works for non-recursive functions. *)
106+
Theorem timestwo'_ex:
107+
forall (z : Z), True ->
108+
exists (y : Z),
109+
⟨ [], (timestwo' (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ (y = z * 2)%Z.
110+
Proof.
111+
solve_symbolically z.
112+
Qed.
113+
114+
Definition times_two_simple (e : Exp) : Exp :=
115+
(EExp (ECall (VVal (VLit (Atom "erlang"%string))) (VVal (VLit (Atom "*"%string))) [e;(VVal (VLit (Integer (2))))])).
116+
117+
(* Multiplying by two, using 'erlang':'*' *)
118+
Theorem times_two_simple_ex:
119+
forall (z : Z), True ->
120+
exists (y : Z),
121+
⟨ [], (times_two_simple (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ (y = z * 2)%Z.
122+
Proof.
123+
solve_symbolically z.
124+
Qed.
125+
126+
Definition times_two_rec (e : Exp) : Exp := ELetRec [
127+
(1, (EExp (ECase (VVal (VVar 1))
128+
[
129+
([(PLit (Integer (0)))], (VVal (VLit (Atom "true"%string))), (VVal (VLit (Integer (0)))));
130+
([PVar], (VVal (VLit (Atom "true"%string))),
131+
(EExp (ELet 1 (EExp (ECall (VVal (VLit (Atom "erlang"%string))) (VVal (VLit (Atom "-"%string))) [(VVal (VVar 0));(VVal (VLit (Integer (1))))]))
132+
(EExp (ECall (VVal (VLit (Atom "erlang"%string))) (VVal (VLit (Atom "+"%string))) [(EExp (EApp (VVal (VFunId (2, 1))) [(VVal (VVar 0))]));(VVal (VLit (Integer (2))))])))))])))]
133+
134+
(EApp (VVal (VFunId (0, 1))) [e]).
135+
136+
(* Multiplying by two, using a recursive definition. (1 argument for the tactic) *)
137+
Theorem times_two_rec_ex:
138+
forall (z : Z), (0 <= z)%Z ->
139+
exists (y : Z),
140+
⟨ [], (times_two_rec (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ (y = z * 2)%Z.
141+
Proof.
142+
solve_symbolically z.
143+
Qed.
144+
145+
Definition plus_nums_simple (e f : Exp) : Exp :=
146+
(EExp (ECall (VVal (VLit (Atom "erlang"%string))) (VVal (VLit (Atom "+"%string))) [e;f])).
147+
148+
(* Adding two numbers using 'erlang':'+'. *)
149+
Theorem plus_nums_simple_ex:
150+
forall (z : Z) (z' : Z), True ->
151+
exists (y : Z),
152+
⟨ [], (plus_nums_simple (˝VLit z) (˝VLit z')) ⟩ -->* RValSeq [VLit y] /\ (y = z + z')%Z.
153+
Proof.
154+
solve_symbolically z.
155+
Qed.
156+
157+
Definition plus_nums_rec (e f : Exp) := ELetRec [(2, (EExp (ECase (VVal (VVar 1)) [([(PLit (Integer (0)))], (VVal (VLit (Atom "true"%string))), (VVal (VVar 2)));([PVar], (VVal (VLit (Atom "true"%string))), (EExp (ELet 1 (EExp (ECall (VVal (VLit (Atom "erlang"%string))) (VVal (VLit (Atom "-"%string))) [(VVal (VVar 0));(VVal (VLit (Integer (1))))])) (EExp (ELet 1 (EExp (ECall (VVal (VLit (Atom "erlang"%string))) (VVal (VLit (Atom "+"%string))) [(VVal (VVar 4));(VVal (VLit (Integer (1))))])) (EExp (EApp (VVal (VFunId (3, 2))) [(VVal (VVar 1));(VVal (VVar 0))])))))))])))] (EApp (VVal (VFunId (0, 2))) [e;f]).
158+
159+
Theorem plus_nums_rec_ex:
160+
forall (z : Z),
161+
exists (y : Z),
162+
⟨ [], (plus_nums_rec (˝VLit z) (˝VLit 0%Z)) ⟩ -->* RValSeq [VLit y] /\ (y = z)%Z.
163+
Proof.
164+
(* This cannot be proven by induction, since the goal is too specific. *)
165+
Abort.
166+
167+
(* Adding two numbers using a recursive definition. (2 arguments for the tactic) *)
168+
Theorem plus_nums_rec_ex':
169+
forall (z : Z) (z' : Z), (z >= 0)%Z ->
170+
exists (y : Z),
171+
⟨ [], (plus_nums_rec (˝VLit z) (˝VLit z')) ⟩ -->* RValSeq [VLit y] /\ (y = z + z')%Z.
172+
Proof.
173+
solve_symbolically z z'.
174+
Qed.
175+
176+
Definition isitzero_atom (e : Exp) : Exp :=
177+
(EExp (ECase (e) [([(PLit (Integer (0)))], (VVal (VLit (Atom "true"%string))), (VVal (VLit (Atom "true"%string))));([PVar], (VVal (VLit (Atom "true"%string))), (VVal (VLit (Atom "false"%string))))])).
178+
179+
(* Theorem with atom in the postcondition instead of Z. This is just a case expression,
180+
not a function application. *)
181+
Theorem isitzero_atom_ex:
182+
forall (z : Z), (z >= 0)%Z ->
183+
exists (y : string),
184+
⟨ [], (isitzero_atom (˝VLit (Z.succ z))) ⟩ -->* RValSeq [VLit y] /\ (y = "false"%string)%Z.
185+
Proof.
186+
solve_symbolically z.
187+
Qed.
188+
189+
Definition isitzero_num (e : Exp) : Exp :=
190+
(EExp (ECase (e) [([(PLit (Integer (0)))], (VVal (VLit (Atom "true"%string))), (VVal (VLit (Integer (1)))));([PVar], (VVal (VLit (Atom "true"%string))), (VVal (VLit (Integer (0)))))])).
191+
192+
Theorem isitzero_num_ex:
193+
forall (z : Z), True ->
194+
exists (y : Z),
195+
⟨ [], (isitzero_num (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ ((y = 0)%Z \/ (y = 1)%Z).
196+
Proof.
197+
solve_symbolically z.
198+
Qed.
199+
200+
Definition isitzero_num_app (e : Exp) : Exp :=
201+
EExp ( EApp ( EFun 1 (EExp (ECase (VVal (VVar 0)) [([(PLit (Integer (0)))], (VVal (VLit (Atom "true"%string))), (VVal (VLit (Integer (1)))));([PVar], (VVal (VLit (Atom "true"%string))), (VVal (VLit (Integer (0)))))]))) [e]).
202+
203+
Theorem isitzero_num_app_ex:
204+
forall (z : Z), True ->
205+
exists (y : Z),
206+
⟨ [], (isitzero_num_app (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ ((y = 0)%Z \/ (y = 1)%Z).
207+
Proof.
208+
solve_symbolically z.
209+
Qed.
210+
211+
(* Theorem with atom in the postcondition instead of Z. *)
212+
Definition isitzero_atom_app (e : Exp) : Exp :=
213+
EExp ( EApp ( EFun 1(EExp (ECase (VVal (VVar 0)) [([(PLit (Integer (0)))], (VVal (VLit (Atom "true"%string))), (VVal (VLit (Atom "true"%string))));([PVar], (VVal (VLit (Atom "true"%string))), (VVal (VLit (Atom "false"%string))))]))) [e]).
214+
215+
Theorem isitzero_atom_app_ex:
216+
forall (z : Z), (z > 0)%Z ->
217+
exists (y : string),
218+
⟨ [], (isitzero_atom_app (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ (y = "false"%string).
219+
Proof.
220+
solve_symbolically z.
221+
Qed.
222+
223+
Theorem timestwo_ex':
224+
forall (z : Z),
225+
exists (y : Z),
226+
⟨ [], (times_two_simple (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ (y = z * 2)%Z.
227+
Proof.
228+
solve_symbolically z.
229+
Qed.
230+
231+
Definition times_two_simple_app (e : Exp) : Exp :=
232+
EExp (EApp (EExp (EFun 1 (EExp (ECall (VVal (VLit (Atom "erlang"%string))) (VVal (VLit (Atom "*"%string))) [(VVal (VVar 0));(VVal (VLit (Integer (2))))])))) [e]).
233+
234+
Theorem timestwo_ex'':
235+
forall (z : Z),
236+
exists (y : Z),
237+
⟨ [], (times_two_simple_app (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ (y = z * 2)%Z.
238+
Proof.
239+
solve_symbolically z.
240+
Qed.
241+
242+
Theorem timestwo_ex''':
243+
forall (z : Z), (0 <= z)%Z ->
244+
exists (y : Z),
245+
⟨ [], (times_two_rec (˝VLit z)) ⟩ -->* RValSeq [VLit y] /\ (y = z * 2)%Z.
246+
Proof.
247+
solve_symbolically z.
248+
Qed.

0 commit comments

Comments
 (0)