summaryrefslogtreecommitdiff
path: root/expr.v
blob: 541b910ab13baa7f76d55c091cbf0809285dd879 (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
96
97
98
99
100
101
Inductive Exp (v : Type) :=
  | elit : nat -> Exp v
  | evar : v   -> Exp v
  | eadd : Exp v -> Exp v -> Exp v.

Fixpoint eval {v} (env : v -> nat) (e : Exp v) : nat :=
  match e with
  | elit _ n   => n
  | evar _ n   => env n
  | eadd _ a b => eval env a + eval env b
  end.

Inductive RPN (v : Type) : nat -> Type :=
  | rpnnil : RPN v 0
  | rpnlit : forall {n}, RPN v n -> nat  -> RPN v (S n)
  | rpnvar : forall {n}, RPN v n -> v    -> RPN v (S n)
  | rpnadd : forall {n}, RPN v (S (S n)) -> RPN v (S n).

Fixpoint rpn_app {v} {n} {m} (a : RPN v n) (b : RPN v m) : RPN v (n+m) :=
  match a with
  | rpnnil _           => b
  | rpnlit _ rest x => rpnlit _ (rpn_app rest b) x
  | rpnvar _ rest x => rpnvar _ (rpn_app rest b) x
  | rpnadd _ rest   => rpnadd _ (rpn_app rest b)
  end.

Definition cast: forall {A m} (v: RPN A m) {n}, m = n -> RPN A n.
intros.
rewrite <- H.
exact v.
Defined.

Require Import Coq.Arith.Plus.
Require Import Coq.Program.Equality.
Lemma rpn_app_assoc_jmeq {v} {p} {q} {r} (a : RPN v p) (b : RPN v q) (c : RPN v r) :
  rpn_app a (rpn_app b c) ~= rpn_app (rpn_app a b) c.
induction a.
simpl.
reflexivity.
simpl.
Admitted.

Lemma rpn_app_assoc {v} {p} {q} {r} (a : RPN v p) (b : RPN v q) (c : RPN v r) :
  rpn_app (rpn_app a b) c = cast (rpn_app a (rpn_app b c)) (plus_assoc _ _ _).


Fixpoint rpn {v} (e : Exp v) : RPN v 1 :=
  match e with
  | elit _ n   => rpnlit _ (rpnnil _) n
  | evar _ n   => rpnvar _ (rpnnil _) n
  | eadd _ a b => rpnadd _ (rpn_app (rpn a) (rpn b))
  end.

Require Import Coq.Vectors.VectorDef.
Fixpoint rpn_eval' {v} {n} (env : v -> nat) (rpn : RPN v n) : t nat n.
refine (match rpn with
  | rpnnil _           => nil _
  | rpnlit _ rest x  => cons _ x       _ (rpn_eval' _ _ env rest)
  | rpnvar _ rest x  => cons _ (env x) _ (rpn_eval' _ _ env rest)
  | rpnadd _ rest => _
  end).
set (recurse := rpn_eval' _ _ env rest).
remember (S (S n0)) as stack_size.
destruct recurse.
discriminate. (* nil case *)
assert (n1 = S n0) by (abstract congruence).
rewrite H in recurse.
exact recurse.
Defined.

Definition rpn_eval {v} (env : v -> nat) (rpn : RPN v 1) : nat :=
  match rpn_eval' env rpn with
  | cons _ x _ _ => x
  | nil _ => 0
  end.

Fixpoint exprsize {v} (e : Exp v) : nat :=
  match e with
  | elit _ _ => 1
  | evar _ _ => 1
  | eadd _ a b => 1 + exprsize a + exprsize b
  end.

Require Import Wellfounded.
Theorem correctness (v : Type) (e : Exp v) : forall env : v -> nat,
  forall n rest (results : t nat n),
  results = rpn_eval' env rest ->
  cons _ (eval env e) _ results = rpn_eval' env (rpn_app (rpn e) rest).
Proof.
induction e using (well_founded_induction
  (wf_inverse_image _ nat _ exprsize PeanoNat.Nat.lt_wf_0)).
intros.
destruct e.
simpl; try rewrite <- H0; try reflexivity.
simpl; try rewrite <- H0; try reflexivity.
simpl (rpn (eadd v e1 e2)).
simpl rpn_app.
assert (rpn_app (rpn_app (rpn e1) (rpn e2)) rest = rpn_app (rpn e1) (rpn_app (rpn e2) rest)).
  apply rpn_app_assoc.
rewrite (app_assoc_reverse (rev (rpn v e1)) (rev (rpn v e2)) rest).
Qed.