blob: 7c6cab3ff341e725611390299164853938415042 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
Require Import Omega.
Require Import Wellfounded.
Inductive Exp : Set :=
| elit : nat -> Exp
| evar : nat -> Exp
| eadd : Exp -> Exp -> Exp.
Fixpoint eval (env : nat -> nat) (e : Exp) :=
match e with
| elit n => n
| evar n => env n
| eadd a b => eval env a + eval env b
end.
Inductive RPNOp :=
| rpnlit : nat -> RPNOp
| rpnvar : nat -> RPNOp
| rpnadd : RPNOp.
Fixpoint rpn (e : Exp) :=
match e with
| elit n => cons (rpnlit n) nil
| evar n => cons (rpnvar n) nil
| eadd a b => cons rpnadd (app (rpn a) (rpn b))
end.
Definition _fmap A B (f : A -> B) (o : option A) :=
match o with
| Some x => Some (f x)
| None => None
end.
Notation fmap := (_fmap _ _).
Fixpoint rpn_eval' (env : nat -> nat) (rpn : list RPNOp) :=
match rpn with
| nil => Some nil
| cons (rpnlit n) a => fmap (cons n) (rpn_eval' env a)
| cons (rpnvar n) a => fmap (cons (env n)) (rpn_eval' env a)
| cons (rpnadd) a => match rpn_eval' env a with
| Some (cons x (cons y stack)) => Some (cons (x+y) stack)
| _ => None
end
end.
Function rpn_eval (env : nat -> nat) (rpn : list RPNOp) :=
match rpn_eval' env rpn with
| Some (cons x nil) => Some x
| _ => None
end.
Fixpoint exprsize e :=
match e with
| elit _ => 1
| evar _ => 1
| eadd a b => 1 + exprsize a + exprsize b
end.
Lemma exprsize_left e1 e2 : exprsize e1 < exprsize (eadd e1 e2).
Proof. simpl. omega. Qed.
Lemma exprsize_right e1 e2 : exprsize e1 < exprsize (eadd e2 e1).
Proof. simpl. omega. Qed.
Lemma free_append' e1 :
forall env rest results,
Some results = rpn_eval' env rest ->
Some (eval env e1 :: results)%list = rpn_eval' env (app (rpn e1) rest).
Proof.
induction e1 using (well_founded_induction
(wf_inverse_image _ nat _ exprsize PeanoNat.Nat.lt_wf_0)).
intros.
destruct e1; simpl; try rewrite <- H0; try reflexivity.
(* Only eadd is left now *)
rewrite (List.app_assoc_reverse (rpn e1_1) (rpn e1_2) rest).
assert (Some (eval env e1_1 :: eval env e1_2 :: results)%list
= rpn_eval' env (app (rpn e1_1) (app (rpn e1_2) rest))).
apply H. apply exprsize_left.
apply H. apply exprsize_right.
assumption.
rewrite <- H1.
reflexivity.
Qed.
Lemma correctness e env : Some (eval env e) = rpn_eval env (rpn e).
Proof.
assert (Some (eval env e :: nil)%list = rpn_eval' env (rpn e)).
assert (app (rpn e) nil = rpn e).
apply List.app_nil_r.
rewrite <- H.
apply free_append'.
simpl. reflexivity.
unfold rpn_eval.
rewrite <- H.
reflexivity.
Qed.
|