| Some example programs and proofs of their correctness |
Require Import List.
Require Import Binding.
Require Import PSLC.
Require Import MemMonad.
Require Import Imp.
Set Implicit Arguments.
Source language |
| A specialization of the denotation function to closed terms |
Definition meaning (t : ty) (e : term nil t) : tyDenote t :=
termDenote e (SNil _).
Definition snd : term nil (Arrow (Data Nat) (Arrow (Data Nat) (Data Nat))) :=
Lam (Lam (EVar (First _ _))).
Theorem snd_ok : forall n1 n2,
meaning (App (App snd (Const _ n1)) (Const _ n2))
= meaning (Const _ n2).
trivial.
Qed.
| That was easy! This theorem is actually proved by reflexivity with a single proof constructor, since Coq identifies terms up to computational reduction. |
Definition dup : term nil (Arrow (Data Nat) (Data (Prod Nat Nat))) :=
Lam (Pair (EVar (First _ _)) (EVar (First _ _))).
Theorem dup_ok : forall n,
meaning (Fst (App dup (Const _ n)))
= meaning (Const _ n).
trivial.
Qed.
| Another trivial one. |
Definition JM_case : term nil (Arrow (Data (Sum Nat Nat)) (Data Nat)) :=
Lam (Case (EVar (First _ _))
(Const _ 42)
(Const _ 42)).
Theorem JM_case_ok : forall (e : term nil (Data (Sum Nat Nat))),
meaning (App JM_case e)
= meaning (Const _ 42).
unfold meaning; simplify;
destruct (termDenote e (SNil _)); trivial.
Qed.
This one was a little more work, but not much.
Definitional equality wasn't strong enough to prove the goal, but asking
explicitly for a case analysis over the denotation of the argument e was
enough.
|
Target language |
Definition imeaning (t : ity) (e : iterm nil t) : ityDenote t :=
itermDenote e (SNil _).
Our generic strategy for proving term correctness:
Expand the definition of our specialized denotation function for closed terms
and then ask the MemMonad library to work its magic.
|
Ltac simp := unfold imeaning; memM_simplify.
Definition read_back : iterm nil (IArrow (IData INat) (IData INat)) :=
ILam (ISeq
(IWrite (IConst _ O) (IVar (First _ _)))
(IRead (IConst _ O))).
Theorem read_back_ok : forall m n,
mspec (fun _ n' => n' = n) (imeaning (IApp read_back (IConst _ n))) m.
simp.
Qed.
Here, the actual proof term generated (you can see it with ) is long and scary, but the memM_simplify tactic does the
work for us.
|
Definition scribbler : iterm nil (IArrow (IData INat) (IData INat)) :=
ILam (ISeq
(IWrite (IVar (First _ _)) (IConst _ 0))
(ISeq
(IWrite (ISucc (IVar (First _ _))) (IConst _ 1))
(IRead (IVar (First _ _))))).
Theorem scribbler_ok : forall m a,
mspec (fun _ n => n = O) (imeaning (IApp scribbler (IConst _ a))) m.
simp.
Qed.
Another victory for memM_simplify
|