Library MetaCoq.Erasure.SafeErasureFunction



Section fix_sigma.
Variable Σ : global_env_ext.
Variable : wf Σ.

Definition term_rel : Relation_Definitions.relation ( Γ t, wellformed Σ Γ t) :=
  fun '(Γ2; B; H) '(Γ1; t1; H2)
     na A, red (fst Σ) Γ1 t1 (tProd na A B) × (Γ1,, vass na A) = Γ2.

Definition cod B t := match t with tProd _ _ B'B = B' | _False end.

Lemma wf_cod : WellFounded cod.

Lemma wf_cod' : WellFounded (Relation_Operators.clos_trans _ cod).

Lemma Acc_no_loop X (R : X X Prop) t : Acc R t R t t False.


Instance wf_reduction : WellFounded term_rel.


Equations is_arity Γ ( : wf_local Σ Γ) T (HT : wellformed Σ Γ T) :
  typing_result ({Is_conv_to_Arity Σ Γ T} + {¬ Is_conv_to_Arity Σ Γ T})
  by wf ((Γ;T;HT) : ( Γ t, wellformed Σ Γ t)) term_rel :=
  {
    is_arity Γ T HT with (@reduce_to_sort _ Σ Γ T HT) ⇒ {
    | Checked Hret (left _) ;
    | TypeError _ with inspect (@reduce_to_prod _ Σ Γ T _) ⇒ {
      | exist (Checked (na; A; B; H)) He
        match is_arity (Γ,, vass na A) _ B _ with
        | Checked (left H) ⇒ ret (left _)
        | Checked (right H) ⇒ ret (right _)
        | TypeError tTypeError t
        end;
      | exist (TypeError (NotAProduct _ _)) Heret (right _);
      | exist (TypeError t) HeTypeError t }
    }
  }.


End fix_sigma.

Definition wf_ext_wf Σ : wf_ext Σ wf Σ := fst.

Program Definition is_erasable (Sigma : PCUICAst.global_env_ext) ( : wf_ext Sigma) (Gamma : context) (t : PCUICAst.term) (Ht : welltyped Sigma Gamma t) :
  typing_result ({isErasable Sigma Gamma t} +{∥(isErasable Sigma Gamma t False)∥}) :=
  mlet (T; _) <- @type_of extraction_checker_flags Sigma _ _ Gamma t Ht ;;
  mlet b <- is_arity Sigma _ Gamma _ T _ ;;
  if b : {_} + {_} then
    ret (left _)
  else mlet (K; _) <- @type_of extraction_checker_flags Sigma _ _ Gamma T _ ;;
       mlet (u;_) <- @reduce_to_sort _ Sigma _ Gamma K _ ;;
      match is_prop_sort u with trueret (left _) | falseret (right _) end
.









