150 lines
4.3 KiB
Coq
150 lines
4.3 KiB
Coq
|
Require Import MyTactics.
|
||
|
Require Import LambdaCalculusSyntax.
|
||
|
Require Import LambdaCalculusValues.
|
||
|
Require Import CPSDefinition.
|
||
|
Require Import CPSContextSubstitution.
|
||
|
Require Import CPSRenaming.
|
||
|
|
||
|
(* The CPS transformation commutes with certain substitutions. More precisely,
|
||
|
it commutes with a substitution [sigma] of values for variables, up to a
|
||
|
transformation of the values in the codomain of [sigma].
|
||
|
|
||
|
In the case of [cpsv], we have the following diagram: applying [sigma]
|
||
|
first, followed with [cpsv], is the same as applying [cpsv] first, followed
|
||
|
with [sigma >>> cpsv].
|
||
|
|
||
|
cpsv v.[sigma] = (cpsv v).[sigma >>> cpsv]
|
||
|
|
||
|
This can also be written in point-free style, that is, without mentioning
|
||
|
the value [v]:
|
||
|
|
||
|
subst sigma >>> cpsv = cpsv >>> subst (sigma >>> cpsv)
|
||
|
|
||
|
As in the case of the renaming lemma (see CPSRenaming.v), this statement is
|
||
|
proved by induction on the size of terms, together with an analogous
|
||
|
statement about the function [cps]. *)
|
||
|
|
||
|
(* The proof depends on [CPSRenaming] via the lemmas [up_sigma_cpsv] and
|
||
|
[upn_sigma_cpsv], which are declared as hints for [obvious]. *)
|
||
|
|
||
|
Lemma substitution:
|
||
|
(
|
||
|
forall v sigma sigma',
|
||
|
sigma' = sigma >>> cpsv ->
|
||
|
is_value_subst sigma ->
|
||
|
(cpsv v).[sigma'] = cpsv v.[sigma]
|
||
|
) /\ (
|
||
|
forall t c sigma c' sigma',
|
||
|
sigma' = sigma >>> cpsv ->
|
||
|
is_value_subst sigma ->
|
||
|
substc sigma' c = c' ->
|
||
|
(cps t c).[sigma'] = cps t.[sigma] c'
|
||
|
).
|
||
|
Proof.
|
||
|
eapply mutual_induction.
|
||
|
(* [cpsv] *)
|
||
|
{ intros n IHcps v Hvn sigma sigma' Heq Hsigma. subst.
|
||
|
destruct v; asimpl; cpsv; asimpl; try reflexivity.
|
||
|
(* Lam *)
|
||
|
{ erewrite IHcps by obvious. asimpl. reflexivity. }
|
||
|
}
|
||
|
(* [cps] *)
|
||
|
{ intros n IHcpsv IHcps t c Htn sigma c' sigma' Heq Hsigma Hsubstc. subst.
|
||
|
value_or_app_or_let t; asimpl; cps.
|
||
|
(* Case: [t] is a value. *)
|
||
|
{ erewrite apply_substitution by eauto.
|
||
|
erewrite IHcpsv by obvious.
|
||
|
reflexivity. }
|
||
|
(* Case: [t] is an application. *)
|
||
|
{ eapply IHcps; obvious.
|
||
|
simpl. f_equal.
|
||
|
erewrite <- lift_up by tc.
|
||
|
eapply IHcps; obvious.
|
||
|
asimpl. do 2 f_equal.
|
||
|
rewrite lift_reify.
|
||
|
eapply reify_substitution.
|
||
|
rewrite substc_substc.
|
||
|
reflexivity. }
|
||
|
(* Case: [t] is a [let] construct. *)
|
||
|
{ eapply IHcps; obvious.
|
||
|
simpl.
|
||
|
rewrite fold_up_up.
|
||
|
do 2 f_equal.
|
||
|
erewrite IHcps by first [ eapply substc_liftc_liftc; eauto | obvious ].
|
||
|
autosubst. }
|
||
|
}
|
||
|
Qed.
|
||
|
|
||
|
(* The projections of the above result. *)
|
||
|
|
||
|
Definition cpsv_substitution := proj1 substitution.
|
||
|
Definition cps_substitution := proj2 substitution.
|
||
|
|
||
|
(* A point-free reformulation of the above result: [cpsv] commutes with an
|
||
|
arbitrary substitution [sigma], up to a transformation of the values in the
|
||
|
codomain of [sigma]. *)
|
||
|
|
||
|
Goal
|
||
|
forall sigma,
|
||
|
is_value_subst sigma ->
|
||
|
cpsv >>> subst (sigma >>> cpsv) =
|
||
|
subst sigma >>> cpsv.
|
||
|
Proof.
|
||
|
intros. f_ext; intros v. asimpl. eauto using cpsv_substitution.
|
||
|
Qed.
|
||
|
|
||
|
(* This technical lemma is used below. *)
|
||
|
|
||
|
Lemma cpsv_cons:
|
||
|
forall v,
|
||
|
cpsv v .: ids = (v .: ids) >>> cpsv.
|
||
|
Proof.
|
||
|
intros. f_ext; intros [|x]; autosubst.
|
||
|
Qed.
|
||
|
|
||
|
(* A corollary where the substitution [sigma] is [v .: ids], that is, a
|
||
|
substitution of the value [v] for the variable 0. This one is about
|
||
|
[cpsv]. *)
|
||
|
|
||
|
Lemma cpsv_substitution_0:
|
||
|
forall v w,
|
||
|
is_value v ->
|
||
|
(cpsv w).[cpsv v/] =
|
||
|
cpsv w.[v/].
|
||
|
Proof.
|
||
|
intros. rewrite cpsv_cons. erewrite cpsv_substitution by obvious. reflexivity.
|
||
|
Qed.
|
||
|
|
||
|
(* Another corollary where the substitution [sigma] is [v .: ids], that is, a
|
||
|
substitution of the value [v] for the variable 0. This one is about [cps]
|
||
|
and concerns the case where the continuation is of the form [liftc 1 c], so
|
||
|
it is unaffected. *)
|
||
|
|
||
|
Lemma cps_substitution_0:
|
||
|
forall t c v,
|
||
|
is_value v ->
|
||
|
(cps t (liftc 1 c)).[cpsv v/] =
|
||
|
cps t.[v/] c.
|
||
|
Proof.
|
||
|
intros. eapply cps_substitution.
|
||
|
{ autosubst. }
|
||
|
{ obvious. }
|
||
|
{ eauto using substc_liftc_single. }
|
||
|
Qed.
|
||
|
|
||
|
(* A corollary where the substitution [sigma] is [up (v .: ids)], that is, a
|
||
|
substitution of the value [v] for the variable 1, and the continuation is
|
||
|
the variable 0, so it is unaffected. *)
|
||
|
|
||
|
Lemma cps_substitution_1_O_Var_0:
|
||
|
forall t v,
|
||
|
is_value v ->
|
||
|
(cps t (O (Var 0))).[up (cpsv v .: ids)] =
|
||
|
cps t.[up (v .: ids)] (O (Var 0)).
|
||
|
Proof.
|
||
|
intros. eapply cps_substitution.
|
||
|
{ rewrite cpsv_cons. obvious. }
|
||
|
{ obvious. }
|
||
|
{ reflexivity. }
|
||
|
Qed.
|