314 lines
9.5 KiB
Coq
314 lines
9.5 KiB
Coq
|
Require Import List.
|
||
|
Require Import MyList.
|
||
|
Require Import MyTactics.
|
||
|
Require Import Sequences.
|
||
|
Require Import MetalSyntax.
|
||
|
Require Import Autosubst_Env.
|
||
|
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
|
||
|
(* A big-step call-by-value semantics with explicit environments. *)
|
||
|
|
||
|
(* Because every lambda-abstraction is closed, no closures are involved:
|
||
|
a lambda-abstraction evaluates to itself. Thus, an mvalue [mv] must be
|
||
|
either a (closed) lambda-abstraction or a pair of mvalues. *)
|
||
|
|
||
|
Inductive mvalue :=
|
||
|
| MVLam : {bind metal} -> mvalue
|
||
|
| MVPair : mvalue -> mvalue -> mvalue.
|
||
|
|
||
|
Definition dummy_mvalue : mvalue :=
|
||
|
MVLam (MVar 0).
|
||
|
|
||
|
(* An environment [e] is a list of mvalues. *)
|
||
|
|
||
|
Definition menv :=
|
||
|
list mvalue.
|
||
|
|
||
|
(* The judgement [mbigcbv e t mv] means that, under the environment [e], the
|
||
|
term [t] evaluates to [mv]. *)
|
||
|
|
||
|
Inductive mbigcbv : menv -> metal -> mvalue -> Prop :=
|
||
|
| MBigcbvVar:
|
||
|
forall e x mv,
|
||
|
(* The variable [x] must be in the domain of [e]. *)
|
||
|
x < length e ->
|
||
|
(* This allows us to safely look up [e] at [x]. *)
|
||
|
mv = nth x e dummy_mvalue ->
|
||
|
mbigcbv e (MVar x) mv
|
||
|
| MBigcbvLam:
|
||
|
forall e t,
|
||
|
(* The lambda-abstraction must have no free variables. *)
|
||
|
closed (MLam t) ->
|
||
|
mbigcbv e (MLam t) (MVLam t)
|
||
|
| MBigcbvApp:
|
||
|
forall e t1 t2 u1 mv2 mv,
|
||
|
(* Evaluate [t1] to a lambda-abstraction, *)
|
||
|
mbigcbv e t1 (MVLam u1) ->
|
||
|
(* evaluate [t2] to a value, *)
|
||
|
mbigcbv e t2 mv2 ->
|
||
|
(* and evaluate the function body in a singleton environment. *)
|
||
|
mbigcbv (mv2 :: nil) u1 mv ->
|
||
|
mbigcbv e (MApp t1 t2) mv
|
||
|
| MBigcbvLet:
|
||
|
forall e t1 t2 mv1 mv,
|
||
|
(* Evaluate [t1] to a value, *)
|
||
|
mbigcbv e t1 mv1 ->
|
||
|
(* and evaluate [t2] under a suitable environment. *)
|
||
|
mbigcbv (mv1 :: e) t2 mv ->
|
||
|
mbigcbv e (MLet t1 t2) mv
|
||
|
| MBigcbvPair:
|
||
|
forall e t1 t2 mv1 mv2,
|
||
|
(* Evaluate each component to a value, *)
|
||
|
mbigcbv e t1 mv1 ->
|
||
|
mbigcbv e t2 mv2 ->
|
||
|
(* and construct a pair. *)
|
||
|
mbigcbv e (MPair t1 t2) (MVPair mv1 mv2)
|
||
|
| MBigcbvPi:
|
||
|
forall e i t mv1 mv2 mv,
|
||
|
(* Evaluate [t] to a pair value, *)
|
||
|
mbigcbv e t (MVPair mv1 mv2) ->
|
||
|
(* and project out the desired component. *)
|
||
|
mv = match i with 0 => mv1 | _ => mv2 end ->
|
||
|
mbigcbv e (MPi i t) mv
|
||
|
.
|
||
|
|
||
|
Hint Constructors mbigcbv : mbigcbv.
|
||
|
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
|
||
|
(* A reformulation of the evaluation rule for variables. *)
|
||
|
|
||
|
Lemma MBigcbvVarExact:
|
||
|
forall e1 mv e2 x,
|
||
|
x = length e1 ->
|
||
|
mbigcbv (e1 ++ mv :: e2) (MVar x) mv.
|
||
|
Proof.
|
||
|
intros. econstructor.
|
||
|
{ length. }
|
||
|
{ rewrite app_nth by eauto. reflexivity. }
|
||
|
Qed.
|
||
|
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
|
||
|
(* We now examine how the big-step semantics interacts with renamings.
|
||
|
We prove that if (roughly) the equation [e = xi >>> e'] holds then
|
||
|
evaluating [t.[xi]] under [e'] is the same as evaluating [t] under
|
||
|
[e]. *)
|
||
|
|
||
|
Lemma mbigcbv_ren:
|
||
|
forall e t mv,
|
||
|
mbigcbv e t mv ->
|
||
|
forall e' xi,
|
||
|
env_ren_comp e xi e' ->
|
||
|
mbigcbv e' t.[ren xi] mv.
|
||
|
Proof.
|
||
|
induction 1; intros;
|
||
|
try solve [ asimpl; eauto with env_ren_comp mbigcbv ].
|
||
|
(* MVar *)
|
||
|
{ pick @env_ren_comp invert.
|
||
|
econstructor; eauto. }
|
||
|
(* MLam *)
|
||
|
{ rewrite closed_unaffected by eauto.
|
||
|
eauto with mbigcbv. }
|
||
|
Qed.
|
||
|
|
||
|
(* As a special case, evaluating [eos x t] under an environment of the form
|
||
|
[e1 ++ mv :: e2], where length of [e1] is [x] (so [x] is mapped to [mv])
|
||
|
is the same as evaluating [t] under [e1 ++ e2]. The operational effect
|
||
|
of the end-of-scope mark [eos x _] is to delete the value stored at index
|
||
|
[x] in the evaluation environment. *)
|
||
|
|
||
|
Lemma mbigcbv_eos:
|
||
|
forall e1 e2 x t mv mw,
|
||
|
mbigcbv (e1 ++ e2) t mw ->
|
||
|
x = length e1 ->
|
||
|
mbigcbv (e1 ++ mv :: e2) (eos x t) mw.
|
||
|
Proof.
|
||
|
intros. eapply mbigcbv_ren; eauto with env_ren_comp.
|
||
|
Qed.
|
||
|
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
|
||
|
(* Evaluation rules for (simulated) tuples. *)
|
||
|
|
||
|
Fixpoint MVTuple mvs :=
|
||
|
match mvs with
|
||
|
| nil =>
|
||
|
MVLam (MVar 0)
|
||
|
| mv :: mvs =>
|
||
|
MVPair mv (MVTuple mvs)
|
||
|
end.
|
||
|
|
||
|
Lemma MBigcbvTuple:
|
||
|
forall e ts mvs,
|
||
|
(* Evaluate every component to a value, *)
|
||
|
Forall2 (mbigcbv e) ts mvs ->
|
||
|
(* and construct a tuple. *)
|
||
|
mbigcbv e (MTuple ts) (MVTuple mvs).
|
||
|
Proof.
|
||
|
induction 1; simpl; econstructor; eauto.
|
||
|
{ unfold closed. fv. }
|
||
|
Qed.
|
||
|
|
||
|
Lemma MBigcbvProj:
|
||
|
forall i e t mvs mv,
|
||
|
i < length mvs ->
|
||
|
(* Evaluate [t] to a tuple value, *)
|
||
|
mbigcbv e t (MVTuple mvs) ->
|
||
|
(* and project out the desired component. *)
|
||
|
mv = nth i mvs dummy_mvalue ->
|
||
|
mbigcbv e (MProj i t) mv.
|
||
|
Proof.
|
||
|
(* By induction on [i]. In either case, [mvs] cannot be an empty list. *)
|
||
|
induction i; intros; (destruct mvs as [| mv0 mvs ]; [ false; simpl in *; omega |]).
|
||
|
(* Base case. *)
|
||
|
{ econstructor; eauto. }
|
||
|
(* Step case. *)
|
||
|
{ assert (i < length mvs). { length. }
|
||
|
simpl. eauto with mbigcbv. }
|
||
|
Qed.
|
||
|
|
||
|
Lemma MBigcbvLetPair:
|
||
|
forall e t u mv mv1 mv2,
|
||
|
mbigcbv e t (MVPair mv1 mv2) ->
|
||
|
mbigcbv (mv2 :: mv1 :: e) u mv ->
|
||
|
mbigcbv e (MLetPair t u) mv.
|
||
|
Proof.
|
||
|
unfold MLetPair. eauto 6 using mbigcbv_ren, env_ren_comp_plus1 with mbigcbv.
|
||
|
Qed.
|
||
|
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
|
||
|
(* Evaluation rules for [MMultiLet]. *)
|
||
|
|
||
|
Local Lemma Forall2_mbigcbv_plus1:
|
||
|
forall ts mvs e i mv,
|
||
|
Forall2 (mbigcbv e) (map (fun t : metal => lift i t) ts) mvs ->
|
||
|
Forall2 (mbigcbv (mv :: e)) (map (fun t : metal => lift (i + 1) t) ts) mvs.
|
||
|
Proof.
|
||
|
induction ts as [| t ts]; simpl; intros;
|
||
|
pick Forall2 invert; econstructor; eauto.
|
||
|
replace (lift (i + 1) t) with (lift 1 (lift i t)) by autosubst.
|
||
|
eauto using mbigcbv_ren, env_ren_comp_plus1.
|
||
|
Qed.
|
||
|
|
||
|
Lemma MBigcbvMultiLet:
|
||
|
forall ts e i u mvs mv,
|
||
|
Forall2 (mbigcbv e) (map (fun t => lift i t) ts) mvs ->
|
||
|
mbigcbv (rev mvs ++ e) u mv ->
|
||
|
mbigcbv e (MMultiLet i ts u) mv.
|
||
|
Proof.
|
||
|
induction ts; simpl; intros; pick Forall2 invert.
|
||
|
{ eauto. }
|
||
|
{ pick mbigcbv ltac:(fun h => rewrite rev_cons_app in h).
|
||
|
econstructor; eauto using Forall2_mbigcbv_plus1. }
|
||
|
Qed.
|
||
|
|
||
|
Lemma MBigcbvMultiLet_0:
|
||
|
forall ts e u mvs mv,
|
||
|
Forall2 (mbigcbv e) ts mvs ->
|
||
|
mbigcbv (rev mvs ++ e) u mv ->
|
||
|
mbigcbv e (MMultiLet 0 ts u) mv.
|
||
|
Proof.
|
||
|
intros. eapply MBigcbvMultiLet.
|
||
|
{ asimpl. rewrite map_id. eauto. }
|
||
|
{ eauto. }
|
||
|
Qed.
|
||
|
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
|
||
|
(* An evaluation rule for [MVars]. *)
|
||
|
|
||
|
Lemma MBigcbvVars_preliminary:
|
||
|
forall e2 e1 e x n,
|
||
|
e = e1 ++ e2 ->
|
||
|
x = length e1 ->
|
||
|
n = length e2 ->
|
||
|
Forall2 (mbigcbv e) (map MVar (seq x n)) e2.
|
||
|
Proof.
|
||
|
induction e2 as [| mv e2 ]; intros; subst; econstructor.
|
||
|
{ eauto using MBigcbvVarExact. }
|
||
|
{ eapply IHe2 with (e1 := e1 ++ mv :: nil).
|
||
|
{ rewrite <- app_assoc. reflexivity. }
|
||
|
{ length. }
|
||
|
{ eauto. }
|
||
|
}
|
||
|
Qed.
|
||
|
|
||
|
Lemma MBigcbvVars:
|
||
|
forall e,
|
||
|
Forall2 (mbigcbv e) (MVars (length e)) e.
|
||
|
Proof.
|
||
|
unfold MVars, nats. intros.
|
||
|
eapply MBigcbvVars_preliminary with (e1 := nil); eauto.
|
||
|
Qed.
|
||
|
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
|
||
|
(* An evaluation rule for [MProjs]. If the term [t] evaluates to a tuple whose
|
||
|
components numbered 1, ..., n are collected in the list [mvs1], then the
|
||
|
family of terms [MProjs n t] evaluates to the family of values [rev mvs1]. *)
|
||
|
|
||
|
Lemma MBigcbvProjs:
|
||
|
forall n e t mv mvs1 mvs2,
|
||
|
mbigcbv e t (MVTuple (mv :: mvs1 ++ mvs2)) ->
|
||
|
length mvs1 = n ->
|
||
|
Forall2 (mbigcbv e) (MProjs n t) (rev mvs1).
|
||
|
Proof.
|
||
|
(* This result is "obvious" but requires some low-level work. *)
|
||
|
unfold MProjs. induction n; intros.
|
||
|
(* Case: [n] is zero. Then, [mvs1] must be [nil]. The result follows. *)
|
||
|
{ destruct mvs1; [| false; simpl in *; omega ].
|
||
|
econstructor. }
|
||
|
(* Case: [n] is nonzero. Then, the list [mvs1] must be nonempty. *)
|
||
|
assert (hmvs1: mvs1 <> nil).
|
||
|
{ intro. subst. simpl in *. omega. }
|
||
|
(* So, this list has one element at the end. Let us write this list in the
|
||
|
form [mvs1 ++ mv1]. *)
|
||
|
destruct (exists_last hmvs1) as (hd&mv1&?). subst mvs1. clear hmvs1.
|
||
|
generalize dependent hd; intro mvs1; intros.
|
||
|
(* Simplify. *)
|
||
|
rewrite rev_unit.
|
||
|
rewrite <- app_assoc in *.
|
||
|
rewrite app_length in *.
|
||
|
assert (length mvs1 = n). { length. }
|
||
|
simpl map.
|
||
|
econstructor.
|
||
|
(* The list heads. *)
|
||
|
{ eapply MBigcbvProj; eauto.
|
||
|
{ length. }
|
||
|
{ replace (n + 1) with (S n) by omega. simpl.
|
||
|
rewrite app_nth by omega.
|
||
|
reflexivity. }
|
||
|
}
|
||
|
(* The list tails. *)
|
||
|
{ eauto. }
|
||
|
Qed.
|
||
|
|
||
|
(* -------------------------------------------------------------------------- *)
|
||
|
|
||
|
(* An evaluation rule for the combination of [MMultiLet] and [MProjs]. If the
|
||
|
term [t] evaluates to a tuple whose components are [mv :: mvs], and if [n]
|
||
|
is the length of [mvs], then evaluating [MMultiLet 0 (MProjs n t) u] in an
|
||
|
environment [e] leads to evaluating [u] in environment [mvs ++ e]. *)
|
||
|
|
||
|
Lemma MBigcbvMultiLetProjs:
|
||
|
forall e t mvs u mv mw n,
|
||
|
mbigcbv e t (MVTuple (mv :: mvs)) ->
|
||
|
length mvs = n ->
|
||
|
mbigcbv (mvs ++ e) u mw ->
|
||
|
mbigcbv e (MMultiLet 0 (MProjs n t) u) mw.
|
||
|
Proof.
|
||
|
intros.
|
||
|
eapply MBigcbvMultiLet_0.
|
||
|
{ eapply MBigcbvProjs with (mvs2 := nil); [ rewrite app_nil_r |]; eauto. }
|
||
|
{ rewrite rev_involutive. eauto. }
|
||
|
Qed.
|