diff options
Diffstat (limited to 'src/Compilers/MapCastInterp.v')
-rw-r--r-- | src/Compilers/MapCastInterp.v | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/src/Compilers/MapCastInterp.v b/src/Compilers/MapCastInterp.v new file mode 100644 index 000000000..bbf4581b5 --- /dev/null +++ b/src/Compilers/MapCastInterp.v @@ -0,0 +1,291 @@ +Require Import Crypto.Compilers.Syntax. +Require Import Crypto.Compilers.Wf. +Require Import Crypto.Compilers.SmartMap. +Require Import Crypto.Compilers.ExprInversion. +Require Import Crypto.Compilers.MapCast. +Require Import Crypto.Compilers.Relations. +Require Import Crypto.Compilers.WfProofs. +Require Import Crypto.Compilers.WfInversion. +Require Import Crypto.Util.Sigma. +Require Import Crypto.Util.Prod. +Require Import Crypto.Util.Option. +Require Import Crypto.Util.Tactics.BreakMatch. +Require Import Crypto.Util.Tactics.SpecializeBy. +Require Import Crypto.Util.Tactics.DestructHead. +Require Import Crypto.Util.Tactics.SplitInContext. +Require Import Crypto.Util.Tactics.RewriteHyp. + +Local Open Scope ctype_scope. +Local Open Scope expr_scope. +Section language. + Context {base_type_code : Type} + {interp_base_type1 : base_type_code -> Type} + {interp_base_type2 : base_type_code -> Type} + {op : flat_type base_type_code -> flat_type base_type_code -> Type} + (interp_op1 : forall src dst, op src dst -> interp_flat_type interp_base_type1 src -> interp_flat_type interp_base_type1 dst) + (interp_op2 : forall src dst, op src dst -> interp_flat_type interp_base_type2 src -> interp_flat_type interp_base_type2 dst) + (failv : forall {var t}, @exprf base_type_code op var (Tbase t)). + Context (transfer_op : forall ovar src1 dst1 src2 dst2 + (opc1 : op src1 dst1) + (opc2 : op src2 dst2) + (args1' : @exprf base_type_code op ovar src1) + (args2 : interp_flat_type interp_base_type2 src2), + @exprf base_type_code op ovar dst1). + + Context (R' : forall t, interp_base_type1 t -> interp_base_type2 t -> Prop). + Local Notation R x y := (interp_flat_type_rel_pointwise R' x y). + Section gen_Prop. + Context (P : Type) (and : P -> P -> P) (True : P). + Context (bound_is_good : forall t, interp_base_type2 t -> P). + Local Notation bounds_are_good + := (@interp_flat_type_rel_pointwise1_gen_Prop _ _ P and True bound_is_good _). + Fixpoint bounds_are_recursively_good_gen_Prop {t} (e : exprf base_type_code op t) : P + := match e with + | LetIn tx ex tC eC + => and (@bounds_are_recursively_good_gen_Prop tx ex) + (@bounds_are_recursively_good_gen_Prop tC (eC (interpf interp_op2 ex))) + | Op t1 tR opc args as e' + => and (@bounds_are_recursively_good_gen_Prop _ args) + (bounds_are_good (interpf interp_op2 e')) + | TT => True + | Var t v => bound_is_good _ v + | Pair tx ex ty ey + => and (@bounds_are_recursively_good_gen_Prop _ ex) + (@bounds_are_recursively_good_gen_Prop _ ey) + end. + End gen_Prop. + Definition bounds_are_recursively_goodb + := bounds_are_recursively_good_gen_Prop bool andb true. + Global Arguments bounds_are_recursively_goodb _ {_} !_ / . + Definition bounds_are_recursively_good + := @bounds_are_recursively_good_gen_Prop Prop and True. + Global Arguments bounds_are_recursively_good _ {_} !_ / . + Lemma bounds_are_recursively_good_iff_bool + R t x + : is_true (@bounds_are_recursively_goodb R t x) + <-> @bounds_are_recursively_good (fun t x => is_true (R t x)) t x. + Proof using Type. + unfold is_true. + clear; induction x; simpl in *; rewrite ?Bool.andb_true_iff; + try setoid_rewrite interp_flat_type_rel_pointwise1_gen_Prop_iff_bool; + rewrite_hyp ?*; intuition congruence. + Qed. + Definition bounds_are_recursively_good_gen_Prop_iff_bool + : forall R t x, + is_true (@bounds_are_recursively_good_gen_Prop bool _ _ R t x) + <-> @bounds_are_recursively_good_gen_Prop Prop _ _ (fun t x => is_true (R t x)) t x + := bounds_are_recursively_good_iff_bool. + + Context (bound_is_good : forall t, interp_base_type2 t -> Prop). + Local Notation bounds_are_good + := (@interp_flat_type_rel_pointwise1 _ _ bound_is_good). + Lemma bounds_are_good_when_recursively_good {t} e + : @bounds_are_recursively_good bound_is_good t e -> bounds_are_good (interpf interp_op2 e). + Proof using Type. + induction e; simpl; unfold LetIn.Let_In; intuition auto. + Qed. + Local Hint Resolve bounds_are_good_when_recursively_good. + + Local Notation G_invariant_holds G + := (forall t x x', + List.In (existT _ t (x, x')%core) G -> R' t x x') + (only parsing). + + Context (interpf_transfer_op + : forall G t tR opc ein eout ebounds, + wff G ein ebounds + -> G_invariant_holds G + -> interpf interp_op1 ein = interpf interp_op1 eout + -> bounds_are_recursively_good bound_is_good ebounds + -> bounds_are_good (interp_op2 t tR opc (interpf interp_op2 ebounds)) + -> interpf interp_op1 (transfer_op interp_base_type1 t tR t tR opc opc eout (interpf interp_op2 ebounds)) + = interpf interp_op1 (Op opc ein)). + + Context (R_transfer_op + : forall G t tR opc ein eout ebounds, + wff G ein ebounds + -> G_invariant_holds G + -> interpf interp_op1 ein = interpf interp_op1 eout + -> bounds_are_recursively_good bound_is_good ebounds + -> bounds_are_good (interp_op2 t tR opc (interpf interp_op2 ebounds)) + -> R (interpf interp_op1 (transfer_op interp_base_type1 t tR t tR opc opc eout (interpf interp_op2 ebounds))) + (interpf interp_op2 (Op opc ebounds))). + + Local Notation mapf_interp_cast + := (@mapf_interp_cast + base_type_code base_type_code interp_base_type2 + op op interp_op2 failv + transfer_op). + Local Notation map_interp_cast + := (@map_interp_cast + base_type_code base_type_code interp_base_type2 + op op interp_op2 failv + transfer_op). + Local Notation MapInterpCast + := (@MapInterpCast + base_type_code interp_base_type2 + op interp_op2 failv + transfer_op). + + (* Local *) Hint Resolve <- List.in_app_iff. + Local Hint Resolve (fun t T => @interp_flat_type_rel_pointwise_flatten_binding_list _ _ _ t T R'). + + Local Ltac break_t + := first [ progress subst + | progress inversion_wf + | progress invert_expr_subst + | progress inversion_sigma + | progress inversion_prod + | progress destruct_head sig + | progress destruct_head sigT + | progress destruct_head ex + | progress destruct_head and + | progress destruct_head prod + | progress split_and + | progress break_match_hyps ]. + + Local Ltac fin_False := + lazymatch goal with + | [ H : False |- _ ] => exfalso; assumption + end. + + Local Ltac fin_t0 := + solve [ constructor; eauto + | eauto + | auto + | hnf; auto ]. + + Local Ltac handle_list_t := + match goal with + | _ => progress cbv [LetIn.Let_In duplicate_types] in * + | [ H : List.In _ (_ ++ _) |- _ ] => apply List.in_app_or in H + | [ H : List.In _ (List.map _ _) |- _ ] + => rewrite List.in_map_iff in H + | _ => rewrite <- flatten_binding_list_flatten_binding_list2 + | [ H : appcontext[flatten_binding_list2] |- _ ] + => rewrite <- flatten_binding_list_flatten_binding_list2 in H + | [ H : context[flatten_binding_list (SmartVarfMap _ _) (SmartVarfMap _ _)] |- _ ] + => rewrite flatten_binding_list_SmartVarfMap in H + | [ H : context[flatten_binding_list2 (SmartVarfMap _ _) (SmartVarfMap _ _)] |- _ ] + => rewrite flatten_binding_list2_SmartVarfMap in H + | [ H : context[flatten_binding_list2 (SmartVarfMap _ _) _] |- _ ] + => rewrite flatten_binding_list2_SmartVarfMap1 in H + | [ H : context[flatten_binding_list2 _ (SmartVarfMap _ _)] |- _ ] + => rewrite flatten_binding_list2_SmartVarfMap2 in H + | _ => rewrite <- flatten_binding_list_flatten_binding_list2 + | _ => rewrite List.in_map_iff + | [ H : context[List.In _ (_ ++ _)] |- _ ] + => setoid_rewrite List.in_app_iff in H + end. + + Local Ltac wff_t := + match goal with + | [ |- wff _ _ _ ] => constructor + | [ H : _ |- wff _ (mapf_interp_cast _ _ _) (mapf_interp_cast _ _ _) ] + => eapply H; eauto; []; clear H + | _ => solve [ eauto using wff_in_impl_Proper ] + end. + + Local Ltac R_t := + match goal with + | [ |- R' _ _ _ ] => eapply interp_flat_type_rel_pointwise_flatten_binding_list; eauto + | [ H : forall x y, _ -> R _ _ |- R _ _ ] => apply H; eauto; [] + | [ H : forall x y, _ -> _ -> R _ _ |- R _ _ ] => apply H; eauto; [] + end. + + Local Ltac misc_t := + match goal with + | _ => progress specialize_by eauto + | [ |- exists _, _ ] + => eexists (existT _ _ _) + | [ |- _ /\ _ ] => split + | [ H : _ = _ |- _ ] => rewrite H + | [ H : ?x = _, H' : context[?x] |- _ ] => rewrite H in H' + | [ H : forall x y, _ -> _ -> _ = _ |- interpf _ _ = interpf _ _ ] + => apply H + end. + + Local Ltac t_step := + first [ intro + | fin_False + | progress break_t + | fin_t0 + | progress simpl in * + | wff_t + | handle_list_t + | progress destruct_head' or + | misc_t + | R_t ]. + + Lemma interpf_mapf_interp_cast_and_rel + G + {t1} e1 ebounds + (Hgood : bounds_are_recursively_good bound_is_good ebounds) + (HG : G_invariant_holds G) + (Hwf : wff G e1 ebounds) + : interpf interp_op1 (@mapf_interp_cast interp_base_type1 t1 e1 t1 ebounds) + = interpf interp_op1 e1 + /\ R (interpf interp_op1 (@mapf_interp_cast interp_base_type1 t1 e1 t1 ebounds)) + (interpf interp_op2 ebounds). + Proof using R_transfer_op interpf_transfer_op. induction Hwf; repeat t_step. Qed. + + Local Hint Resolve interpf_mapf_interp_cast_and_rel. + + Lemma interpf_mapf_interp_cast + G + {t1} e1 ebounds + (Hgood : bounds_are_recursively_good bound_is_good ebounds) + (HG : G_invariant_holds G) + (Hwf : wff G e1 ebounds) + : interpf interp_op1 (@mapf_interp_cast interp_base_type1 t1 e1 t1 ebounds) + = interpf interp_op1 e1. + Proof using R_transfer_op interpf_transfer_op. eapply interpf_mapf_interp_cast_and_rel; eassumption. Qed. + + Lemma interp_map_interp_cast_and_rel + {t1} e1 ebounds + args2 + (Hgood : bounds_are_recursively_good bound_is_good (invert_Abs ebounds args2)) + (Hwf : wf e1 ebounds) + : forall x, + R x args2 + -> interp interp_op1 (@map_interp_cast interp_base_type1 t1 e1 t1 ebounds args2) x + = interp interp_op1 e1 x + /\ R (interp interp_op1 (@map_interp_cast interp_base_type1 t1 e1 t1 ebounds args2) x) + (interp interp_op2 ebounds args2). + Proof using R_transfer_op interpf_transfer_op. destruct Hwf; intros; eapply interpf_mapf_interp_cast_and_rel; eauto. Qed. + + Lemma interp_map_interp_cast + {t1} e1 ebounds + args2 + (Hgood : bounds_are_recursively_good bound_is_good (invert_Abs ebounds args2)) + (Hwf : wf e1 ebounds) + : forall x, + R x args2 + -> interp interp_op1 (@map_interp_cast interp_base_type1 t1 e1 t1 ebounds args2) x + = interp interp_op1 e1 x. + Proof using R_transfer_op interpf_transfer_op. intros; eapply interp_map_interp_cast_and_rel; eassumption. Qed. + + Lemma InterpMapInterpCastAndRel + {t} e + args + (Hwf : Wf e) + (Hgood : bounds_are_recursively_good bound_is_good (invert_Abs (e interp_base_type2) args)) + : forall x, + R x args + -> Interp interp_op1 (@MapInterpCast t e args) x + = Interp interp_op1 e x + /\ R (Interp interp_op1 (@MapInterpCast t e args) x) + (Interp interp_op2 e args). + Proof using R_transfer_op interpf_transfer_op. apply interp_map_interp_cast_and_rel; auto. Qed. + + Lemma InterpMapInterpCast + {t} e + args + (Hwf : Wf e) + (Hgood : bounds_are_recursively_good bound_is_good (invert_Abs (e interp_base_type2) args)) + : forall x, + R x args + -> Interp interp_op1 (@MapInterpCast t e args) x + = Interp interp_op1 e x. + Proof using R_transfer_op interpf_transfer_op. apply interp_map_interp_cast; auto. Qed. +End language. |