Require Import List.
Require Import Arith.
Require Import Freevar.
Require Import Misc.
Require Import Psatz.
Require Import Star.
Require Import Coq.Logic.Eqdep_dec.
Require Import FEnv.
Require Import STerm.
Require Import Pretty.
Require Import RedE.
Require Import RedM.
Require Import Inductive.
Compatibility proof between redM and redE.
Inductive read_eiM (
res :
freevar ->
option clo)
dom :
eiM ->
clo ->
Prop :=
|
read_eiM_lazy :
forall t ys vs xs,
map Some vs =
map res ys ->
read_eiM res dom (
eiM_lazy t ys) (
clo_term xs t vs)
|
read_eiM_abs1 :
forall t ys u ws vs xs fvs,
map Some vs =
map res ys ->
redE shallow xs dom fvs (
extE_term ws u) (
out_ret (
valEs_abs t vs)) ->
read_eiM res dom (
eiM_abs1 t ys) (
clo_term xs u ws)
|
read_eiM_abs2 :
forall t ys u ws v vs xs fvs,
map Some vs =
map res ys ->
redE deep xs dom fvs (
extE_term ws u) (
out_ret (
valEd_abs t vs v)) ->
read_eiM res dom (
eiM_abs2 t ys v) (
clo_term xs u ws)
|
read_eiM_constr1 :
forall tag ys u ws vs xs fvs,
map Some vs =
map res ys ->
redE shallow xs dom fvs (
extE_term ws u) (
out_ret (
valEs_constr tag vs)) ->
read_eiM res dom (
eiM_constr1 tag ys) (
clo_term xs u ws)
|
read_eiM_constr2 :
forall tag ys u ws v vs xs fvs,
map Some vs =
map res ys ->
redE deep xs dom fvs (
extE_term ws u) (
out_ret (
valEd_constr tag vs v)) ->
read_eiM res dom (
eiM_constr2 tag ys v) (
clo_term xs u ws)
|
read_eiM_val :
forall u ws v xs fvs,
redE shallow xs dom fvs (
extE_term ws u) (
out_ret (
valE_nf v)) ->
read_eiM res dom (
eiM_val v) (
clo_term xs u ws)
|
read_eiM_var :
forall y,
read_eiM res dom (
eiM_val (
nxvar y)) (
clo_var y).
Lemma read_eiM_dom_mono :
forall res dom u c,
read_eiM res dom u c ->
forall dom2,
dom \
subseteq dom2 ->
read_eiM res dom2 u c.
Proof.
intros res dom u c H; inversion H; subst; intros dom2 Hdom2; econstructor; try eassumption;
eapply redE_dom_mono; eassumption.
Qed.
Definition read_memM (
m :
memxM) (
res :
freevar ->
option clo) :=
(
forall x u,
env_find (
fst m)
x =
Some u ->
exists v,
res x =
Some v /\
read_eiM res (
snd m)
u v) /\
(
forall x,
env_find (
fst m)
x =
None ->
res x =
None).
Lemma read_memM_Some :
forall m res x u v,
read_memM m res ->
env_find (
fst m)
x =
Some u ->
res x =
Some v ->
read_eiM res (
snd m)
u v.
Proof.
intros m res x u v Hread Hm Hres. apply Hread in Hm.
destruct Hm as (v2 & Hx2 & Hv2). congruence.
Qed.
Inductive read_valM :
forall {
df}, (
freevar ->
option clo) ->
valM df ->
valE df ->
Prop :=
|
read_valM_nf :
forall df res v, @
read_valM df res (
valM_nf v) (
valE_nf v)
|
read_valMs_abs :
forall res t ys vs,
map Some vs =
map res ys ->
@
read_valM shallow res (
valMs_abs t ys) (
valEs_abs t vs)
|
read_valMd_abs :
forall res t ys v vs,
map Some vs =
map res ys ->
@
read_valM deep res (
valMd_abs t ys v) (
valEd_abs t vs v)
|
read_valMs_constr :
forall res tag ys vs,
map Some vs =
map res ys ->
@
read_valM shallow res (
valMs_constr tag ys) (
valEs_constr tag vs)
|
read_valMd_constr :
forall res tag ys v vs,
map Some vs =
map res ys ->
@
read_valM deep res (
valMd_constr tag ys v) (
valEd_constr tag vs v).
Definition read_memxM m res :=
read_memM m res /\ (
forall x xs t env,
res x =
Some (
clo_term xs t env) ->
xs \
subseteq (
snd m)).
Inductive read_outM :
forall df, (
freevar ->
option clo) ->
outM (
valM df)
memxM ->
out (
valE df) ->
Prop :=
|
read_outM_div :
forall df res,
read_outM df res outM_div out_div
|
read_outM_ret :
forall df res m v1 v2,
read_memxM m res ->
read_valM res v1 v2 ->
read_outM df res (
outM_ret v1 m) (
out_ret v2).
Inductive read_extM :
forall df, (
freevar ->
option clo) ->
extM df ->
extE df ->
Prop :=
|
read_extM_term :
forall df res env1 env2 m t,
map Some env2 =
map res env1 ->
read_memxM m res ->
read_extM df res (
extM_term env1 m t) (
extE_term env2 t)
|
read_extM_clo :
forall df res m x c,
read_memxM m res ->
res x =
Some c ->
read_extM df res (
extM_clo m x) (
extE_clo c)
|
read_extM_app :
forall df res env1 env2 o1 o2 t,
map Some env2 =
map res env1 ->
read_outM shallow res o1 o2 ->
read_extM df res (
extM_app env1 o1 t) (
extE_app env2 o2 t)
|
read_extM_appnf :
forall df res env1 env2 v o1 o2,
map Some env2 =
map res env1 ->
read_outM deep res o1 o2 ->
read_extM df res (
extM_appnf env1 v o1) (
extE_appnf env2 v o2)
|
read_extM_switch :
forall df res env1 env2 o1 o2 m,
map Some env2 =
map res env1 ->
read_outM shallow res o1 o2 ->
read_extM df res (
extM_switch env1 o1 m) (
extE_switch env2 o2 m)
|
read_extM_switchnf1 :
forall df res env1 env2 v m1 m m2,
map Some env2 =
map res env1 ->
read_memxM m res ->
read_extM df res (
extM_switchnf1 env1 v m1 m m2) (
extE_switchnf1 env2 v m1 m2)
|
read_extM_switchnf2 :
forall df res env1 env2 v m1 xs o1 o2 m2,
map Some env2 =
map res env1 ->
read_outM deep res o1 o2 ->
read_extM df res (
extM_switchnf2 env1 v m1 xs o1 m2) (
extE_switchnf2 env2 v m1 xs o2 m2)
|
read_extMd_abs :
forall res env1 env2 x t o1 o2,
map Some env2 =
map res env1 ->
read_outM deep res o1 o2 ->
read_extM deep res (
extMd_abs env1 x t o1) (
extEd_abs env2 x t o2)
|
read_extMd_constr1 :
forall res tag xs vs l ys ws m,
read_memxM m res ->
map Some vs =
map res xs ->
map Some ws =
map res ys ->
read_extM deep res (
extMd_constr1 tag xs l m ys) (
extEd_constr1 tag vs l ws)
|
read_extMd_constr2 :
forall res tag xs vs l o1 o2 ys ws,
read_outM deep res o1 o2 ->
map Some vs =
map res xs ->
map Some ws =
map res ys ->
read_extM deep res (
extMd_constr2 tag xs l o1 ys) (
extEd_constr2 tag vs l o2 ws).
Definition compat_res (
res1 res2 :
freevar ->
option clo) := (
forall x u,
res1 x =
Some u ->
res2 x =
Some u).
Lemma compat_res_refl :
forall res,
compat_res res res.
Proof.
intros res x u H. exact H.
Qed.
Lemma compat_res_trans :
forall res1 res2 res3,
compat_res res1 res2 ->
compat_res res2 res3 ->
compat_res res1 res3.
Proof.
intros res1 res2 res3 H1 H2 x u H. apply H2. apply H1. assumption.
Qed.
Lemma nenv_eqs :
forall {
A B :
Type} {
res :
A ->
option B} {
env1 :
list A} {
env2 :
list B} {
n :
nat} {
x :
A},
nth_error env1 n =
Some x ->
map Some env2 =
map res env1 ->
exists u,
nth_error env2 n =
Some u /\
res x =
Some u.
Proof.
intros A B res env1 env2 n x H1 H2.
assert (Heq : nth_error (map Some env2) n = nth_error (map res env1) n) by congruence.
rewrite nth_error_map, nth_error_map, H1 in Heq.
destruct (nth_error env2 n) as [u|]; [|congruence]. exists u; split; congruence.
Qed.
Lemma nenv_compat_list :
forall {
res1 res2 :
freevar ->
option clo} {
env1 :
list freevar} {
env2 :
list clo},
compat_res res1 res2 ->
map Some env2 =
map res1 env1 ->
map Some env2 =
map res2 env1.
Proof.
intros res1 res2 env1 env2 Hcompat. revert env2; induction env1 as [|x env1 Henv1]; intros env2 Heq.
- simpl in *. assumption.
- simpl in *. destruct env2 as [|u env2]; simpl in *; [congruence|].
injection Heq; intros. f_equal; [|apply Henv1; assumption].
symmetry. apply Hcompat. symmetry. assumption.
Qed.
Lemma compat_res_read_eiM :
forall dom res1 res2 u c,
compat_res res1 res2 ->
read_eiM res1 dom u c ->
read_eiM res2 dom u c.
Proof.
intros dom res1 res2 u c H1 H2. inversion H2; subst; econstructor; try eassumption.
all: eapply nenv_compat_list; eassumption.
Qed.
Lemma compat_res_read_valM :
forall res1 res2 df v1 v2,
compat_res res1 res2 -> @
read_valM df res1 v1 v2 -> @
read_valM df res2 v1 v2.
Proof.
intros res1 res2 df v1 v2 H1 H2.
inversion H2; subst; unexistT; subst; econstructor; try eassumption.
all: eapply nenv_compat_list; eassumption.
Qed.
Lemma update_env_in_fst :
forall {
A :
Type} (
env :
list (
freevar *
A))
x u v,
env_find env x =
Some u ->
map fst (
update_env env x v) =
map fst env.
Proof.
induction env as [|[y w] env]; intros x u v H.
- simpl in H. congruence.
- simpl in *. destruct freevar_eq_dec.
+ simpl. congruence.
+ simpl. f_equal. eapply IHenv; eassumption.
Qed.
Lemma read_memM_update :
forall m res x c u,
read_memM m res ->
res x =
Some c ->
read_eiM res (
snd m)
u c ->
read_memM (
update_mem m x u)
res.
Proof.
intros [m dom] res x c u Hmem Hres Hread. unfold update_mem; simpl in *.
split; simpl.
- intros y v Hy. rewrite env_find_update_env in Hy. destruct freevar_eq_dec.
+ injection Hy; intros; subst. exists c. split; assumption.
+ apply Hmem. assumption.
- intros y Hy. rewrite env_find_update_env in Hy. destruct freevar_eq_dec.
+ congruence.
+ apply Hmem. assumption.
Qed.
Lemma read_memxM_update :
forall m res x c u,
read_memxM m res ->
res x =
Some c ->
read_eiM res (
snd m)
u c ->
read_memxM (
update_mem m x u)
res.
Proof.
intros m res x c u H1 H2 H3. split; [|apply H1].
eapply read_memM_update; [apply H1|eassumption|eassumption].
Qed.
Definition update_res (
res :
freevar ->
option clo)
x v := (
fun a =>
if freevar_eq_dec a x then Some v else res a).
Definition redM_mklazy_nres t dom x res nenv :=
match env_get_maybe_var nenv t with
|
Some _ =>
res
|
None =>
update_res res x (
clo_term dom t nenv)
end.
Lemma update_res_compat :
forall res x v,
res x =
None ->
compat_res res (
update_res res x v).
Proof.
intros res x v Hx y c Hy. unfold update_res. destruct freevar_eq_dec; [congruence|assumption].
Qed.
Lemma update_res_eq :
forall res x v,
update_res res x v x =
Some v.
Proof.
intros. unfold update_res. rewrite freevar_eq_dec_eq_ifte; reflexivity.
Qed.
Lemma update_res_read_memxM :
forall m res x v1 v2 dom,
env_find (
fst m)
x =
None ->
read_memxM m res ->
read_eiM res dom v1 v2 ->
match v2 with clo_term xs _ _ =>
xs \
subseteq dom |
_ =>
True end ->
snd m \
subseteq dom ->
compat_res res (
update_res res x v2) /\
read_memxM ((
x,
v1) ::
fst m,
dom) (
update_res res x v2) /\
update_res res x v2 x =
Some v2.
Proof.
intros m res x v1 v2 dom H1 H2 H3 H4 H5.
split; [apply update_res_compat, H2, H1|].
split; [|apply update_res_eq].
split; [split|].
- intros y u Hu. simpl in Hu.
destruct freevar_eq_dec.
+ subst; autoinjSome. simpl. exists v2.
split; [apply update_res_eq|].
eapply compat_res_read_eiM; [|eassumption]. apply update_res_compat, H2, H1.
+ apply H2 in Hu. destruct Hu as (v & Hv1 & Hv2); exists v.
simpl. split; [unfold update_res; rewrite freevar_eq_dec_neq_ifte; assumption|].
eapply compat_res_read_eiM, read_eiM_dom_mono; [|eassumption|eassumption]. apply update_res_compat, H2, H1.
- intros y Hy; simpl in Hy. unfold update_res. destruct freevar_eq_dec; [congruence|].
apply H2. assumption.
- intros y xs t env Hy. simpl. unfold update_res in *.
destruct freevar_eq_dec; [|rewrite <- H5; eapply H2; eassumption].
subst; autoinjSome. assumption.
Qed.
Lemma redM_mklazy_nres_compat :
forall t x env1 env2 m1 m2 res,
map Some env2 =
map res env1 ->
redM_mklazy t env1 m1 x m2 ->
read_memxM m1 res ->
compat_res res (
redM_mklazy_nres t (
snd m1)
x res env2) /\
read_memxM m2 (
redM_mklazy_nres t (
snd m1)
x res env2) /\
redM_mklazy_nres t (
snd m1)
x res env2 x =
Some match env_get_maybe_var env2 t with Some c =>
c |
None =>
clo_term (
snd m1)
t env2 end.
Proof.
intros t x env1 env2 m1 m2 res H1 H2 H3.
unfold redM_mklazy, redM_mklazy_nres in *.
destruct (env_get_maybe_var env1 t) as [y|] eqn:Hy.
- destruct t; simpl in *; try congruence.
destruct (nenv_eqs Hy H1) as (c & -> & Hc).
destruct H2 as [-> ->].
split; [apply compat_res_refl|].
split; assumption.
- destruct H2 as [Hx ->]. simpl.
destruct (env_get_maybe_var env2 t) eqn:Henv2.
+ destruct t; simpl in *; try congruence.
assert (length (map Some env2) = length (map res env1)) by congruence; rewrite !map_length in *.
erewrite nth_error_None, <- H, <- nth_error_None in Hy. congruence.
+ apply update_res_read_memxM; [assumption|assumption| |reflexivity|reflexivity].
constructor. assumption.
Qed.
Fixpoint redM_mknlazy_nres l dom xs res nenv :=
match l,
xs with
|
nil,
_ |
_,
nil =>
res
|
t ::
l,
x ::
xs =>
redM_mknlazy_nres l dom xs (
redM_mklazy_nres t dom x res nenv)
nenv
end.
Lemma redM_mknlazy_nres_compat :
forall l xs env1 env2 m1 m2 res,
map Some env2 =
map res env1 ->
redM_mknlazy l env1 m1 xs m2 ->
read_memxM m1 res ->
compat_res res (
redM_mknlazy_nres l (
snd m1)
xs res env2) /\
read_memxM m2 (
redM_mknlazy_nres l (
snd m1)
xs res env2) /\
map (
redM_mknlazy_nres l (
snd m1)
xs res env2)
xs =
map (
fun t =>
Some match env_get_maybe_var env2 t with Some c =>
c |
None =>
clo_term (
snd m1)
t env2 end)
l.
Proof.
intros l xs env1 env2 m1 m2 res H1 H2; revert res H1; induction H2; intros res H1 H3; simpl in *.
- split; [apply compat_res_refl|]. split; [assumption|reflexivity].
- destruct (redM_mklazy_nres_compat _ _ _ _ _ _ _ H1 H H3) as (H4 & H5 & H6).
specialize (IHredM_mknlazy _ ltac:(eapply nenv_compat_list; eassumption) H5).
erewrite <- redM_mklazy_usedvars_eq with (m2 := m2) in IHredM_mknlazy by eassumption.
destruct IHredM_mknlazy as (H7 & H8 & H9).
splits 3.
+ eapply compat_res_trans; eassumption.
+ eassumption.
+ f_equal; [|eassumption].
apply H7. assumption.
Qed.
Definition redM_newvar_nres res a x :=
update_res res a (
clo_var x).
Lemma redM_newvar_nres_compat :
forall m1 m2 a x res,
redM_newvar m1 m2 a x ->
read_memxM m1 res ->
compat_res res (
redM_newvar_nres res a x) /\
read_memxM m2 (
redM_newvar_nres res a x) /\
redM_newvar_nres res a x a =
Some (
clo_var x).
Proof.
intros m1 m2 a x res (H1 & H2 & H3) H4.
unfold redM_newvar_nres in *. rewrite -> H3.
apply update_res_read_memxM; try eassumption.
- constructor.
- tauto.
- prove_list_inc.
Qed.
Fixpoint redM_nnewvar_nres res la lx :=
match la,
lx with
|
nil,
_ |
_,
nil =>
res
|
a ::
la,
x ::
lx =>
redM_nnewvar_nres (
redM_newvar_nres res a x)
la lx
end.
Lemma redM_nnewvar_nres_compat :
forall m1 m2 la lx p res,
redM_nnewvar m1 m2 la lx p ->
read_memxM m1 res ->
compat_res res (
redM_nnewvar_nres res la lx) /\
read_memxM m2 (
redM_nnewvar_nres res la lx) /\
map (
redM_nnewvar_nres res la lx)
la =
map (
fun x =>
Some (
clo_var x))
lx.
Proof.
intros m1 m2 la lx p res H1; revert res; induction H1; intros res H2; simpl in *.
- split; [apply compat_res_refl|]. split; [assumption|reflexivity].
- eapply redM_newvar_nres_compat in H; [|eassumption].
destruct H as (H3 & H4 & H5).
destruct (IHredM_nnewvar _ H4) as (H6 & H7 & H8).
splits 3.
+ eapply compat_res_trans; eassumption.
+ assumption.
+ f_equal; [|eassumption].
apply H6. assumption.
Qed.
Lemma redM_redE :
forall df e o,
redM df e o ->
forall m res e2,
get_ext_memxM e =
Some m ->
read_extM df res e e2 ->
exists m2 o2 res2,
get_out_memxM o =
Some m2 /\
redE df (
snd m) (
snd m2)
nil e2 o2 /\
read_outM df res2 o o2 /\
compat_res res res2.
Proof.
refine (preserved3_rec _ _ redM_is_ind3 _ _).
intros df e o H m res e2 Hm He.
Local Ltac use_recM_ H Hm Hrec Hread Hres a :=
let Hred := fresh "Hred" in
let tmp := fresh "_tmp" in
let tmp2 := fresh "_tmp" in
destruct H as [Hred tmp]; refine ((fun tmp2 => _) (tmp _ a _ _ _)); clear tmp;
try (match type of tmp2 with
exists (name1 : _) (name2 : _) (name3 : _), _ =>
let name1 := fresh name1 in
let name2 := fresh name2 in
let name3 := fresh name3 in
destruct tmp2 as (name1 & name2 & name3 & Hm & Hrec & Hread & Hres)
end).
Tactic Notation "use_recM" ident(H) ident(Hm) ident(Hrec) ident(Hread) ident(Hres) := use_recM_ H Hm Hrec Hread Hres uconstr:(_).
Tactic Notation "use_recM" ident(H) ident(Hm) ident(Hrec) ident(Hread) ident(Hres) uconstr(a):= use_recM_ H Hm Hrec Hread Hres a.
inversion H; unexistT; subst; unexistT; subst; simpl in *; subst; autoinjSome;
lazymatch goal with [ _ : get_abortM _ = _ |- _ ] => idtac | _ => inversion He end; unexistT; subst; simpl in *.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H6) H3 H7). inversion Hx2; subst.
+ do 3 eexists. splits 4.
* reflexivity.
* constructor. econstructor; [eapply H6; eassumption|].
eapply redE_fvs_any.
destruct df; simpl; [eassumption|]. apply redE_shallow_deep_val in H1; assumption.
* constructor; [eassumption|constructor].
* apply compat_res_refl.
+ do 3 eexists. splits 4.
* reflexivity.
* constructor. econstructor.
* constructor; [eassumption|constructor].
* apply compat_res_refl.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H8) H2 H9). inversion Hx2; subst.
do 3 eexists. splits 4.
+ reflexivity.
+ constructor. econstructor; [eapply H8; eassumption|].
eapply redE_fvs_any. eassumption.
+ constructor; [eassumption|constructor; assumption].
+ apply compat_res_refl.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H10) H5 H11). inversion Hx2; subst.
use_recM H6 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
destruct (update_result_memxM _ _ _ _ _ H7 Hm2) as (m3 & Ho2 & Hm3a & Hm3b).
assert (HredE : redE deep xs (snd m2) nil (extE_term ws u) o2). {
eapply redE_shallow_deep_abs in H9; [eapply redE_fvs_any; eassumption| | |eapply redE_fvs_any; eassumption].
-- apply H10 in H11. assumption.
-- eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm2 in Hred; assumption.
}
do 3 eexists. splits 4.
+ eassumption.
+ constructor. econstructor.
* apply H10 in H11. etransitivity; [eassumption|]. rewrite <- Hm3b.
eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm2 in Hred; assumption.
* rewrite <- Hm3b. eassumption.
+ apply redM_abs_deep_result in Hred. destruct Hred as (v & m4 & ->).
inversion H7; unexistT; subst. inversion Hread2; unexistT; subst. inversion H14; unexistT; subst.
constructor; simpl in *; [|constructor; eassumption].
eapply read_memxM_update; [eassumption|eapply Hres2; eassumption|].
econstructor; [eassumption|]. autoinjSome. eassumption.
+ eassumption.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H8) H2 H9). inversion Hx2; subst.
do 3 eexists. splits 4.
+ reflexivity.
+ constructor.
eapply redE_deep_shallow_abs in H10; [|reflexivity].
econstructor; [eapply H8; eassumption|].
eapply redE_fvs_any. eassumption.
+ constructor; [eassumption|constructor; assumption].
+ apply compat_res_refl.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H8) H2 H9). inversion Hx2; subst.
do 3 eexists. splits 4.
+ reflexivity.
+ constructor. econstructor; [eapply H8; eassumption|].
eapply redE_fvs_any. eassumption.
+ constructor; [eassumption|constructor; assumption].
+ apply compat_res_refl.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H8) H2 H9). inversion Hx2; subst.
do 3 eexists. splits 4.
+ reflexivity.
+ constructor. econstructor; [eapply H8; eassumption|].
eapply redE_fvs_any. eassumption.
+ constructor; [eassumption|constructor; assumption].
+ apply compat_res_refl.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H10) H5 H11). inversion Hx2; subst.
use_recM H6 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
destruct (update_result_memxM _ _ _ _ _ H7 Hm2) as (m3 & Ho2 & Hm3a & Hm3b).
assert (HredE : redE deep xs (snd m2) nil (extE_term ws u) o2). {
eapply redE_shallow_deep_constr in H9; [eapply redE_fvs_any; eassumption| | |eapply redE_fvs_any; eassumption].
-- apply H10 in H11. assumption.
-- eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm2 in Hred; assumption.
}
do 3 eexists. splits 4.
+ eassumption.
+ constructor. econstructor.
* apply H10 in H11. etransitivity; [eassumption|]. rewrite <- Hm3b.
eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm2 in Hred; assumption.
* rewrite <- Hm3b. eassumption.
+ apply redM_constr_deep_result in Hred. destruct Hred as (v & m4 & ->).
inversion H7; unexistT; subst. inversion Hread2; unexistT; subst. inversion H14; unexistT; subst.
constructor; simpl in *; [|constructor; eassumption].
eapply read_memxM_update; [eassumption|eapply Hres2; eassumption|].
econstructor; [eassumption|]. autoinjSome. eassumption.
+ eassumption.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H8) H2 H9). inversion Hx2; subst.
do 3 eexists. splits 4.
+ reflexivity.
+ constructor. econstructor; [eapply H8; eassumption|].
eapply redE_fvs_any. eapply redE_deep_shallow_constr in H10; [eassumption|reflexivity].
+ constructor; [eassumption|constructor; assumption].
+ apply compat_res_refl.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H8) H2 H9). inversion Hx2; subst.
do 3 eexists. splits 4.
+ reflexivity.
+ constructor. econstructor; [eapply H8; eassumption|].
eapply redE_fvs_any. eassumption.
+ constructor; [eassumption|constructor; assumption].
+ apply compat_res_refl.
- assert (Hx2 := read_memM_Some _ _ _ _ _ (proj1 H8) H2 H9). inversion Hx2; subst.
use_recM H4 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
destruct (update_result_memxM _ _ _ _ _ H5 Hm2) as (m3 & Ho2 & Hm3a & Hm3b).
do 3 eexists. splits 4.
+ eassumption.
+ constructor. econstructor; [|eapply redE_fvs_any, redE_xs_mono; [rewrite <- Hm3b; eassumption|]].
* apply H8 in H9. etransitivity; [eassumption|]. rewrite <- Hm3b.
eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm2 in Hred; assumption.
* apply H8 in H9. assumption.
+ inversion H5; unexistT; subst; inversion Hread2; unexistT; subst; try (simpl in *; congruence).
* inversion H11; unexistT; subst. constructor; [|constructor].
eapply read_memxM_update; [eassumption|eapply Hres2, H9|].
simpl in *; autoinjSome. econstructor. eapply redE_xs_mono; [destruct df|].
-- eassumption.
-- eapply redE_deep_shallow_val; [eassumption|reflexivity].
-- apply H8 in H9. assumption.
* injection H0 as; subst. inversion H14; unexistT; subst.
constructor; [|constructor; assumption].
eapply read_memxM_update; [eassumption|eapply Hres2, H9|].
simpl in *; autoinjSome. econstructor; [eassumption|].
eapply redE_xs_mono; [eassumption|].
apply H8 in H9. assumption.
* injection H0 as; subst. inversion H14; unexistT; subst.
constructor; [|constructor; assumption].
eapply read_memxM_update; [eassumption|eapply Hres2, H9|].
simpl in *; autoinjSome. econstructor; [eassumption|].
eapply redE_xs_mono; [eassumption|].
apply H8 in H9. assumption.
* injection H0 as; subst. inversion H14; unexistT; subst.
constructor; [|constructor; assumption].
eapply read_memxM_update; [eassumption|eapply Hres2, H9|].
simpl in *; autoinjSome. econstructor; [eassumption|].
eapply redE_xs_mono; [eassumption|].
apply H8 in H9. assumption.
* injection H0 as; subst. inversion H14; unexistT; subst.
constructor; [|constructor; assumption].
eapply read_memxM_update; [eassumption|eapply Hres2, H9|].
simpl in *; autoinjSome. econstructor; [eassumption|].
eapply redE_xs_mono; [eassumption|].
apply H8 in H9. assumption.
+ eassumption.
- destruct (nenv_eqs H3 H6) as (c & Hc1 & Hc2).
use_recM H4 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
do 3 eexists. splits 4.
+ eassumption.
+ constructor. econstructor; eassumption.
+ eassumption.
+ assumption.
- do 3 eexists. splits 4.
+ reflexivity.
+ constructor. econstructor.
+ constructor; [eassumption|].
constructor. assumption.
+ apply compat_res_refl.
- destruct (redM_newvar_nres_compat m m2 a x res) as (Hcompat & Hread2 & Hres2); try assumption.
destruct H5 as (Ha & Hx & Hm2). subst m2.
use_recM H6 Hm3 Hrec3 Hread3 Hres3 (redM_newvar_nres res a x);
[use_recM H7 Hm4 Hrec4 Hread4 Hres4; [|eassumption|]|reflexivity|constructor].
+ do 3 eexists. splits 4.
* eassumption.
* constructor. econstructor.
-- eassumption.
-- eapply redM_usedvars_inc in Hred0; [|eassumption].
rewrite Hm4 in Hred0. rewrite <- Hred0.
eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm3 in Hred. rewrite <- Hred. simpl. left; reflexivity.
-- eapply redE_fvs_any. eapply redE_dom_mono; [eassumption|].
eapply redM_usedvars_inc in Hred0; [|eassumption].
rewrite Hm4 in Hred0. assumption.
-- eapply redE_xs_mono; [eassumption|].
eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm3 in Hred. rewrite <- Hred.
simpl. prove_list_inc.
* eassumption.
* eapply compat_res_trans; [exact Hcompat|].
eapply compat_res_trans; [exact Hres3|].
eassumption.
+ constructor; [|eassumption].
eapply nenv_compat_list; [|eassumption]. eapply compat_res_trans; eassumption.
+ simpl. f_equal; [symmetry; assumption|].
eapply nenv_compat_list; eassumption.
+ assumption.
- inversion H9; unexistT; subst.
do 3 eexists; splits 4.
+ reflexivity.
+ constructor. econstructor.
+ constructor; [eassumption|]. inversion H10; unexistT; subst; constructor; assumption.
+ apply compat_res_refl.
- use_recM H3 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
use_recM H4 Hm3 Hrec3 Hread3 Hres3; [|eassumption|constructor; [eapply nenv_compat_list; eassumption|eassumption]].
do 3 eexists; splits 4.
+ eassumption.
+ constructor. econstructor.
* eapply redE_dom_mono; [eassumption|].
eapply redM_usedvars_inc in Hred0; [|eassumption].
rewrite Hm3 in Hred0. assumption.
* eapply redE_xs_mono; [eassumption|].
eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm2 in Hred. assumption.
+ eassumption.
+ eapply compat_res_trans; eassumption.
- inversion H9; unexistT; subst. inversion H10; unexistT; subst.
use_recM H3 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
use_recM H4 Hm3 Hrec3 Hread3 Hres3; [|eassumption|constructor; [eapply nenv_compat_list; eassumption|eassumption]].
do 3 eexists; splits 4.
+ eassumption.
+ constructor. econstructor.
* eapply redE_dom_mono; [eassumption|].
eapply redM_usedvars_inc in Hred0; [|eassumption].
rewrite Hm3 in Hred0. assumption.
* eapply redE_xs_mono; [eassumption|].
eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm2 in Hred. assumption.
+ eassumption.
+ eapply compat_res_trans; eassumption.
- inversion H9; unexistT; subst. inversion H10; unexistT; subst.
destruct (redM_mklazy_nres_compat t2 x env env0 m m2 res) as (Hcompat & Hm2 & Hres2); try assumption.
use_recM H4 Hm3 Hrec3 Hread3 Hres3; [do 3 eexists; splits 4|reflexivity|constructor].
+ eassumption.
+ constructor. econstructor; [reflexivity| |eapply redE_xs_mono; [eassumption|]].
* eapply redM_usedvars_inc in Hred; [|reflexivity]. rewrite Hm3 in Hred.
erewrite redM_mklazy_usedvars_eq; eassumption.
* erewrite redM_mklazy_usedvars_eq; [reflexivity|eassumption].
+ eassumption.
+ eapply compat_res_trans; [exact Hcompat|exact Hres3].
+ simpl. f_equal; [|eapply nenv_compat_list; eassumption].
symmetry; assumption.
+ assumption.
- inversion H7; unexistT; subst.
do 3 eexists; splits 4.
+ reflexivity.
+ constructor. econstructor.
+ constructor; [eassumption|].
inversion H8; unexistT; subst; simpl in *; constructor.
+ apply compat_res_refl.
- destruct (redM_mknlazy_nres_compat l lc env env2 m m2 res) as (Hcompat & Hm2 & Hres2); try assumption.
do 3 eexists; splits 4.
+ reflexivity.
+ constructor.
apply redE_constr_shallow with
(lc := map (fun t => match env_get_maybe_var env2 t with Some c => c | None => clo_term (snd m) t env2 end) l).
rewrite Forall2_map_right, Forall2_map_same.
assert (snd m = snd m2) by (eapply redM_mknlazy_usedvars_eq; eassumption).
apply Forall_True. intros t.
destruct env_get_maybe_var; [reflexivity|].
eexists; splits 3; [reflexivity|rewrite H1; reflexivity|reflexivity].
+ constructor; [eassumption|]. constructor. rewrite map_map, <- Hres2. reflexivity.
+ assumption.
- destruct (redM_mknlazy_nres_compat l lc env env2 m m2 res) as (Hcompat & Hm2 & Hres2); try assumption.
pose (nlc := map (fun t => match env_get_maybe_var env2 t with Some c => c | None => clo_term (snd m) t env2 end) l).
assert (map Some nlc = map (redM_mknlazy_nres l (snd m) lc res env2) lc) by
(unfold nlc; rewrite map_map, Hres2; reflexivity).
use_recM H6 Hm3 Hrec3 Hread3 Hres3 (redM_mknlazy_nres l (snd m) lc res env2); [|reflexivity|constructor; eassumption].
do 3 eexists; splits 4.
+ eassumption.
+ assert (Hmeq : snd m = snd m2) by (eapply redM_mknlazy_usedvars_eq; eassumption).
constructor. econstructor; [|rewrite Hmeq; eassumption].
unfold nlc; rewrite Forall2_map_right, Forall2_map_same.
apply Forall_True. intros t.
destruct env_get_maybe_var; [reflexivity|].
eexists; splits 3; [reflexivity| |reflexivity].
rewrite Hmeq. eapply redM_usedvars_inc in Hred; [|reflexivity].
rewrite Hm3 in Hred; assumption.
+ eassumption.
+ eapply compat_res_trans; eassumption.
- destruct ws; simpl in *; [|congruence].
do 3 eexists; splits 4.
+ reflexivity.
+ constructor. econstructor.
+ constructor; [eassumption|]. constructor. assumption.
+ apply compat_res_refl.
- destruct ws as [|c ws]; simpl in *; [congruence|].
injection H13 as H13 H14.
use_recM H4 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; [eassumption|symmetry; eassumption]].
use_recM H6 Hm3 Hrec3 Hread3 Hres3; [|eassumption|constructor; try eassumption; eapply nenv_compat_list; eassumption].
do 3 eexists; splits 4.
+ eassumption.
+ constructor. econstructor.
* eapply redE_dom_mono; [eassumption|].
eapply redM_usedvars_inc in Hred0; [|eassumption]; rewrite Hm3 in Hred0. assumption.
* eapply redE_xs_mono; [eassumption|].
eapply redM_usedvars_inc in Hred; [|reflexivity]; rewrite Hm2 in Hred. assumption.
+ eassumption.
+ eapply compat_res_trans; eassumption.
- inversion H8; unexistT; subst.
use_recM H2 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
do 3 eexists; splits 4.
+ eassumption.
+ constructor. econstructor.
inversion H10; unexistT; subst; simpl in *; eassumption.
+ eassumption.
+ eassumption.
- use_recM H3 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
use_recM H4 Hm3 Hrec3 Hread3 Hres3; [|eassumption|constructor; [|eassumption]; eapply nenv_compat_list; eassumption].
do 3 eexists; splits 4.
+ eassumption.
+ constructor. econstructor.
* eapply redE_dom_mono; [eassumption|].
eapply redM_usedvars_inc in Hred0; [|eassumption]; rewrite Hm3 in Hred0. assumption.
* eapply redE_xs_mono; [eassumption|].
eapply redM_usedvars_inc in Hred; [|reflexivity]; rewrite Hm2 in Hred. assumption.
+ eassumption.
+ eapply compat_res_trans; eassumption.
- inversion H9; unexistT; subst. inversion H10; unexistT; subst.
use_recM H4 Hm2 Hrec2 Hread2 Hres2; [do 3 eexists; splits 4|reflexivity|constructor].
+ eassumption.
+ constructor. econstructor; [|eassumption].
rewrite H3. f_equal. f_equal.
erewrite <- map_length, <- H7, map_length. reflexivity.
+ eassumption.
+ eassumption.
+ rewrite !map_app. f_equal; eassumption.
+ eassumption.
- inversion H8; unexistT; subst. inversion H9; unexistT; subst.
use_recM H3 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
do 3 eexists; splits 4.
+ eassumption.
+ constructor. econstructor. eassumption.
+ eassumption.
+ eassumption.
- do 3 eexists; splits 4.
+ reflexivity.
+ constructor. econstructor.
+ constructor; [eassumption|]. constructor.
+ apply compat_res_refl.
- destruct (redM_nnewvar_nres_compat m m2 la lx p res) as (Hcompat & Hm2 & Hres2); try assumption.
use_recM H4 Hm3 Hrec3 Hread3 Hres3 (redM_nnewvar_nres res la lx); [|reflexivity|constructor].
+ use_recM H5 Hm4 Hrec4 Hread4 Hres4; [do 3 eexists; splits 4|eassumption|constructor].
* eassumption.
* constructor. econstructor.
-- eapply redM_nnewvar_distinct; eassumption.
-- erewrite redM_nnewvar_incl; [|eassumption].
eapply redM_usedvars_inc in Hred; [|reflexivity]. rewrite Hm3 in Hred.
eapply redM_usedvars_inc in Hred0; [|eassumption]. rewrite Hm4 in Hred0.
etransitivity; eassumption.
-- eapply redE_xsdom_mono; [eassumption| |eapply redM_usedvars_inc in Hred0; [rewrite Hm4 in Hred0|]; eassumption].
rewrite list_inc_app_left. split; [|eapply redM_nnewvar_usedvars_inc; eassumption].
eapply redM_nnewvar_incl; eassumption.
-- eapply redE_xs_mono; [eassumption|].
etransitivity; [eapply redM_nnewvar_usedvars_inc; eassumption|].
eapply redM_usedvars_inc in Hred; [|reflexivity]. rewrite Hm3 in Hred. assumption.
* eassumption.
* eapply compat_res_trans; [|exact Hres4]. eapply compat_res_trans; [exact Hcompat|exact Hres3].
* eapply nenv_compat_list; [|eassumption].
eapply compat_res_trans; eassumption.
* assumption.
+ rewrite !map_app. f_equal; [|eapply nenv_compat_list; eassumption].
rewrite map_map, Hres2. reflexivity.
+ assumption.
- inversion H11; unexistT; subst.
use_recM H3 Hm2 Hrec2 Hread2 Hres2; [|reflexivity|constructor; eassumption].
do 3 eexists; splits 4.
+ eassumption.
+ constructor. econstructor.
inversion H8; unexistT; subst; simpl in *; eassumption.
+ eassumption.
+ eassumption.
- destruct e; simpl in *; try congruence; destruct o0; simpl in *; congruence.
Qed.