Section Erase.

  Definition is_box c :=
    match c with
    | E.tBoxtrue
    | _false
    end.

  Fixpoint mkAppBox c n :=
    match n with
    | 0 ⇒ c
    | S nmkAppBox (E.tApp c E.tBox) n
    end.

  Definition on_snd_map {A B C} (f : B C) (p : A × B) :=
    (fst p, f (snd p)).

  Variable (Σ : global_env_ext)( : wf_ext Σ ).


  Section EraseMfix.
    Context (erase : (Γ : context) (t : term) (Ht : welltyped Σ Γ t), typing_result E.term).

    Program Definition erase_mfix Γ (defs : mfixpoint term) : typing_result (EAst.mfixpoint E.term) :=
      let Γ' := (PCUICLiftSubst.fix_context defs ++ Γ)%list in
      monad_map (fun dH <- _ ;;
                   dbody' <- erase Γ' d.(dbody) H;;
                          ret ({| E.dname := d.(dname); E.rarg := d.(rarg);
                                  E.dbody := dbody' |})) defs.

  End EraseMfix.

  Equations(noind) erase (Γ : context) (t : term) (Ht : welltyped Σ Γ t) : typing_result E.term :=
    erase Γ t Ht with (is_erasable Σ Γ t Ht) :=
    {
      erase Γ _ Ht (Checked (left _)) := ret (E.tBox);
      erase Γ _ Ht (TypeError t) := TypeError t ;
      erase Γ (tRel i) Ht _ := ret (E.tRel i) ;
      erase Γ (tVar n) Ht _ := ret (E.tVar n) ;
      erase Γ (tEvar m l) Ht _ := l' <- monad_map (fun xerase Γ x _) l;; ret (E.tEvar m l') ;
      erase Γ (tSort u) Ht _ := ret E.tBox

      ; erase Γ (tConst kn u) Ht _ := ret (E.tConst kn)
      ; erase Γ (tInd kn u) Ht _ := ret E.tBox
      ; erase Γ (tConstruct kn k u) Ht _ := ret (E.tConstruct kn k)
      ; erase Γ (tProd na b t) Ht _ := ret E.tBox
      ; erase Γ (tLambda na b t) Ht _ :=
                           t' <- erase (vass na b :: Γ) t _;;
                              ret (E.tLambda na t')
      ; erase Γ (tLetIn na b t0 t1) Ht _ :=
                              b' <- erase Γ b _;;
                                 t1' <- erase (vdef na b t0 :: Γ) t1 _;;
                                 ret (E.tLetIn na b' t1')
      ; erase Γ (tApp f u) Ht _ :=
                     f' <- erase Γ f _;;
                     l' <- erase Γ u _;;
                     ret (E.tApp f' l')
      ; erase Γ (tCase ip p c brs) Ht _ :=
          c' <- erase Γ c _;;
          if is_box c' then
            match brs with
            | (a, b) :: brsb' <- erase Γ b _ ;; ret (E.mkApps b' (repeat E.tBox a))
            | []ret (E.tCase ip c' [])
            end
          else
            brs' <- monad_map (T :=typing_result) (fun xx' <- erase Γ (snd x) _;; ret (fst x, x')) brs;;
            ret (E.tCase ip c' brs')
      ; erase Γ (tProj p c) Ht _ :=
          c' <- erase Γ c _;;
          if is_box c' then ret (E.tBox) else
          ret (E.tProj p c')
      ; erase Γ (tFix mfix n) Ht _ :=
          mfix' <- erase_mfix erase Γ mfix;;
          ret (E.tFix mfix' n)
      ; erase Γ (tCoFix mfix n) Ht _ :=
                          mfix' <- erase_mfix (erase) Γ mfix;;
                                ret (E.tCoFix mfix' n)
    }.

End Erase.

Lemma erases_erase (Σ : global_env_ext) Γ t T (wfΣ : wf_ext Σ) t' :
  Σ ;;; Γ |- t : T
                  (wt : welltyped Σ Γ t),
  erase Σ wfΣ Γ t wt = Checked t'
  erases Σ Γ t t'.

Lemma erase_Some_typed {Σ wfΣ Γ t wft r} :
  erase Σ wfΣ Γ t wft = Checked r T, Σ ;;; Γ |- t : T.

Definition optM {M : Type Type} `{Monad M} {A B} (x : option A) (f : A M B) : M (option B) :=
  match x with
  | Some xy <- f x ;; ret (Some y)
  | Noneret None
  end.

Lemma wf_local_nil {Σ} : wf_local Σ [] .

Program Definition erase_constant_body Σ wfΣ (cb : constant_body)
  (Hcb : on_constant_decl (lift_typing typing) Σ cb ) : typing_result E.constant_body :=
  
  body <- match cb.(cst_body) with
          | Some b
            t <- (erase Σ wfΣ [] b _) ;;
            ret (Some t)
          | Noneret None
          end;;
  ret {| E.cst_body := body; |}.

Definition lift_opt_typing {A} (a : option A) (e : type_error) : typing_result A :=
  match a with
  | Some xret x
  | Noneraise e
  end.


Program Definition erase_mutual_inductive_body Σ wfΣ
           (mib : mutual_inductive_body)
: typing_result E.mutual_inductive_body :=
  let bds := mib.(ind_bodies) in
  let arities := arities_context bds in
  bodies <- monad_map (erase_one_inductive_body Σ wfΣ mib.(ind_npars) arities) bds ;;
  ret {| E.ind_npars := mib.(ind_npars);
         E.ind_bodies := bodies; |}.

Program Fixpoint erase_global_decls Σ : wf Σ typing_result E.global_declarations := fun wfΣ
  match Σ with
  | []ret []
  | ConstantDecl kn cb :: Σ
    cb' <- erase_constant_body (Σ, cst_universes cb) _ cb _;;
    Σ' <- erase_global_decls Σ _;;
    ret (E.ConstantDecl kn cb' :: Σ')
  | InductiveDecl kn mib :: Σ
    mib' <- erase_mutual_inductive_body (Σ, ind_universes mib) _ mib ;;
    Σ' <- erase_global_decls Σ _;;
    ret (E.InductiveDecl kn mib' :: Σ')
  end.


Program Definition erase_global Σ : wf Σ _:=
  fun wfΣ
  Σ' <- erase_global_decls Σ wfΣ ;;
  ret Σ'.

Lemma erase_global_correct Σ (wfΣ : wf Σ) Σ' :
  erase_global Σ wfΣ = Checked Σ'
  erases_global Σ Σ'.