679 lines
18 KiB
Coq
679 lines
18 KiB
Coq
Require Import Sequences.
|
|
Require Import Relations.
|
|
Require Import LambdaCalculusSyntax.
|
|
Require Import LambdaCalculusValues.
|
|
Require Import LambdaCalculusReduction.
|
|
Require Import LambdaCalculusParallelReduction.
|
|
Require Import MyTactics.
|
|
|
|
(* This is an adaptation of the paper "A Simple Proof of Call-by-Value
|
|
Standardization", by Karl Crary (2009). We establish two main results:
|
|
|
|
First, parallel call-by-value reduction is adequate, i.e., is contained in
|
|
contextual equivalence: if [t1] parallel-reduces to [t2], then [t1] halts
|
|
if and only if [t2] halts (where halting is considered with respect to
|
|
ordinary call-by-value reduction, [cbv]).
|
|
|
|
Second, every call-by-value reduction sequence can be put in a standard
|
|
form, as defined by the predicate [stdred]. *)
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* "Evaluation" in Crary's paper is [cbv] here. Parallel reduction in Crary's
|
|
paper is [pcbv] here. Internal parallel reduction, [ipcbv], is defined as
|
|
follows. It is a restricted version of parallel reduction: it is allowed to
|
|
act only under lambda, in the right-hand side of an application whose
|
|
left-hand side is not a value, and in the right-hand side of [Let]. *)
|
|
|
|
Inductive ipcbv : term -> term -> Prop :=
|
|
| IRedVar:
|
|
forall x,
|
|
ipcbv (Var x) (Var x)
|
|
| IRedLam:
|
|
forall t1 t2,
|
|
pcbv t1 t2 ->
|
|
ipcbv (Lam t1) (Lam t2)
|
|
| IRedAppLRNonValue:
|
|
forall t1 t2 u1 u2,
|
|
~ is_value t1 ->
|
|
ipcbv t1 t2 ->
|
|
pcbv u1 u2 ->
|
|
ipcbv (App t1 u1) (App t2 u2)
|
|
| IRedAppLR:
|
|
forall t1 t2 u1 u2,
|
|
is_value t1 -> (* wlog; see [ipcbv_IRedAppLR] below *)
|
|
ipcbv t1 t2 ->
|
|
ipcbv u1 u2 ->
|
|
ipcbv (App t1 u1) (App t2 u2)
|
|
| IRedLetLR:
|
|
forall t1 t2 u1 u2,
|
|
ipcbv t1 t2 ->
|
|
pcbv u1 u2 ->
|
|
ipcbv (Let t1 u1) (Let t2 u2)
|
|
.
|
|
|
|
Local Hint Constructors ipcbv : red obvious.
|
|
|
|
(* [ipcbv] is a subset of [pcbv]. *)
|
|
|
|
Lemma ipcbv_subset_pcbv:
|
|
forall t1 t2,
|
|
ipcbv t1 t2 ->
|
|
pcbv t1 t2.
|
|
Proof.
|
|
induction 1; obvious.
|
|
Qed.
|
|
|
|
Local Hint Resolve ipcbv_subset_pcbv : red obvious.
|
|
|
|
(* The side condition [is_value t1] in [IRedAppLR] does not cause any loss
|
|
of expressiveness, as the previous rule covers the case where [t1] is
|
|
not a value. *)
|
|
|
|
Lemma ipcbv_IRedAppLR:
|
|
forall t1 t2 u1 u2,
|
|
ipcbv t1 t2 ->
|
|
ipcbv u1 u2 ->
|
|
ipcbv (App t1 u1) (App t2 u2).
|
|
Proof.
|
|
intros. value_or_nonvalue t1; obvious.
|
|
Qed.
|
|
|
|
Local Hint Resolve ipcbv_IRedAppLR : red obvious.
|
|
|
|
(* [ipcbv] is reflexive. *)
|
|
|
|
Lemma ipcbv_refl:
|
|
forall t,
|
|
ipcbv t t.
|
|
Proof.
|
|
induction t; eauto using red_refl with obvious.
|
|
Qed.
|
|
|
|
Local Hint Resolve ipcbv_refl.
|
|
|
|
(* [ipcbv] preserves values, both ways. *)
|
|
|
|
Lemma ipcbv_preserves_values:
|
|
forall v1 v2, ipcbv v1 v2 -> is_value v1 -> is_value v2.
|
|
Proof.
|
|
induction 1; is_value.
|
|
Qed.
|
|
|
|
Lemma ipcbv_preserves_values_reversed:
|
|
forall v1 v2, ipcbv v1 v2 -> is_value v2 -> is_value v1.
|
|
Proof.
|
|
induction 1; is_value.
|
|
Qed.
|
|
|
|
Lemma ipcbv_preserves_values_reversed_contrapositive:
|
|
forall v1 v2, ipcbv v1 v2 -> ~ is_value v1 -> ~ is_value v2.
|
|
Proof.
|
|
induction 1; is_value.
|
|
Qed.
|
|
|
|
Local Hint Resolve ipcbv_preserves_values ipcbv_preserves_values_reversed
|
|
ipcbv_preserves_values_reversed_contrapositive.
|
|
|
|
Lemma star_ipcbv_preserves_values_reversed:
|
|
forall v1 v2, star ipcbv v1 v2 -> is_value v2 -> is_value v1.
|
|
Proof.
|
|
induction 1; eauto.
|
|
Qed.
|
|
|
|
Local Hint Resolve star_ipcbv_preserves_values_reversed.
|
|
|
|
(* Reverse internal parallel reduction preserves the property of being stuck
|
|
and (therefore) the property of being irreducible. *)
|
|
|
|
Lemma reverse_ipcbv_preserves_stuck:
|
|
forall t1 t2,
|
|
ipcbv t1 t2 ->
|
|
stuck t2 ->
|
|
stuck t1.
|
|
Proof.
|
|
induction 1; inversion 1; subst; eauto with stuck.
|
|
{ false. obvious. }
|
|
{ false. obvious. }
|
|
{ eapply StuckApp; eauto.
|
|
do 2 intro; subst. inv ipcbv. congruence. }
|
|
Qed.
|
|
|
|
Lemma reverse_star_ipcbv_preserves_stuck:
|
|
forall t1 t2,
|
|
star ipcbv t1 t2 ->
|
|
stuck t2 ->
|
|
stuck t1.
|
|
Proof.
|
|
induction 1; eauto using reverse_ipcbv_preserves_stuck.
|
|
Qed.
|
|
|
|
Lemma reverse_ipcbv_preserves_irred:
|
|
forall t1 t2,
|
|
ipcbv t1 t2 ->
|
|
irred cbv t2 ->
|
|
irred cbv t1.
|
|
Proof.
|
|
do 3 intro. rewrite !irred_cbv_characterization.
|
|
intuition eauto 2 using reverse_ipcbv_preserves_stuck.
|
|
Qed.
|
|
|
|
Local Hint Resolve
|
|
pcbv_preserves_irred
|
|
reverse_ipcbv_preserves_irred
|
|
(star_implication (irred cbv))
|
|
(star_implication_reversed (irred cbv))
|
|
: irred.
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Strong parallel reduction requires both (1) parallel reduction; and (2) a
|
|
decomposition as an ordinary call-by-value reduction sequence, followed
|
|
with an internal parallel reduction step. Our goal is to prove that strong
|
|
parallel reduction in fact coincides with parallel reduction, which means
|
|
that this decomposition always exists. *)
|
|
|
|
Inductive spcbv : term -> term -> Prop :=
|
|
| SPCbv:
|
|
forall t1 u t2,
|
|
pcbv t1 t2 ->
|
|
star cbv t1 u ->
|
|
ipcbv u t2 ->
|
|
spcbv t1 t2.
|
|
|
|
Local Hint Constructors spcbv.
|
|
|
|
(* By definition, [spcbv] is a subset of [pcbv]. *)
|
|
|
|
Lemma spcbv_subset_pcbv:
|
|
forall t1 t2,
|
|
spcbv t1 t2 ->
|
|
pcbv t1 t2.
|
|
Proof.
|
|
inversion 1; eauto.
|
|
Qed.
|
|
|
|
Local Hint Resolve spcbv_subset_pcbv.
|
|
|
|
(* [spcbv] is reflexive. *)
|
|
|
|
Lemma spcbv_refl:
|
|
forall t,
|
|
spcbv t t.
|
|
Proof.
|
|
econstructor; eauto using red_refl with sequences obvious.
|
|
Qed.
|
|
|
|
Local Hint Resolve spcbv_refl.
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* The main series of technical lemmas begins here. *)
|
|
|
|
Lemma crarys_lemma2:
|
|
forall t1 t2 u1 u2,
|
|
spcbv t1 t2 ->
|
|
pcbv u1 u2 ->
|
|
~ is_value t2 ->
|
|
spcbv (App t1 u1) (App t2 u2).
|
|
Proof.
|
|
inversion 1; intros; subst. econstructor; obvious.
|
|
Qed.
|
|
|
|
Lemma crarys_lemma3_App:
|
|
forall t1 t2 u1 u2,
|
|
spcbv t1 t2 ->
|
|
spcbv u1 u2 ->
|
|
spcbv (App t1 u1) (App t2 u2).
|
|
Proof.
|
|
inversion 1; inversion 1; intros; subst.
|
|
value_or_nonvalue t2.
|
|
{ eauto 6 with obvious. }
|
|
{ eauto using crarys_lemma2. }
|
|
Qed.
|
|
|
|
Lemma crarys_lemma3_Let:
|
|
forall t1 t2 u1 u2,
|
|
spcbv t1 t2 ->
|
|
pcbv u1 u2 ->
|
|
spcbv (Let t1 u1) (Let t2 u2).
|
|
Proof.
|
|
inversion 1; intros; subst; obvious.
|
|
Qed.
|
|
|
|
Lemma crarys_lemma4:
|
|
forall {u1 u2},
|
|
spcbv u1 u2 ->
|
|
is_value u1 ->
|
|
forall {t1 t2},
|
|
ipcbv t1 t2 ->
|
|
spcbv t1.[u1/] t2.[u2/].
|
|
Proof.
|
|
induction 3; intros.
|
|
(* Var. *)
|
|
{ destruct x as [|x]; asimpl; eauto. }
|
|
(* Lam *)
|
|
{ rewrite !subst_lam. inv spcbv.
|
|
econstructor; eauto 11 with sequences obvious. (* slow *) }
|
|
(* App (nonvalue) *)
|
|
{ asimpl. eapply crarys_lemma2; obvious. eauto 9 with obvious. }
|
|
(* App *)
|
|
{ asimpl. eapply crarys_lemma3_App; obvious. }
|
|
(* Let *)
|
|
{ rewrite !subst_let.
|
|
eapply crarys_lemma3_Let; eauto 12 with obvious. }
|
|
Qed.
|
|
|
|
Lemma crarys_lemma5:
|
|
forall {t1 t2 u1 u2},
|
|
spcbv t1 t2 ->
|
|
spcbv u1 u2 ->
|
|
is_value u1 ->
|
|
spcbv t1.[u1/] t2.[u2/].
|
|
Proof.
|
|
intros _ _ u1 u2 [ t1 t t2 Hpcbvt Hstarcbv Hipcbv ] Hpcbvu Hvalue.
|
|
generalize (crarys_lemma4 Hpcbvu Hvalue Hipcbv).
|
|
inversion 1; subst.
|
|
econstructor; [| | obvious ].
|
|
{ eauto 11 with obvious. }
|
|
{ eauto using star_red_subst with sequences obvious. }
|
|
Qed.
|
|
|
|
Lemma crarys_lemma6:
|
|
forall {t1 t2},
|
|
pcbv t1 t2 ->
|
|
spcbv t1 t2.
|
|
Proof.
|
|
induction 1; try solve [ tauto ]; subst.
|
|
(* RedParBetaV *)
|
|
{ match goal with hv: is_value _ |- _ =>
|
|
generalize (crarys_lemma5 IHred1 IHred2 hv)
|
|
end.
|
|
inversion 1; subst.
|
|
econstructor; obvious.
|
|
eauto with sequences obvious. }
|
|
(* RedParLetV *)
|
|
{ match goal with hv: is_value _ |- _ =>
|
|
generalize (crarys_lemma5 IHred1 IHred2 hv)
|
|
end.
|
|
inversion 1; subst.
|
|
econstructor; obvious.
|
|
eauto with sequences obvious. }
|
|
(* RedVar *)
|
|
{ obvious. }
|
|
(* RedLam *)
|
|
{ clear IHred. eauto with sequences obvious. }
|
|
(* RedAppLR *)
|
|
{ eauto using crarys_lemma3_App. }
|
|
(* RedLetLR *)
|
|
{ eauto using crarys_lemma3_Let. }
|
|
Qed.
|
|
|
|
(* A reformulation of Lemma 6. We can now forget about [spcbv]. *)
|
|
|
|
Lemma crarys_main_lemma:
|
|
forall t1 t2,
|
|
pcbv t1 t2 ->
|
|
exists t, star cbv t1 t /\ ipcbv t t2.
|
|
Proof.
|
|
intros ? ? H.
|
|
generalize (crarys_lemma6 H); inversion 1; subst.
|
|
eauto.
|
|
Qed.
|
|
|
|
Lemma crarys_main_lemma_plus:
|
|
commutation22
|
|
cbv pcbv
|
|
(plus cbv) ipcbv.
|
|
Proof.
|
|
unfold commutation22. intros ? ? Hstarcbv ? Hpcbv.
|
|
forward1 crarys_main_lemma.
|
|
eauto with sequences.
|
|
Qed.
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Postponement. *)
|
|
|
|
Lemma crarys_lemma7:
|
|
commutation22
|
|
ipcbv cbv
|
|
cbv pcbv.
|
|
Local Ltac ih7 :=
|
|
match goal with IH: forall u, cbv _ u -> _, h: cbv _ _ |- _ =>
|
|
generalize (IH _ h)
|
|
end; intros (?&?&?).
|
|
Proof.
|
|
unfold commutation22.
|
|
induction 1; intros; subst;
|
|
try solve [ false; eauto 2 with obvious ].
|
|
(* IRedAppLRNonValue *)
|
|
{ invert_cbv. ih7. obvious. }
|
|
(* IRedAppLR *)
|
|
{ (* [t1] and [t2] are values. *)
|
|
clear IHipcbv1.
|
|
invert_cbv.
|
|
(* Case: [u1] and [u2] are values. (Case 5 in Crary's proof.) *)
|
|
{ assert (is_value u1). { obvious. }
|
|
inv ipcbv.
|
|
eexists; split.
|
|
{ eapply RedBetaV; obvious. }
|
|
{ eauto 7 with obvious. }
|
|
}
|
|
(* Case: [u1] and [u2] are nonvalues. (Case 4 in Crary's proof.) *)
|
|
{ ih7. eexists; split; obvious. }
|
|
}
|
|
(* IRedLetLR *)
|
|
{ invert_cbv.
|
|
(* Case: [t1] and [t2] are values. *)
|
|
{ eexists; split; eauto 8 with obvious. }
|
|
(* Case: [t1] and [t2] are nonvalues. *)
|
|
{ ih7. eexists; split; obvious. }
|
|
}
|
|
Qed.
|
|
|
|
(* Internal parallel reduction commutes with reduction, as follows. *)
|
|
|
|
Lemma crarys_lemma8_plus:
|
|
commutation22
|
|
ipcbv cbv
|
|
(plus cbv) ipcbv.
|
|
Proof.
|
|
eauto using crarys_lemma7, crarys_main_lemma_plus,
|
|
commutation22_transitive.
|
|
Qed.
|
|
|
|
Lemma crarys_lemma8:
|
|
commutation22
|
|
ipcbv cbv
|
|
(star cbv) ipcbv.
|
|
Proof.
|
|
eauto using crarys_lemma8_plus, commutation22_variance with sequences.
|
|
Qed.
|
|
|
|
Lemma crarys_lemma8b_plus:
|
|
commutation22
|
|
ipcbv (plus cbv)
|
|
(plus cbv) ipcbv.
|
|
Proof.
|
|
eauto using commute_R_Splus, crarys_lemma8_plus.
|
|
Qed.
|
|
|
|
Lemma crarys_lemma8b:
|
|
commutation22
|
|
ipcbv (star cbv)
|
|
(star cbv) ipcbv.
|
|
Proof.
|
|
eauto using commute_R_Sstar, crarys_lemma8.
|
|
Qed.
|
|
|
|
Lemma crarys_lemma8b_plus_star:
|
|
commutation22
|
|
(star ipcbv) (plus cbv)
|
|
(plus cbv) (star ipcbv).
|
|
Proof.
|
|
eapply commute_Rstar_Splus.
|
|
eauto using crarys_lemma8b_plus, commutation22_variance with sequences.
|
|
Qed.
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Bifurcation. *)
|
|
|
|
(* A sequence of parallel reduction steps can be reformulated as a sequence
|
|
of ordinary reduction steps, followed with a sequence of internal parallel
|
|
reduction steps. *)
|
|
|
|
Lemma crarys_lemma9:
|
|
forall t1 t2,
|
|
star pcbv t1 t2 ->
|
|
exists t,
|
|
star cbv t1 t /\ star ipcbv t t2.
|
|
Proof.
|
|
induction 1.
|
|
{ eauto with sequences. }
|
|
{ unpack.
|
|
forward1 crarys_main_lemma.
|
|
forward2 crarys_lemma8b.
|
|
eauto with sequences. }
|
|
Qed.
|
|
|
|
(* The following result does not seem to explicitly appear in Crary's paper. *)
|
|
|
|
Lemma pcbv_cbv_commutation1:
|
|
commutation22
|
|
(star pcbv) cbv
|
|
(plus cbv) (star pcbv).
|
|
Proof.
|
|
intros t1 t2 ? t3 ?.
|
|
forward1 crarys_lemma9.
|
|
assert (plus cbv t2 t3). { eauto with sequences. }
|
|
forward2 crarys_lemma8b_plus_star.
|
|
eauto 6 using ipcbv_subset_pcbv, star_covariant with sequences.
|
|
Qed.
|
|
|
|
Lemma pcbv_cbv_commutation:
|
|
commutation22
|
|
(star pcbv) (plus cbv)
|
|
(plus cbv) (star pcbv).
|
|
Proof.
|
|
eauto using pcbv_cbv_commutation1, commute_R_Splus.
|
|
Qed.
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* The notion of "reducing (in zero or more steps) to a value" is the same
|
|
under [pcbv] and under [cbv]. *)
|
|
|
|
Lemma equiconvergence:
|
|
forall t v,
|
|
star pcbv t v ->
|
|
is_value v ->
|
|
exists v',
|
|
star cbv t v' /\ is_value v'.
|
|
Proof.
|
|
intros. forward1 crarys_lemma9. eauto.
|
|
Qed.
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* "Adequacy of reduction". In Crary's terminology, "reduction" is the
|
|
compatible closure of "evaluation", and "evaluation" is [cbv]. A
|
|
relation is adequate iff it is contained in contextual equivalence. *)
|
|
|
|
(* The adequacy theorem. (Crary's lemma 10.) *)
|
|
|
|
Theorem pcbv_adequacy:
|
|
forall t1 t2,
|
|
star pcbv t1 t2 ->
|
|
(halts cbv t1) <-> (halts cbv t2).
|
|
Proof.
|
|
split.
|
|
(* Case: [t1] reduces to an irreducible term [u1]. *)
|
|
{ intros (u1&?&?).
|
|
(* [t1] reduces via [pcbv*] to both [u1] and [t2], so they must both
|
|
reduce via [pcbv*] to some common term [u]. *)
|
|
assert (star pcbv t1 u1). { eauto using star_covariant, cbv_subset_pcbv. }
|
|
forward2 diamond_star_pcbv.
|
|
(* The reduction of [t2] to [u] can be bifurcated. That is, [t2] first
|
|
reduces via [cbv*], then via [ipbcv], to [u]. *)
|
|
forward1 crarys_lemma9.
|
|
(* Because [pcbv] and [ipcbv] (reversed) both preserve irreducibility,
|
|
this establishes that [t2] halts. *)
|
|
eexists. split; eauto with irred.
|
|
}
|
|
(* Case: [t2] reduces to an irreducible term [u2]. *)
|
|
{ intros (u2&?&?).
|
|
(* Therefore, [t1] reduces via [pcbv*] to [u2]. *)
|
|
assert (star pcbv t1 u2).
|
|
{ eauto using cbv_subset_pcbv, star_covariant with sequences. }
|
|
(* This reduction can be bifurcated. That is, [t1] first reduces via
|
|
[cbv*], then via [ipcbv], to [u2]. *)
|
|
forward1 crarys_lemma9.
|
|
(* Because [ipcbv] (reversed) preserves irreducibility, this proves
|
|
that [t1] halts. *)
|
|
eexists. split; eauto with irred.
|
|
}
|
|
Qed.
|
|
|
|
(* The previous result implies that [pcbv] and [star pcbv] are contained in
|
|
contextual equivalence. We do not establish this result, because we do
|
|
not need it, and we have not defined contextual equivalence. *)
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Preservation of divergence. *)
|
|
|
|
(* If we have an infinite [cbv] reduction sequence with [pcbv] steps in it,
|
|
then we have an infinite [cbv] reduction sequence. *)
|
|
|
|
Lemma pcbv_preserves_divergence:
|
|
forall t,
|
|
infseq (composition (plus cbv) pcbv) t ->
|
|
infseq cbv t.
|
|
Proof.
|
|
intros ? Hinfseq.
|
|
(* We generalize the statement slightly by allowing any number of initial
|
|
[pcbv] steps from [t] to [u] before finding an infinite reduction sequence
|
|
out of [u]. *)
|
|
eapply infseq_coinduction_principle with (P := fun t =>
|
|
exists u, star pcbv t u /\ infseq (composition (plus cbv) pcbv) u
|
|
); [| eauto with sequences ].
|
|
(* We have to show that, under this hypothesis, we are able to take one step
|
|
of [cbv] out of [t] and reach a term that satisfies this hypothesis again. *)
|
|
clear dependent t. intros t (u&?&hInfSeq).
|
|
pick infseq invert.
|
|
pick @composition invert. unpack.
|
|
(* Out of [t], we have [pcbv* . cbv+ . pcbv ...]. *)
|
|
(* Thus, we have [cbv+ . pcbv* . pcbv ...]. *)
|
|
forward2 pcbv_cbv_commutation.
|
|
(* Thus, we have [cbv . pcbv* ...]. *)
|
|
pick plus invert.
|
|
(* We are happy. *)
|
|
eexists. split; [ eauto |].
|
|
eexists. split; [| eauto ].
|
|
eauto 6 using cbv_subset_pcbv, star_covariant with sequences.
|
|
Qed.
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* The final result in Crary's paper is a standardization theorem for
|
|
call-by-value reduction. The theorem states that any sequence of parallel
|
|
reduction steps can be put in a "standard" form, as defined by the relation
|
|
[stdred] below. *)
|
|
|
|
Inductive stdred : term -> term -> Prop :=
|
|
| StdNil:
|
|
forall t,
|
|
stdred t t
|
|
| StdCons:
|
|
forall t1 t2 t3,
|
|
cbv t1 t2 ->
|
|
stdred t2 t3 ->
|
|
stdred t1 t3
|
|
| StdLam:
|
|
forall t1 t2,
|
|
stdred t1 t2 ->
|
|
stdred (Lam t1) (Lam t2)
|
|
| StdApp:
|
|
forall t1 t2 u1 u2,
|
|
stdred t1 u1 ->
|
|
stdred t2 u2 ->
|
|
stdred (App t1 t2) (App u1 u2)
|
|
| StdLet:
|
|
forall t1 t2 u1 u2,
|
|
stdred t1 u1 ->
|
|
stdred t2 u2 ->
|
|
stdred (Let t1 t2) (Let u1 u2)
|
|
.
|
|
|
|
Hint Constructors stdred : stdred.
|
|
|
|
(* A couple of more flexible constructors for [stdred]. *)
|
|
|
|
Lemma star_cbv_subset_stdred:
|
|
forall t1 t2,
|
|
star cbv t1 t2 ->
|
|
stdred t1 t2.
|
|
Proof.
|
|
induction 1; eauto with stdred.
|
|
Qed.
|
|
|
|
Lemma StdConsStar:
|
|
forall t1 t2 t3,
|
|
star cbv t1 t2 ->
|
|
stdred t2 t3 ->
|
|
stdred t1 t3.
|
|
Proof.
|
|
induction 1; eauto with stdred.
|
|
Qed.
|
|
|
|
Hint Resolve star_cbv_subset_stdred StdConsStar : stdred.
|
|
|
|
(* The following four lemmas analyze a reduction sequence of the form [star
|
|
ipcbv t1 t2], where the head constructor of the term [t2] is known. In
|
|
every case, it can be concluded that the term [t1] exhibits the same head
|
|
constructor. *)
|
|
|
|
Lemma star_ipcbv_into_Var:
|
|
forall {t1 t2}, star ipcbv t1 t2 ->
|
|
forall {x}, t2 = Var x -> t1 = Var x.
|
|
Proof.
|
|
induction 1; intros; subst.
|
|
{ eauto. }
|
|
{ forward (IHstar _ eq_refl). inv ipcbv. eauto. }
|
|
Qed.
|
|
|
|
Lemma star_ipcbv_into_Lam:
|
|
forall {t1 t2}, star ipcbv t1 t2 ->
|
|
forall {u2}, t2 = Lam u2 ->
|
|
exists u1, t1 = Lam u1 /\ star pcbv u1 u2.
|
|
Proof.
|
|
induction 1; intros; subst.
|
|
{ eauto with sequences. }
|
|
{ forward (IHstar _ eq_refl). inv ipcbv. eauto with sequences. }
|
|
Qed.
|
|
|
|
Lemma star_ipcbv_into_App:
|
|
forall {t1 t2}, star ipcbv t1 t2 ->
|
|
forall {t21 t22}, t2 = App t21 t22 ->
|
|
exists t11 t12,
|
|
t1 = App t11 t12 /\ star pcbv t11 t21 /\ star pcbv t12 t22.
|
|
Proof.
|
|
induction 1; intros; subst.
|
|
{ eauto with sequences. }
|
|
{ forward (IHstar _ _ eq_refl). inv ipcbv;
|
|
eauto 9 using ipcbv_subset_pcbv with sequences. }
|
|
Qed.
|
|
|
|
Lemma star_ipcbv_into_Let:
|
|
forall {t1 t2}, star ipcbv t1 t2 ->
|
|
forall {t21 t22}, t2 = Let t21 t22 ->
|
|
exists t11 t12,
|
|
t1 = Let t11 t12 /\ star ipcbv t11 t21 /\ star pcbv t12 t22.
|
|
Proof.
|
|
induction 1; intros; subst.
|
|
{ eauto with sequences. }
|
|
{ forward (IHstar _ _ eq_refl). inv ipcbv. eauto 9 with sequences. }
|
|
Qed.
|
|
|
|
Ltac star_ipcbv_into :=
|
|
pick (star ipcbv) ltac:(fun h => first [
|
|
forward (star_ipcbv_into_Var h eq_refl)
|
|
| forward (star_ipcbv_into_Lam h eq_refl)
|
|
| forward (star_ipcbv_into_App h eq_refl)
|
|
| forward (star_ipcbv_into_Let h eq_refl)
|
|
]).
|
|
|
|
(* The standardization theorem. (Crary's lemma 12.) *)
|
|
|
|
Theorem cbv_standardization:
|
|
forall t2 t1,
|
|
star pcbv t1 t2 ->
|
|
stdred t1 t2.
|
|
Proof.
|
|
induction t2; intros;
|
|
forward1 crarys_lemma9;
|
|
star_ipcbv_into;
|
|
eauto 8 using ipcbv_subset_pcbv, star_covariant with stdred.
|
|
Qed.
|