aboutsummaryrefslogtreecommitdiff
path: root/src/Experiments/NewPipeline/UnderLetsProofs.v
diff options
context:
space:
mode:
authorGravatar Andres Erbsen <andreser@mit.edu>2019-01-08 01:59:52 -0500
committerGravatar Andres Erbsen <andreser@mit.edu>2019-01-09 12:44:11 -0500
commit3ec21c64b3682465ca8e159a187689b207c71de4 (patch)
tree2294367302480f1f4c29a2266e2d1c7c8af3ee48 /src/Experiments/NewPipeline/UnderLetsProofs.v
parentdf7920808566c0d70b5388a0a750b40044635eb6 (diff)
move src/Experiments/NewPipeline/ to src/
Diffstat (limited to 'src/Experiments/NewPipeline/UnderLetsProofs.v')
-rw-r--r--src/Experiments/NewPipeline/UnderLetsProofs.v1025
1 files changed, 0 insertions, 1025 deletions
diff --git a/src/Experiments/NewPipeline/UnderLetsProofs.v b/src/Experiments/NewPipeline/UnderLetsProofs.v
deleted file mode 100644
index 19e79e95b..000000000
--- a/src/Experiments/NewPipeline/UnderLetsProofs.v
+++ /dev/null
@@ -1,1025 +0,0 @@
-Require Import Coq.Lists.List.
-Require Import Coq.Classes.Morphisms.
-Require Import Coq.Lists.SetoidList.
-Require Import Crypto.Experiments.NewPipeline.Language.
-Require Import Crypto.Experiments.NewPipeline.LanguageInversion.
-Require Import Crypto.Experiments.NewPipeline.LanguageWf.
-Require Import Crypto.Experiments.NewPipeline.UnderLets.
-Require Import Crypto.Util.Prod.
-Require Import Crypto.Util.Sigma.
-Require Import Crypto.Util.Option.
-Require Import Crypto.Util.Tactics.BreakMatch.
-Require Import Crypto.Util.Tactics.DestructHead.
-Require Import Crypto.Util.Tactics.SpecializeAllWays.
-Require Import Crypto.Util.Tactics.SpecializeBy.
-Import ListNotations. Local Open Scope list_scope.
-
-Import EqNotations.
-Module Compilers.
- Import Language.Compilers.
- Import LanguageInversion.Compilers.
- Import LanguageWf.Compilers.
- Import UnderLets.Compilers.
- Import ident.Notations.
- Import expr.Notations.
- Import invert_expr.
-
- Module SubstVarLike.
- Section with_ident.
- Context {base_type : Type}.
- Local Notation type := (type.type base_type).
- Context {ident : type -> Type}.
- Local Notation expr := (@expr.expr base_type ident).
- Section with_var.
- Context {var1 var2 : type -> Type}.
- Local Notation expr1 := (@expr.expr base_type ident var1).
- Local Notation expr2 := (@expr.expr base_type ident var2).
- Section with_var_like.
- Context (is_var_like1 : forall t, @expr var1 t -> bool)
- (is_var_like2 : forall t, @expr var2 t -> bool).
- Local Notation subst_var_like1 := (@SubstVarLike.subst_var_like base_type ident var1 is_var_like1).
- Local Notation subst_var_like2 := (@SubstVarLike.subst_var_like base_type ident var2 is_var_like2).
- Definition is_var_like_wfT := forall G t e1 e2, expr.wf G (t:=t) e1 e2 -> is_var_like1 t e1 = is_var_like2 t e2.
- Context (is_var_like_good : is_var_like_wfT).
-
- Lemma wf_subst_var_like G1 G2 t e1 e2
- (HG1G2 : forall t v1 v2, List.In (existT _ t (v1, v2)) G1 -> expr.wf G2 v1 v2)
- : expr.wf G1 (t:=t) e1 e2 -> expr.wf G2 (subst_var_like1 e1) (subst_var_like2 e2).
- Proof.
- cbv [is_var_like_wfT] in *.
- intro Hwf; revert dependent G2; induction Hwf;
- cbn [SubstVarLike.subst_var_like];
- repeat first [ match goal with
- | [ H : is_var_like1 _ ?x = _, H' : is_var_like2 _ ?y = _ |- _ ]
- => assert (is_var_like1 _ x = is_var_like2 _ y) by eauto; congruence
- end
- | progress wf_safe_t
- | progress break_innermost_match
- | solve [ wf_t ] ].
- Qed.
- End with_var_like.
-
- Section with_ident_like.
- Context (ident_is_good : forall t, ident t -> bool).
-
- Lemma wfT_is_recursively_var_or_ident
- : is_var_like_wfT (fun t => SubstVarLike.is_recursively_var_or_ident ident_is_good)
- (fun t => SubstVarLike.is_recursively_var_or_ident ident_is_good).
- Proof.
- intros G t e1 e2 Hwf; induction Hwf; cbn [SubstVarLike.is_recursively_var_or_ident];
- congruence.
- Qed.
- End with_ident_like.
-
- Lemma wfT_is_var
- : is_var_like_wfT (fun _ e => match invert_Var e with Some _ => true | None => false end)
- (fun _ e => match invert_Var e with Some _ => true | None => false end).
- Proof. intros G t e1 e2 Hwf; destruct Hwf; cbn [invert_Var]; reflexivity. Qed.
- End with_var.
-
- Local Notation SubstVarLike := (@SubstVarLike.SubstVarLike base_type ident).
- Local Notation SubstVar := (@SubstVarLike.SubstVar base_type ident).
- Local Notation SubstVarOrIdent := (@SubstVarLike.SubstVarOrIdent base_type ident).
-
- Lemma Wf_SubstVarLike (is_var_like : forall var t, @expr var t -> bool)
- (is_var_like_good : forall var1 var2, is_var_like_wfT (is_var_like var1) (is_var_like var2))
- {t} (e : expr.Expr t)
- : expr.Wf e -> expr.Wf (SubstVarLike is_var_like e).
- Proof.
- intros Hwf var1 var2; eapply wf_subst_var_like; eauto with nocore; cbn [In]; tauto.
- Qed.
-
- Lemma Wf_SubstVar {t} (e : expr.Expr t)
- : expr.Wf e -> expr.Wf (SubstVar e).
- Proof.
- intros Hwf var1 var2; eapply wf_subst_var_like; eauto using wfT_is_var with nocore; cbn [In]; tauto.
- Qed.
-
- Lemma Wf_SubstVarOrIdent (should_subst_ident : forall t, ident t -> bool)
- {t} (e : expr.Expr t)
- : expr.Wf e -> expr.Wf (SubstVarOrIdent should_subst_ident e).
- Proof.
- intros Hwf var1 var2; eapply wf_subst_var_like; eauto using wfT_is_recursively_var_or_ident with nocore; cbn [In]; tauto.
- Qed.
-
- Section interp.
- Context {base_interp : base_type -> Type}
- {interp_ident : forall t, ident t -> type.interp base_interp t}
- {interp_ident_Proper : forall t, Proper (eq ==> type.eqv) (interp_ident t)}.
- Section with_is_var_like.
- Context (is_var_like : forall t, @expr (type.interp base_interp) t -> bool).
-
- Lemma interp_subst_var_like_gen G t (e1 e2 : expr t)
- (HG : forall t v1 v2, List.In (existT _ t (v1, v2)) G -> expr.interp interp_ident v1 == v2)
- (Hwf : expr.wf G e1 e2)
- : expr.interp interp_ident (SubstVarLike.subst_var_like is_var_like e1) == expr.interp interp_ident e2.
- Proof.
- induction Hwf; cbn [SubstVarLike.subst_var_like]; cbv [Proper respectful] in *;
- interp_safe_t; break_innermost_match; interp_safe_t.
- Qed.
-
- Lemma interp_subst_var_like_gen_nil t (e1 e2 : expr t)
- (Hwf : expr.wf nil e1 e2)
- : expr.interp interp_ident (SubstVarLike.subst_var_like is_var_like e1) == expr.interp interp_ident e2.
- Proof. apply interp_subst_var_like_gen with (G:=nil); cbn [In]; eauto with nocore; tauto. Qed.
- End with_is_var_like.
-
- Lemma Interp_SubstVarLike (is_var_like : forall var t, @expr var t -> bool)
- {t} (e : expr.Expr t) (Hwf : expr.Wf e)
- : expr.Interp interp_ident (SubstVarLike is_var_like e) == expr.Interp interp_ident e.
- Proof. apply interp_subst_var_like_gen_nil, Hwf. Qed.
-
- Lemma Interp_SubstVar {t} (e : expr.Expr t) (Hwf : expr.Wf e)
- : expr.Interp interp_ident (SubstVar e) == expr.Interp interp_ident e.
- Proof. apply interp_subst_var_like_gen_nil, Hwf. Qed.
-
- Lemma Interp_SubstVarOrIdent (should_subst_ident : forall t, ident t -> bool)
- {t} (e : expr.Expr t) (Hwf : expr.Wf e)
- : expr.Interp interp_ident (SubstVarOrIdent should_subst_ident e) == expr.Interp interp_ident e.
- Proof. apply interp_subst_var_like_gen_nil, Hwf. Qed.
- End interp.
- End with_ident.
-
- Lemma Wf_SubstVarFstSndPairOppCast {t} (e : expr.Expr t)
- : expr.Wf e -> expr.Wf (SubstVarLike.SubstVarFstSndPairOppCast e).
- Proof. apply Wf_SubstVarOrIdent. Qed.
-
- Section with_cast.
- Context {cast_outside_of_range : ZRange.zrange -> BinInt.Z -> BinInt.Z}.
- Local Notation ident_interp := (@ident.gen_interp cast_outside_of_range).
- Local Notation interp := (@expr.interp _ _ _ (@ident_interp)).
- Local Notation Interp := (@expr.Interp _ _ _ (@ident_interp)).
-
- Lemma Interp_SubstVarFstSndPairOppCast {t} (e : expr.Expr t) (Hwf : expr.Wf e)
- : Interp (SubstVarLike.SubstVarFstSndPairOppCast e) == Interp e.
- Proof. apply Interp_SubstVarOrIdent, Hwf. Qed.
- End with_cast.
- End SubstVarLike.
-
- Hint Resolve SubstVarLike.Wf_SubstVar SubstVarLike.Wf_SubstVarFstSndPairOppCast SubstVarLike.Wf_SubstVarLike SubstVarLike.Wf_SubstVarOrIdent : wf.
- Hint Rewrite @SubstVarLike.Interp_SubstVar @SubstVarLike.Interp_SubstVarFstSndPairOppCast @SubstVarLike.Interp_SubstVarLike @SubstVarLike.Interp_SubstVarOrIdent : interp.
-
- Module UnderLets.
- Import UnderLets.Compilers.UnderLets.
- Section with_ident.
- Context {base_type : Type}.
- Local Notation type := (type.type base_type).
- Context {ident : type -> Type}.
- Local Notation expr := (@expr.expr base_type ident).
- Local Notation UnderLets := (@UnderLets base_type ident).
-
- Section with_var.
- Context {var1 var2 : type -> Type}.
-
- Inductive wf {T1 T2} {P : list { t : type & var1 t * var2 t }%type -> T1 -> T2 -> Prop}
- : list { t : type & var1 t * var2 t }%type -> @UnderLets var1 T1 -> @UnderLets var2 T2 -> Prop :=
- | Wf_Base G e1 e2 : P G e1 e2 -> wf G (Base e1) (Base e2)
- | Wf_UnderLet G A x1 x2 f1 f2
- : expr.wf G x1 x2
- -> (forall v1 v2, wf (existT _ A (v1, v2) :: G) (f1 v1) (f2 v2))
- -> wf G (UnderLet x1 f1) (UnderLet x2 f2).
- Global Arguments wf {T1 T2} P _ _ _.
-
- Lemma wf_Proper_list_impl {T1 T2}
- (P1 P2 : list { t : type & var1 t * var2 t }%type -> T1 -> T2 -> Prop)
- G1 G2
- (HP : forall seg v1 v2, P1 (seg ++ G1) v1 v2 -> P2 (seg ++ G2) v1 v2)
- (HG1G2 : forall t v1 v2, List.In (existT _ t (v1, v2)) G1 -> List.In (existT _ t (v1, v2)) G2)
- e1 e2
- (Hwf : @wf T1 T2 P1 G1 e1 e2)
- : @wf T1 T2 P2 G2 e1 e2.
- Proof.
- revert dependent G2; induction Hwf; constructor;
- repeat first [ progress cbn in *
- | progress intros
- | solve [ eauto ]
- | progress subst
- | progress destruct_head'_or
- | progress inversion_sigma
- | progress inversion_prod
- | match goal with H : _ |- _ => apply H; clear H end
- | wf_unsafe_t_step
- | eapply (HP nil)
- | rewrite ListUtil.app_cons_app_app in * ].
- Qed.
-
- Lemma wf_Proper_list {T1 T2}
- {P : list { t : type & var1 t * var2 t }%type -> T1 -> T2 -> Prop}
- (HP : forall G1 G2,
- (forall t v1 v2, List.In (existT _ t (v1, v2)) G1 -> List.In (existT _ t (v1, v2)) G2)
- -> forall v1 v2, P G1 v1 v2 -> P G2 v1 v2)
- G1 G2
- (HG1G2 : forall t v1 v2, List.In (existT _ t (v1, v2)) G1 -> List.In (existT _ t (v1, v2)) G2)
- e1 e2
- (Hwf : @wf T1 T2 P G1 e1 e2)
- : @wf T1 T2 P G2 e1 e2.
- Proof.
- eapply wf_Proper_list_impl; [ intros | | eassumption ]; eauto.
- eapply HP; [ | eassumption ]; intros *.
- rewrite !in_app_iff; intuition eauto.
- Qed.
-
- Lemma wf_to_expr {t} (x : @UnderLets var1 (@expr var1 t)) (y : @UnderLets var2 (@expr var2 t))
- G
- : wf (fun G => expr.wf G) G x y -> expr.wf G (to_expr x) (to_expr y).
- Proof.
- intro Hwf; induction Hwf; cbn [to_expr]; [ assumption | constructor; auto ].
- Qed.
-
- Lemma wf_splice {A1 B1 A2 B2}
- {P : list { t : type & var1 t * var2 t }%type -> A1 -> A2 -> Prop}
- {Q : list { t : type & var1 t * var2 t }%type -> B1 -> B2 -> Prop}
- G
- (x1 : @UnderLets var1 A1) (x2 : @UnderLets var2 A2) (Hx : @wf _ _ P G x1 x2)
- (e1 : A1 -> @UnderLets var1 B1) (e2 : A2 -> @UnderLets var2 B2)
- (He : forall G' a1 a2, (exists seg, G' = seg ++ G) -> P G' a1 a2 -> @wf _ _ Q G' (e1 a1) (e2 a2))
- : @wf _ _ Q G (splice x1 e1) (splice x2 e2).
- Proof.
- induction Hx; cbn [splice]; [ | constructor ];
- eauto using (ex_intro _ nil); intros.
- match goal with H : _ |- _ => eapply H end;
- intros; destruct_head'_ex; subst.
- rewrite ListUtil.app_cons_app_app in *.
- eauto using (ex_intro _ nil).
- Qed.
-
- Lemma wf_splice_list {A1 B1 A2 B2}
- {P_parts : nat -> list { t : type & var1 t * var2 t }%type -> A1 -> A2 -> Prop}
- {P : list { t : type & var1 t * var2 t }%type -> list A1 -> list A2 -> Prop}
- {Q : list { t : type & var1 t * var2 t }%type -> B1 -> B2 -> Prop}
- G
- (x1 : list (@UnderLets var1 A1)) (x2 : list (@UnderLets var2 A2))
- (P_parts_Proper_list : forall n G1 G2 a1 a2,
- (forall t v1 v2, List.In (existT _ t (v1, v2)) G1 -> List.In (existT _ t (v1, v2)) G2)
- -> P_parts n G1 a1 a2 -> P_parts n G2 a1 a2)
- (HP : forall G' l1 l2,
- (exists seg, G' = seg ++ G) -> length l1 = length x1 -> length l2 = length x2
- -> (forall n v1 v2, nth_error l1 n = Some v1 -> nth_error l2 n = Some v2 -> P_parts n G' v1 v2)
- -> P G' l1 l2)
- (Hx_len : length x1 = length x2)
- (Hx : forall n v1 v2, nth_error x1 n = Some v1 -> nth_error x2 n = Some v2 ->@wf _ _ (P_parts n) G v1 v2)
- (e1 : list A1 -> @UnderLets var1 B1) (e2 : list A2 -> @UnderLets var2 B2)
- (He : forall G' a1 a2, (exists seg, G' = seg ++ G) -> P G' a1 a2 -> @wf _ _ Q G' (e1 a1) (e2 a2))
- : @wf _ _ Q G (splice_list x1 e1) (splice_list x2 e2).
- Proof.
- revert dependent P; revert dependent P_parts; revert dependent G; revert dependent e1; revert dependent e2; revert dependent x2;
- induction x1 as [|x1 xs1 IHx1], x2 as [|x2 xs2];
- cbn [splice_list length nth_error]; intros; try congruence.
- { eapply He; [ exists nil; reflexivity | eapply HP; eauto using (ex_intro _ nil) ].
- intros []; cbn [nth_error]; intros; congruence. }
- { inversion Hx_len; clear Hx_len.
- pose proof (fun n => Hx (S n)) as Hxs.
- specialize (Hx O).
- cbn [nth_error] in *.
- eapply wf_splice; [ eapply Hx; reflexivity | wf_safe_t ].
- destruct_head'_ex; subst.
- lazymatch goal with
- | [ |- wf _ _ (splice_list _ (fun _ => ?e1 (?a1 :: _))) (splice_list _ (fun _ => ?e2 (?a2 :: _))) ]
- => eapply IHx1 with (P_parts:=fun n => P_parts (S n)) (P:=fun G' l1 l2 => P G' (a1::l1) (a2::l2))
- end; wf_safe_t; destruct_head'_ex; wf_safe_t.
- { eapply wf_Proper_list; [ | | eapply Hxs ]; wf_t. }
- { eapply HP; cbn [length]; rewrite ?app_assoc; eauto; [].
- intros []; cbn [nth_error]; wf_safe_t; inversion_option; wf_safe_t.
- { eapply P_parts_Proper_list; [ | eauto ]; wf_t. }
- { eapply P_parts_Proper_list; [ | eauto ]; wf_t. } }
- { eapply He; eauto; rewrite ?app_assoc; eauto. } }
- Qed.
-
- Lemma wf_splice_list_no_order {A1 B1 A2 B2}
- {P : list { t : type & var1 t * var2 t }%type -> A1 -> A2 -> Prop}
- {Q : list { t : type & var1 t * var2 t }%type -> B1 -> B2 -> Prop}
- G
- (x1 : list (@UnderLets var1 A1)) (x2 : list (@UnderLets var2 A2))
- (P_Proper_list : forall G1 G2 a1 a2,
- (forall t v1 v2, List.In (existT _ t (v1, v2)) G1 -> List.In (existT _ t (v1, v2)) G2)
- -> P G1 a1 a2 -> P G2 a1 a2)
- (Hx_len : length x1 = length x2)
- (Hx : forall n v1 v2, nth_error x1 n = Some v1 -> nth_error x2 n = Some v2 ->@wf _ _ P G v1 v2)
- (e1 : list A1 -> @UnderLets var1 B1) (e2 : list A2 -> @UnderLets var2 B2)
- (He : forall G' a1 a2, (exists seg, G' = seg ++ G)
- -> length a1 = length x1
- -> length a2 = length x2
- -> (forall v1 v2, List.In (v1, v2) (combine a1 a2) -> P G' v1 v2)
- -> @wf _ _ Q G' (e1 a1) (e2 a2))
- : @wf _ _ Q G (splice_list x1 e1) (splice_list x2 e2).
- Proof.
- apply @wf_splice_list
- with (P_parts := fun _ => P)
- (P:=fun G' l1 l2 => length l1 = length x1 /\ length l2 = length x2
- /\ forall v1 v2, List.In (v1, v2) (combine l1 l2) -> P G' v1 v2);
- repeat first [ progress wf_safe_t
- | apply conj
- | progress inversion_option
- | progress destruct_head'_ex
- | progress break_innermost_match_hyps
- | match goal with
- | [ H : In _ (combine _ _) |- _ ] => apply ListUtil.In_nth_error_value in H
- | [ H : context[nth_error (combine _ _) _] |- _ ]
- => rewrite ListUtil.nth_error_combine in H
- end ].
- Qed.
- End with_var.
-
- Section for_interp.
- Context {base_interp : base_type -> Type}
- (ident_interp : forall t, ident t -> type.interp base_interp t).
-
- Local Notation UnderLets := (@UnderLets (type.interp base_interp)).
-
- Fixpoint interp {T} (v : UnderLets T) : T
- := match v with
- | Base v => v
- | UnderLet A x f => let xv := expr.interp ident_interp x in
- @interp _ (f xv)
- end.
-
- Fixpoint interp_related {T1 T2} (R : T1 -> T2 -> Prop) (e : UnderLets T1) (v2 : T2) : Prop
- := match e with
- | Base v1 => R v1 v2
- | UnderLet t e f (* combine the App rule with the Abs rule *)
- => exists fv ev,
- expr.interp_related ident_interp e ev
- /\ (forall x1 x2,
- x1 == x2
- -> @interp_related T1 T2 R (f x1) (fv x2))
- /\ fv ev = v2
- end.
-
- Lemma interp_splice {A B} (x : UnderLets A) (e : A -> UnderLets B)
- : interp (splice x e) = interp (e (interp x)).
- Proof. induction x; cbn [splice interp]; eauto. Qed.
-
- Lemma interp_splice_list {A B} (x : list (UnderLets A)) (e : list A -> UnderLets B)
- : interp (splice_list x e)
- = interp (e (map interp x)).
- Proof.
- revert e; induction x as [|x xs IHx]; intros; cbn [splice_list interp map]; [ reflexivity | ].
- rewrite interp_splice, IHx; reflexivity.
- Qed.
-
- Lemma interp_to_expr {t} (x : UnderLets (expr t))
- : expr.interp ident_interp (to_expr x) = expr.interp ident_interp (interp x).
- Proof. induction x; cbn [expr.interp interp to_expr]; cbv [LetIn.Let_In]; eauto. Qed.
-
- Lemma interp_of_expr {t} (x : expr t)
- : expr.interp ident_interp (interp (of_expr x)) = expr.interp ident_interp x.
- Proof. induction x; cbn [expr.interp interp of_expr]; cbv [LetIn.Let_In]; eauto. Qed.
-
- Lemma to_expr_interp_related_iff {t e v}
- : interp_related (expr.interp_related ident_interp (t:=t)) e v
- <-> expr.interp_related ident_interp (UnderLets.to_expr e) v.
- Proof using Type.
- revert v; induction e; cbn [UnderLets.to_expr interp_related expr.interp_related]; try reflexivity.
- setoid_rewrite H.
- reflexivity.
- Qed.
-
- Global Instance interp_related_Proper_iff {T1 T2}
- : Proper (pointwise_relation _ (pointwise_relation _ iff) ==> eq ==> eq ==> iff) (@interp_related T1 T2) | 10.
- Proof using Type.
- cbv [pointwise_relation respectful Proper].
- intros R1 R2 HR x y ? x' y' H'; subst y y'.
- revert x'; induction x; [ apply HR | ]; cbn [interp_related].
- setoid_rewrite H; reflexivity.
- Qed.
-
- Lemma splice_interp_related_iff {A B T R x e} {v : T}
- : interp_related R (@UnderLets.splice _ ident _ A B x e) v
- <-> interp_related
- (fun xv => interp_related R (e xv))
- x v.
- Proof using Type.
- revert v; induction x; cbn [UnderLets.splice interp_related]; [ reflexivity | ].
- match goal with H : _ |- _ => setoid_rewrite H end.
- reflexivity.
- Qed.
-
- Lemma splice_list_interp_related_iff_gen {A B T R x e1 e2 base} {v : T}
- (He1e2 : forall ls', e1 ls' = e2 (base ++ ls'))
- : interp_related R (@UnderLets.splice_list _ ident _ A B x e1) v
- <-> list_rect
- (fun _ => list _ -> _ -> Prop)
- (fun ls v => interp_related R (e2 ls) v)
- (fun x xs recP ls v
- => interp_related
- (fun x' v => recP (ls ++ [x']) v)
- x
- v)
- x
- base
- v.
- Proof using Type.
- revert base v e1 e2 He1e2; induction x as [|? ? IHx]; cbn [UnderLets.splice_list interp_related list_rect]; intros.
- { intros; rewrite He1e2, ?app_nil_r; reflexivity. }
- { setoid_rewrite splice_interp_related_iff.
- apply interp_related_Proper_iff; [ | reflexivity.. ]; cbv [pointwise_relation]; intros.
- specialize (fun v => IHx (base ++ [v])).
- setoid_rewrite IHx; [ reflexivity | ].
- intros; rewrite He1e2, <- ?app_assoc; reflexivity. }
- Qed.
-
- Lemma splice_list_interp_related_iff {A B T R x e} {v : T}
- : interp_related R (@UnderLets.splice_list _ ident _ A B x e) v
- <-> list_rect
- (fun _ => list _ -> _ -> Prop)
- (fun ls v => interp_related R (e ls) v)
- (fun x xs recP ls v
- => interp_related
- (fun x' v => recP (ls ++ [x']) v)
- x
- v)
- x
- nil
- v.
- Proof using Type.
- apply splice_list_interp_related_iff_gen; reflexivity.
- Qed.
-
- Lemma splice_interp_related_of_ex {A B T T' RA RB x e} {v : T}
- : (exists ev (xv : T'),
- interp_related RA x xv
- /\ (forall x1 x2,
- RA x1 x2
- -> interp_related RB (e x1) (ev x2))
- /\ ev xv = v)
- -> interp_related RB (@UnderLets.splice _ ident _ A B x e) v.
- Proof using Type.
- revert e v; induction x; cbn [interp_related UnderLets.splice]; intros.
- all: repeat first [ progress destruct_head'_ex
- | progress destruct_head'_and
- | progress subst
- | reflexivity
- | match goal with
- | [ H : _ |- _ ] => apply H; clear H
- end ].
- do 2 eexists; repeat apply conj; [ eassumption | | ]; intros.
- { match goal with H : _ |- _ => apply H; clear H end.
- do 2 eexists; repeat apply conj; now eauto. }
- { reflexivity. }
- Qed.
-
- Lemma splice_list_interp_related_of_ex {A B T T' RA RB x e} {v : T}
- : (exists ev (xv : list T'),
- List.Forall2 (interp_related RA) x xv
- /\ (forall x1 x2,
- List.length x2 = List.length xv
- -> List.Forall2 RA x1 x2
- -> interp_related RB (e x1) (ev x2))
- /\ ev xv = v)
- -> interp_related RB (@UnderLets.splice_list _ ident _ A B x e) v.
- Proof using Type.
- revert e v; induction x as [|x xs IHxs]; cbn [interp_related UnderLets.splice_list]; intros.
- all: repeat first [ progress destruct_head'_ex
- | progress destruct_head'_and
- | progress cbn [List.length] in *
- | progress subst
- | reflexivity
- | match goal with
- | [ H : List.Forall2 _ nil ?x |- _ ] => is_var x; inversion H; clear H
- | [ H : List.Forall2 _ (cons _ _) ?x |- _ ] => is_var x; inversion H; clear H
- | [ |- List.Forall2 _ _ _ ] => constructor
- | [ H : _ |- _ ] => apply H; clear H
- end ].
- lazymatch goal with
- | [ H : forall l1 l2, length l2 = S (length _) -> Forall2 _ l1 l2 -> _ |- _ ]
- => specialize (fun l ls l' ls' (pf0 : length _ = _) pf1 pf2 => H (cons l ls) (cons l' ls') (f_equal S pf0) (Forall2_cons _ _ pf1 pf2))
- end.
- eapply splice_interp_related_of_ex; do 2 eexists; repeat apply conj;
- intros; [ eassumption | | ].
- { eapply IHxs.
- do 2 eexists; repeat apply conj; intros;
- [ eassumption | | ].
- { match goal with H : _ |- _ => eapply H; clear H end; eassumption. }
- { reflexivity. } }
- { reflexivity. }
- Qed.
-
- Lemma list_rect_interp_related {A B Pnil Pcons ls B' Pnil' Pcons' ls' R}
- (Hnil : interp_related R Pnil Pnil')
- (Hcons : forall x x',
- expr.interp_related ident_interp x x'
- -> forall l l',
- List.Forall2 (expr.interp_related ident_interp) l l'
- -> forall rec rec',
- interp_related R rec rec'
- -> interp_related R (Pcons x l rec) (Pcons' x' l' rec'))
- (Hls : List.Forall2 (expr.interp_related ident_interp (t:=A)) ls ls')
- : interp_related
- R
- (list_rect
- (fun _ : list _ => UnderLets B)
- Pnil
- Pcons
- ls)
- (list_rect
- (fun _ : list _ => B')
- Pnil'
- Pcons'
- ls').
- Proof using Type. induction Hls; cbn [list_rect] in *; auto. Qed.
-
- Lemma nat_rect_interp_related {A PO PS n A' PO' PS' n' R}
- (Hnil : interp_related R PO PO')
- (Hcons : forall n rec rec',
- interp_related R rec rec'
- -> interp_related R (PS n rec) (PS' n rec'))
- (Hn : n = n')
- : interp_related
- R
- (nat_rect (fun _ => UnderLets A) PO PS n)
- (nat_rect (fun _ => A') PO' PS' n').
- Proof using Type. subst n'; induction n; cbn [nat_rect] in *; auto. Qed.
-
- Lemma nat_rect_arrow_interp_related {A B PO PS n x A' B' PO' PS' n' x' R}
- {R' : A -> A' -> Prop}
- (Hnil : forall x x', R' x x' -> interp_related R (PO x) (PO' x'))
- (Hcons : forall n rec rec',
- (forall x x', R' x x' -> interp_related R (rec x) (rec' x'))
- -> forall x x',
- R' x x'
- -> interp_related R (PS n rec x) (PS' n rec' x'))
- (Hn : n = n')
- (Hx : R' x x')
- : interp_related
- R
- (nat_rect (fun _ => A -> UnderLets B) PO PS n x)
- (nat_rect (fun _ => A' -> B') PO' PS' n' x').
- Proof using Type. subst n'; revert x x' Hx; induction n; cbn [nat_rect] in *; auto. Qed.
-
- Lemma interp_related_Proper_impl_same_UnderLets {A B B' R1 R2 e v f}
- (HR : forall e v, (R1 e v : Prop) -> (R2 e (f v) : Prop))
- : @interp_related A B R1 e v
- -> @interp_related A B' R2 e (f v).
- Proof using Type.
- revert f v HR; induction e; cbn [interp_related]; [ now eauto | ]; intros F v HR H'.
- destruct H' as [fv H']; exists (fun ev => F (fv ev)).
- repeat first [ let x := fresh "x" in destruct H' as [x H']; exists x
- | let x := fresh "x" in intro x; specialize (H' x)
- | let H := fresh "H" in destruct H' as [H H']; split; [ exact H || now subst | ]
- | let H := fresh "H" in destruct H' as [H' H]; split; [ | exact H || now subst ] ].
- auto.
- Qed.
- End for_interp.
-
- Section for_interp2.
- Context {base_interp1 base_interp2 : base_type -> Type}
- {ident_interp1 : forall t, ident t -> type.interp base_interp1 t}
- {ident_interp2 : forall t, ident t -> type.interp base_interp2 t}.
-
- Lemma wf_interp_Proper {T1 T2}
- {P : list { t : type & type.interp base_interp1 t * type.interp base_interp2 t }%type -> T1 -> T2 -> Prop}
- {G v1 v2}
- (Hwf : @wf _ _ T1 T2 P G v1 v2)
- : exists seg, P (seg ++ G) (interp ident_interp1 v1) (interp ident_interp2 v2).
- Proof using Type.
- induction Hwf; [ exists nil; cbn [List.app]; assumption | ].
- let H := match goal with H : forall v1 v2, ex _ |- _ => H end in
- edestruct H as [seg ?]; eexists (seg ++ [_]).
- rewrite <- List.app_assoc; cbn [List.app].
- eassumption.
- Qed.
- End for_interp2.
- End with_ident.
-
- Section reify.
- Local Notation type := (type.type base.type).
- Local Notation expr := (@expr.expr base.type ident).
- Local Notation UnderLets := (@UnderLets.UnderLets base.type ident).
-
- Section with_var.
- Context {var1 var2 : type -> Type}.
- Local Notation expr1 := (@expr.expr base.type ident var1).
- Local Notation expr2 := (@expr.expr base.type ident var2).
- Local Notation UnderLets1 := (@UnderLets.UnderLets base.type ident var1).
- Local Notation UnderLets2 := (@UnderLets.UnderLets base.type ident var2).
-
- Local Ltac wf_reify_and_let_binds_base_cps_t Hk :=
- repeat first [ lazymatch goal with
- | [ H : expr.wf _ ?e1 ?e2, H' : reflect_list ?e1 = Some _, H'' : reflect_list ?e2 = None |- _ ]
- => apply expr.wf_reflect_list in H; rewrite H', H'' in H; exfalso; clear -H; intuition congruence
- | [ H : expr.wf _ ?e1 ?e2, H' : reflect_list ?e2 = Some _, H'' : reflect_list ?e1 = None |- _ ]
- => apply expr.wf_reflect_list in H; rewrite H', H'' in H; exfalso; clear -H; intuition congruence
- | [ H : expr.wf _ (reify_list _) (reify_list _) |- _ ] => apply expr.wf_reify_list in H
- end
- | progress subst
- | progress destruct_head' False
- | progress expr.inversion_wf_constr
- | progress expr.inversion_expr
- | progress expr.invert_subst
- | progress destruct_head'_sig
- | progress destruct_head'_ex
- | progress destruct_head'_and
- | progress type.inversion_type
- | progress base.type.inversion_type
- | progress cbn [invert_Var invert_Literal ident.invert_Literal eq_rect f_equal f_equal2 type.decode fst snd projT1 projT2 invert_pair Option.bind combine list_rect length] in *
- | progress cbv [type.try_transport type.try_transport_cps CPSNotations.cps_option_bind CPSNotations.cpsreturn CPSNotations.cpsbind CPSNotations.cpscall type.try_make_transport_cps id] in *
- | rewrite base.try_make_transport_cps_correct in *
- | progress type_beq_to_eq
- | discriminate
- | congruence
- | apply Hk
- | exists nil; reflexivity
- | eexists (cons _ nil); reflexivity
- | rewrite app_assoc; eexists; reflexivity
- | progress wf_safe_t
- | match goal with
- | [ H : _ = _ :> ident _ |- _ ] => inversion H; clear H
- end
- | progress inversion_option
- | progress break_innermost_match_hyps
- | progress expr.inversion_wf_one_constr
- | progress expr.invert_match_step
- | match goal with |- wf _ _ _ _ => constructor end
- | match goal with
- | [ H : context[wf _ _ _ _] |- wf _ _ _ _ ] => apply H; eauto with nocore
- end
- | progress wf_unsafe_t_step
- | match goal with
- | [ H : context[match Compilers.reify_list ?ls with _ => _ end] |- _ ]
- => is_var ls; destruct ls; rewrite ?expr.reify_list_cons, ?expr.reify_list_nil in H
- | [ H : SubstVarLike.is_recursively_var_or_ident _ _ = _ |- _ ] => clear H
- | [ H : forall x y, @?A x y \/ @?B x y -> @?C x y |- _ ]
- => pose proof (fun x y pf => H x y (or_introl pf));
- pose proof (fun x y pf => H x y (or_intror pf));
- clear H
- end ].
-
- Lemma wf_reify_and_let_binds_base_cps {t : base.type} {T1 T2} (e1 : expr1 (type.base t)) (e2 : expr2 (type.base t))
- (k1 : expr1 (type.base t) -> UnderLets1 T1) (k2 : expr2 (type.base t) -> UnderLets2 T2)
- (P : _ -> _ -> _ -> Prop) G
- (Hwf : expr.wf G e1 e2)
- (Hk : forall G' e1 e2, (exists seg, G' = seg ++ G) -> expr.wf G' e1 e2 -> wf P G' (k1 e1) (k2 e2))
- : wf P G (reify_and_let_binds_base_cps e1 T1 k1) (reify_and_let_binds_base_cps e2 T2 k2).
- Proof.
- revert dependent G; induction t; cbn [reify_and_let_binds_base_cps]; intros;
- try (cbv [SubstVarLike.is_var_fst_snd_pair_opp_cast] in *; erewrite !SubstVarLike.wfT_is_recursively_var_or_ident by eassumption);
- break_innermost_match; wf_reify_and_let_binds_base_cps_t Hk.
- all: repeat match goal with H : list (sigT _) |- _ => revert dependent H end.
- all: revert dependent k1; revert dependent k2.
- all: lazymatch goal with
- | [ H : length ?l1 = length ?l2 |- _ ]
- => is_var l1; is_var l2; revert dependent l2; induction l1; intro l2; destruct l2; intros
- end;
- wf_reify_and_let_binds_base_cps_t Hk.
- Qed.
-
- Lemma wf_let_bind_return {t} (e1 : expr1 t) (e2 : expr2 t)
- G
- (Hwf : expr.wf G e1 e2)
- : expr.wf G (let_bind_return e1) (let_bind_return e2).
- Proof.
- revert dependent G; induction t; intros; cbn [let_bind_return]; cbv [invert_Abs];
- wf_safe_t;
- expr.invert_match; expr.inversion_wf; try solve [ wf_t ].
- { apply wf_to_expr.
- pose (P := fun t => { e1e2 : expr1 t * expr2 t | expr.wf G (fst e1e2) (snd e1e2) }).
- pose ((exist _ (e1, e2) Hwf) : P _) as pkg.
- change e1 with (fst (proj1_sig pkg)).
- change e2 with (snd (proj1_sig pkg)).
- clearbody pkg; clear Hwf e1 e2.
- type.generalize_one_eq_var pkg; subst P; destruct pkg as [ [e1 e2] Hwf ].
- cbn [fst snd proj1_sig proj2_sig] in *.
- repeat match goal with
- | [ |- context[proj1_sig (rew [fun t => @sig (@?A t) (@?P t)] ?pf in exist ?P0 ?x ?p)] ]
- => progress replace (proj1_sig (rew pf in exist P0 x p)) with (rew [A] pf in x) by (case pf; reflexivity)
- | [ |- context[fst (rew [fun t => @prod (@?A t) (@?B t)] ?pf in pair ?x ?y)] ]
- => progress replace (fst (rew pf in pair x y)) with (rew [A] pf in x) by (case pf; reflexivity)
- | [ |- context[snd (rew [fun t => @prod (@?A t) (@?B t)] ?pf in pair ?x ?y)] ]
- => progress replace (fst (rew pf in pair x y)) with (rew [B] pf in y) by (case pf; reflexivity)
- end.
- assert (H' : t = match t' with type.base t' => t' | _ => t end) by (subst; reflexivity).
- revert pf.
- rewrite H'; clear H'.
- induction Hwf; break_innermost_match; break_innermost_match_hyps;
- repeat first [ progress intros
- | progress type.inversion_type
- | progress base.type.inversion_type
- | progress wf_safe_t
- | progress cbn [of_expr fst snd splice eq_rect type.decode f_equal] in *
- | match goal with
- | [ H : forall pf : ?x = ?x, _ |- _ ] => specialize (H eq_refl)
- | [ H : forall x y (pf : ?a = ?a), _ |- _ ] => specialize (fun x y => H x y eq_refl)
- | [ |- wf _ _ _ _ ] => constructor
- end
- | solve [ eauto ]
- | apply wf_reify_and_let_binds_base_cps ]. }
- Qed.
- End with_var.
-
- Section with_cast.
- Context (cast_outside_of_range : ZRange.zrange -> BinInt.Z -> BinInt.Z).
- Local Notation ident_interp := (@ident.gen_interp cast_outside_of_range).
- Local Notation interp := (@expr.interp _ _ _ (@ident_interp)).
- Local Notation Interp := (@expr.Interp _ _ _ (@ident_interp)).
-
- Lemma interp_reify_and_let_binds_base_cps
- {t e T k}
- (P : T -> Prop)
- (Hk : forall e', interp e' = interp e -> P (UnderLets.interp (@ident_interp) (k e')))
- : P (UnderLets.interp (@ident_interp) (@reify_and_let_binds_base_cps _ t e T k)).
- Proof.
- revert T k P Hk; induction t; cbn [reify_and_let_binds_base_cps]; intros;
- break_innermost_match;
- expr.invert_subst; cbn [type.related UnderLets.interp fst snd expr.interp ident_interp] in *; subst; eauto;
- repeat first [ progress intros
- | reflexivity
- | progress cbn [expr.interp ident_interp List.map]
- | apply (f_equal2 (@pair _ _))
- | apply (f_equal2 (@cons _))
- | match goal with
- | [ H : _ |- _ ] => apply H; clear H
- | [ H : SubstVarLike.is_var_fst_snd_pair_opp_cast (reify_list _) = _ |- _ ] => clear H
- | [ H : context[interp (reify_list _)] |- _ ]
- => rewrite expr.interp_reify_list in H
- | [ |- ?Q (UnderLets.interp _ (list_rect ?P ?X ?Y ?ls ?k)) ]
- => is_var ls; is_var k;
- revert dependent k; induction ls; cbn [list_rect];
- [ | generalize dependent (list_rect P X Y) ]; intros
- end ].
- Qed.
-
- Lemma interp_reify_and_let_binds_base
- {t e}
- : interp (UnderLets.interp (@ident_interp) (@reify_and_let_binds_base_cps _ t e _ UnderLets.Base))
- = interp e.
- Proof.
- eapply interp_reify_and_let_binds_base_cps; cbn [UnderLets.interp].
- trivial.
- Qed.
-
- Local Ltac interp_to_expr_reify_and_let_binds_base_cps_t Hk :=
- repeat first [ progress subst
- | progress destruct_head' False
- | progress destruct_head'_and
- | progress destruct_head' iff
- | progress specialize_by_assumption
- | progress expr.inversion_wf_constr
- | progress expr.inversion_expr
- | progress expr.invert_subst
- | progress destruct_head'_sig
- | progress destruct_head'_ex
- | progress destruct_head'_and
- | progress type.inversion_type
- | progress base.type.inversion_type
- | progress cbn [invert_Var invert_Literal ident.invert_Literal eq_rect f_equal f_equal2 type.decode fst snd projT1 projT2 invert_pair Option.bind to_expr expr.interp ident.interp ident.gen_interp type.eqv length list_rect combine In] in *
- | progress cbv [type.try_transport type.try_transport_cps CPSNotations.cps_option_bind CPSNotations.cpsreturn CPSNotations.cpsbind CPSNotations.cpscall type.try_make_transport_cps id] in *
- | rewrite base.try_make_transport_cps_correct in *
- | progress type_beq_to_eq
- | discriminate
- | congruence
- | apply Hk
- | exists nil; reflexivity
- | eexists (cons _ nil); reflexivity
- | rewrite app_assoc; eexists; reflexivity
- | rewrite expr.reify_list_cons
- | rewrite expr.reify_list_nil
- | progress interp_safe_t
- | match goal with
- | [ H : _ = _ :> ident _ |- _ ] => inversion H; clear H
- | [ H : forall t v1 v2, In _ _ -> _ == _, H' : In _ _ |- _ ] => apply H in H'
- end
- | progress inversion_option
- | progress break_innermost_match_hyps
- | progress expr.inversion_wf_one_constr
- | progress expr.invert_match_step
- | match goal with
- | [ |- ?R (expr.interp _ ?e1) (expr.interp _ ?e2) ]
- => solve [ eapply (@expr.wf_interp_Proper _ _ _ e1 e2); eauto ]
- | [ H : context[reflect_list (reify_list _)] |- _ ] => rewrite expr.reflect_reify_list in H
- | [ H : forall x y, @?A x y \/ @?B x y -> @?C x y |- _ ]
- => pose proof (fun x y pf => H x y (or_introl pf));
- pose proof (fun x y pf => H x y (or_intror pf));
- clear H
- end
- | progress interp_unsafe_t_step
- | match goal with
- | [ H : expr.wf _ (reify_list _) ?e |- _ ]
- => is_var e; destruct (reflect_list e) eqn:?; expr.invert_subst;
- [ rewrite expr.wf_reify_list in H | apply expr.wf_reflect_list in H ]
- | [ H : SubstVarLike.is_recursively_var_or_ident _ _ = _ |- _ ] => clear H
- | [ H : context[expr.interp _ _ = _] |- expr.interp _ (to_expr _) = ?k2 _ ]
- => erewrite H; clear H;
- [ match goal with
- | [ |- ?k (expr.interp ?ii ?e) = ?k' ?v ]
- => has_evar e;
- let p := fresh in
- set (p := expr.interp ii e);
- match v with
- | context G[expr.interp ii ?e']
- => unify e e'; let v' := context G[p] in change (k p = k' v')
- end;
- clearbody p; reflexivity
- end
- | .. ]
- end ].
-
- Lemma interp_to_expr_reify_and_let_binds_base_cps {t : base.type} {t' : base.type} (e1 : expr (type.base t)) (e2 : expr (type.base t))
- G
- (HG : forall t v1 v2, List.In (existT _ t (v1, v2)) G -> v1 == v2)
- (Hwf : expr.wf G e1 e2)
- (k1 : expr (type.base t) -> UnderLets _ (expr (type.base t')))
- (k2 : base.interp t -> base.interp t')
- (Hk : forall e1 v, interp e1 == v -> interp (to_expr (k1 e1)) == k2 v)
- : interp (to_expr (reify_and_let_binds_base_cps e1 _ k1)) == k2 (interp e2).
- Proof.
- revert dependent G; revert dependent t'; induction t; cbn [reify_and_let_binds_base_cps]; intros;
- try (cbv [SubstVarLike.is_var_fst_snd_pair_opp_cast] in *; erewrite !SubstVarLike.wfT_is_recursively_var_or_ident by eassumption);
- break_innermost_match; interp_to_expr_reify_and_let_binds_base_cps_t Hk.
- all: repeat match goal with H : list (sigT _) |- _ => revert dependent H end.
- all: revert dependent k1; revert dependent k2.
- all: lazymatch goal with
- | [ H : length ?l1 = length ?l2 |- _ ]
- => is_var l1; is_var l2; revert dependent l2; induction l1; intro l2; destruct l2; intros
- end;
- interp_to_expr_reify_and_let_binds_base_cps_t Hk.
- Qed.
-
- Lemma interp_let_bind_return {t} (e1 e2 : expr t)
- G
- (HG : forall t v1 v2, List.In (existT _ t (v1, v2)) G -> v1 == v2)
- (Hwf : expr.wf G e1 e2)
- : interp (let_bind_return e1) == interp e2.
- Proof.
- revert dependent G; induction t; intros; cbn [let_bind_return type.eqv expr.interp] in *; cbv [invert_Abs respectful] in *;
- repeat first [ progress wf_safe_t
- | progress expr.invert_subst
- | progress expr.invert_match
- | progress expr.inversion_wf
- | progress break_innermost_match_hyps
- | progress destruct_head' False
- | solve [ wf_t ]
- | match goal with
- | [ H : _ |- expr.interp _ (let_bind_return ?e0) == expr.interp _ ?e ?v ]
- => eapply (H e0 (e @ $v)%expr (cons _ _)); [ .. | solve [ wf_t ] ]; solve [ wf_t ]
- | [ H : _ |- expr.interp _ (let_bind_return ?e0) == expr.interp _ ?e ?v ]
- => cbn [expr.interp]; eapply H; [ | solve [ wf_t ] ]; solve [ wf_t ]
- end ];
- [].
- { pose (P := fun t => { e1e2 : expr t * expr t | expr.wf G (fst e1e2) (snd e1e2) }).
- pose ((exist _ (e1, e2) Hwf) : P _) as pkg.
- change e1 with (fst (proj1_sig pkg)).
- change e2 with (snd (proj1_sig pkg)).
- clearbody pkg; clear Hwf e1 e2.
- type.generalize_one_eq_var pkg; subst P; destruct pkg as [ [e1 e2] Hwf ].
- cbn [fst snd proj1_sig proj2_sig] in *.
- repeat match goal with
- | [ |- context[proj1_sig (rew [fun t => @sig (@?A t) (@?P t)] ?pf in exist ?P0 ?x ?p)] ]
- => progress replace (proj1_sig (rew pf in exist P0 x p)) with (rew [A] pf in x) by (case pf; reflexivity)
- | [ |- context[fst (rew [fun t => @prod (@?A t) (@?B t)] ?pf in pair ?x ?y)] ]
- => progress replace (fst (rew pf in pair x y)) with (rew [A] pf in x) by (case pf; reflexivity)
- | [ |- context[snd (rew [fun t => @prod (@?A t) (@?B t)] ?pf in pair ?x ?y)] ]
- => progress replace (fst (rew pf in pair x y)) with (rew [B] pf in y) by (case pf; reflexivity)
- end.
- assert (H' : t = match t' with type.base t' => t' | _ => t end) by (subst; reflexivity).
- revert pf.
- rewrite H'; clear H'.
- induction Hwf; break_innermost_match; break_innermost_match_hyps;
- repeat first [ progress intros
- | progress type.inversion_type
- | progress base.type.inversion_type
- | progress wf_safe_t
- | progress cbn [of_expr fst snd splice eq_rect type.decode f_equal to_expr] in *
- | match goal with
- | [ H : forall pf : ?x = ?x, _ |- _ ] => specialize (H eq_refl)
- | [ H : forall x (pf : ?a = ?a), _ |- _ ] => specialize (fun x => H x eq_refl)
- | [ H : forall x y (pf : ?a = ?a), _ |- _ ] => specialize (fun x y => H x y eq_refl)
- | [ H : forall x y z (pf : ?a = ?a), _ |- _ ] => specialize (fun x y z => H x y z eq_refl)
- | [ |- context[(expr_let x := _ in _)%expr] ] => progress cbn [expr.interp]; cbv [LetIn.Let_In]
- | [ H : context[expr.interp _ _ = expr.interp _ _] |- expr.interp _ _ = expr.interp _ _ ]
- => eapply H; eauto with nocore
- end
- | solve [ eauto ]
- | solve [ eapply expr.wf_interp_Proper; eauto ] ].
- all: eapply interp_to_expr_reify_and_let_binds_base_cps with (k1:=Base) (k2:=(fun x => x)); eauto; wf_safe_t. }
- Qed.
-
- Ltac recurse_interp_related_step :=
- let do_replace v :=
- ((tryif is_evar v then fail else idtac);
- let v' := open_constr:(_) in
- let v'' := fresh in
- cut (v = v'); [ generalize v; intros v'' ?; subst v'' | symmetry ]) in
- match goal with
- | _ => progress cbv [expr.interp_related] in *
- | _ => progress cbn [type.interp]
- | [ |- context[(fst ?x, snd ?x)] ] => progress eta_expand
- | [ |- context[match ?x with pair a b => _ end] ] => progress eta_expand
- | [ |- expr.interp_related_gen ?ident_interp ?R ?f ?v ]
- => do_replace v
- | [ |- exists (fv : ?T1 -> ?T2) (ev : ?T1),
- _ /\ _ /\ fv ev = ?x ]
- => first [ do_replace x
- | is_evar x; do 2 eexists; repeat apply conj; [ | | reflexivity ] ]
- | _ => progress intros
- | [ |- expr.interp_related_gen _ _ _ ?ev ] => is_evar ev; eassumption
- | [ |- expr.interp_related_gen _ _ (?f @ ?x) ?ev ]
- => is_evar ev;
- let fh := fresh in
- let xh := fresh in
- set (fh := f); set (xh := x); cbn [expr.interp_related_gen]; subst fh xh;
- do 2 eexists; repeat apply conj; [ | | reflexivity ]
- | [ |- expr.interp_related_gen _ _ (expr.Abs ?f) _ ]
- => let fh := fresh in set (fh := f); cbn [expr.interp_related_gen]; subst fh
- | [ |- expr.interp_related_gen _ _ (expr.Ident ?idc) ?ev ]
- => is_evar ev;
- cbn [expr.interp_related_gen]; apply ident.gen_interp_Proper; reflexivity
- | [ H : ?x == _ |- ?x == _ ] => exact H
- | [ |- ?x = ?y ] => tryif first [ has_evar x | has_evar y ] then fail else (progress subst)
- | [ |- ?x = ?x ] => tryif has_evar x then fail else reflexivity
- | [ |- ?ev = _ ] => is_evar ev; reflexivity
- | [ |- _ = ?ev ] => is_evar ev; reflexivity
- end.
-
- Local Ltac do_interp_related :=
- repeat first [ progress cbv beta
- | progress recurse_interp_related_step
- | eassumption
- | do 2 eexists; repeat apply conj; intros
- | match goal with
- | [ H : _ |- _ ] => apply H; clear H; solve [ do_interp_related ]
- end ].
-
- Lemma reify_and_let_binds_base_interp_related_of_ex {t e T k T' R} {v : T'}
- : (exists kv xv,
- expr.interp_related (@ident_interp) e xv
- /\ (forall x1 x2,
- expr.interp_related (@ident_interp) x1 x2
- -> interp_related (@ident_interp) R (k x1) (kv x2))
- /\ kv xv = v)
- -> interp_related (@ident_interp) R (@reify_and_let_binds_base_cps _ t e T k) v.
- Proof using Type.
- cbv [expr.interp_related]; revert T T' k R v; induction t.
- all: repeat first [ progress cbn [expr.interp_related_gen interp_related reify_and_let_binds_base_cps fst snd] in *
- | progress cbv [expr.interp_related] in *
- | progress intros
- | assumption
- | progress destruct_head'_ex
- | progress destruct_head'_and
- | break_innermost_match_step
- | progress expr.invert_subst
- | solve [ eauto ]
- | solve [ do_interp_related ]
- | match goal with
- | [ H : expr.interp_related_gen ?ii _ (reify_list ?ls1) ?ls2 |- _ ] => change (expr.interp_related ii (reify_list ls1) ls2) in H; rewrite expr.reify_list_interp_related_iff in H
- end ].
- all: match goal with
- | [ H : SubstVarLike.is_var_fst_snd_pair_opp_cast _ = _ |- _ ] => clear H
- end.
- all: lazymatch goal with
- | [ H : List.Forall2 _ ?ls1 ?ls2
- |- interp_related _ _
- (list_rect ?Pv ?Nv ?Cv ?ls1 ?k)
- (?f ?ls2) ]
- => let P := fresh "P" in
- let N := fresh "N" in
- let C := fresh "C" in
- is_var k; is_var f; is_var ls1; is_var ls2;
- set (P:=Pv); set (N:=Nv); set (C:=Cv);
- revert dependent f; intro f; revert dependent k; intro k; revert f k;
- induction H; cbn [list_rect]; intros
- end.
- all: repeat match goal with
- | [ F := ?f |- _ ]
- => match goal with
- | [ |- context G[F ?x] ]
- => let G' := context G[f x] in
- change G'; cbv beta
- end
- | [ H : forall x1 x2, ?R x1 x2 -> ?R' (?f1 x1) (?f2 x2) |- ?R' (?f1 _) (?f2 _) ]
- => apply H; clear H
- | [ |- expr.interp_related_gen _ _ _ nil ] => reflexivity
- | [ H : _ |- interp_related _ _ (reify_and_let_binds_base_cps _ _ _) _ ] => apply H
- | [ |- exists kv xv, _ /\ _ /\ kv xv = ?f (?x :: ?xs) ]
- => exists (fun x' => f (x' :: xs)), x; repeat apply conj; [ | | reflexivity ]
- | _ => assumption
- | _ => progress intros
- | [ IH : (forall k k', _ -> ?R (list_rect ?P ?N ?C ?ls1 k') (k ?ls2))
- |- ?R (list_rect ?P ?N ?C ?ls1 ?k'v) ?RHS ]
- => let kv := match (eval pattern ls2 in RHS) with ?kv _ => kv end in
- apply (IH kv k'v); clear IH
- | _ => solve [ do_interp_related ]
- end.
- Qed.
-
- Lemma reify_and_let_binds_base_interp_related {t e v}
- : expr.interp_related (@ident_interp) e v
- -> interp_related (@ident_interp) (expr.interp_related (@ident_interp)) (@reify_and_let_binds_base_cps _ t e _ Base) v.
- Proof using Type.
- intro; eapply reify_and_let_binds_base_interp_related_of_ex.
- eexists id, _; eauto.
- Qed.
-
- Lemma Interp_LetBindReturn {t} (e : expr.Expr t) (Hwf : expr.Wf e) : Interp (LetBindReturn e) == Interp e.
- Proof.
- apply interp_let_bind_return with (G:=nil); cbn [List.In]; eauto; tauto.
- Qed.
- End with_cast.
-
- Lemma Wf_LetBindReturn {t} (e : expr.Expr t) (Hwf : expr.Wf e) : expr.Wf (LetBindReturn e).
- Proof. intros ??; apply wf_let_bind_return, Hwf. Qed.
- End reify.
- End UnderLets.
-
- Hint Resolve UnderLets.Wf_LetBindReturn : wf.
- Hint Rewrite @UnderLets.Interp_LetBindReturn : interp.
-End Compilers.