Library MetaCoq.Translations.param_original

Infix "≤" := Nat.leb.
Definition default_term := tVar "constant_not_found".
Definition debug_term msg:= tVar ("debug: " ++ msg).

Fixpoint tsl_rec0 (n : nat) (t : term) {struct t} : term :=
  match t with
  | tRel kif n k then tRel (2×k-n+1) else t
  | tEvar k tstEvar k (map (tsl_rec0 n) ts)
  | tCast t c atCast (tsl_rec0 n t) c (tsl_rec0 n a)
  | tProd na A BtProd na (tsl_rec0 n A) (tsl_rec0 (n+1) B)
  | tLambda na A ttLambda na (tsl_rec0 n A) (tsl_rec0 (n+1) t)
  | tLetIn na t A utLetIn na (tsl_rec0 n t) (tsl_rec0 n A) (tsl_rec0 (n+1) u)
  | tApp t lutApp (tsl_rec0 n t) (map (tsl_rec0 n) lu)
  | tCase ik t u brtCase ik (tsl_rec0 n t) (tsl_rec0 n u)
                            (map (fun x(fst x, tsl_rec0 n (snd x))) br)
  | tProj p ttProj p (tsl_rec0 n t)
  
  
  | _t
  end.

Fixpoint subst_app (t : term) (us : list term) : term :=
  match t, us with
  | tLambda _ A t, u :: ussubst_app (t {0 := u}) us
  | _, []t
  | _, _mkApps t us
  end.

Fixpoint tsl_rec1_app (app : option term) (E : tsl_table) (t : term) : term :=
  let tsl_rec1 := tsl_rec1_app None in
  let debug case symbol :=
      debug_term ("tsl_rec1: " ++ case ++ " " ++ symbol ++ " not found") in
  match t with
  | tLambda na A t
    let A0 := tsl_rec0 0 A in
    let A1 := tsl_rec1_app None E A in
    tLambda na A0 (tLambda (tsl_name tsl_ident na)
                           (subst_app (lift0 1 A1) [tRel 0])
                           (tsl_rec1_app (option_map (lift 2 2) app) E t))
  | tlet t1 :=
  match t with
  | tRel ktRel (2 × k)
  | tSort stLambda (nNamed "A") (tSort s) (tProd nAnon (tRel 0) (tSort s))

  | tProd na A B
    let A0 := tsl_rec0 0 A in
    let A1 := tsl_rec1 E A in
    let B0 := tsl_rec0 1 B in
    let B1 := tsl_rec1 E B in
    let ΠAB0 := tProd na A0 B0 in
    tLambda (nNamed "f") ΠAB0
      (tProd na (lift0 1 A0)
             (tProd (tsl_name tsl_ident na)
                    (subst_app (lift0 2 A1) [tRel 0])
                    (subst_app (lift 1 2 B1)
                               [tApp (tRel 2) [tRel 1]])))
  | tApp t us
    let us' := concat (map (fun v[tsl_rec0 0 v; tsl_rec1 E v]) us) in
    mkApps (tsl_rec1 E t) us'

  | tLetIn na t A u
    let t0 := tsl_rec0 0 t in
    let t1 := tsl_rec1 E t in
    let A0 := tsl_rec0 0 A in
    let A1 := tsl_rec1 E A in
    let u0 := tsl_rec0 0 u in
    let u1 := tsl_rec1 E u in
    tLetIn na t0 A0 (tLetIn (tsl_name tsl_ident na) (lift0 1 t1)
                            (subst_app (lift0 1 A1) [tRel 0]) u1)

  | tCast t c Alet t0 := tsl_rec0 0 t in
                  let t1 := tsl_rec1 E t in
                  let A0 := tsl_rec0 0 A in
                  let A1 := tsl_rec1 E A in
                  tCast t1 c (mkApps A1 [tCast t0 c A0])

  | tConst s univs
    match lookup_tsl_table E (ConstRef s) with
    | Some tt
    | Nonedebug "tConst" s
    end
  | tInd i univs
    match lookup_tsl_table E (IndRef i) with
    | Some tt
    | Nonedebug "tInd" (match i with mkInd s _s end)
    end
  | tConstruct i n univs
    match lookup_tsl_table E (ConstructRef i n) with
    | Some tt
    | Nonedebug "tConstruct" (match i with mkInd s _s end)
    end
  | tCase ik t u brs as case
    let brs' := List.map (on_snd (lift0 1)) brs in
    let case1 := tCase ik (lift0 1 t) (tRel 0) brs' in
    match lookup_tsl_table E (IndRef (fst ik)) with
    | Some (tInd i _univ) ⇒
      tCase (i, (snd ik) × 2)
            (tsl_rec1_app (Some (tsl_rec0 0 case1)) E t)
            (tsl_rec1 E u)
            (map (on_snd (tsl_rec1 E)) brs)
    | _debug "tCase" (match (fst ik) with mkInd s _s end)
    end
  | tProj _ _todo
  | tFix _ _ | tCoFix _ _todo
  | tVar _ | tEvar _ _todo
  | tLambda _ _ _tVar "impossible"
  end in
  match app with Some t'mkApp t1 (t' {3 := tRel 1} {2 := tRel 0})
               | Nonet1 end
  end.
Definition tsl_rec1 := tsl_rec1_app None.

Definition tsl_mind_body (E : tsl_table) (mp : string) (kn : kername)
           (mind : mutual_inductive_body) : tsl_table × list mutual_inductive_body.
Defined.


Instance param : Translation :=
  {| tsl_id := tsl_ident ;
     tsl_tm := fun ΣE t ret (tsl_rec1 (snd ΣE) t) ;
     
     tsl_ty := None ;
     tsl_ind := fun ΣE mp kn mind ret (tsl_mind_body (snd ΣE) mp kn mind) |}.

Definition T := A, A A.

Definition tm := ((fun A (x:A) ⇒ x) (Type Type) (fun xx)).




Module Id1.
  Definition ID := A, A A.


  Lemma param_ID_identity (f : ID)
    : ID f A x, f A x = x.

  Definition toto := fun n : nat ⇒ (fun y ⇒ 0) (fun _ : Typen).

  Definition my_id : ID :=
    let n := 12 in (fun (_ : nat) yy) 4 (fun A x ⇒ (fun _ : natx) n).


  Definition free_thm_my_id : A x, my_id A x = x
    := param_ID_identity my_id my_id.
End Id1.

Module Id2.
  Definition ID := A x y (p : x = y :> A), x = y.


  Lemma param_ID_identity (f : ID)
    : ID f A x y p, f A x y p = p.

  Definition myf : ID
    := fun A x y peq_trans (eq_trans p (eq_sym p)) p.


  Definition free_thm_myf : A x y p, myf A x y p = p
    := param_ID_identity myf myf.
End Id2.

Module Vectors.
End Vectors.


Definition rev_type := A, list A list A.

Module Axioms.

  Definition UIP := A (x y : A) (p q : x = y), p = q.



  Definition eq_eq {A Ax xy yp}
    : eq A A x x y y p p # x = y.

  Definition eq_eq {A Ax xy yp}
    : p # x = y eq A A x x y y p.

  Definition eq_eq_equiv A Ax xy yp
    : eq A A x x y y p <~> p # x = y.

  Theorem UIP_provably_parametric : h : UIP, UIP h.


  Definition wFunext
    := A (B : A Type) (f g : x, B x), ( x, f x = g x) f = g.


  Theorem wFunext_provably_parametric : h : wFunext, wFunext h.




  Definition wUnivalence := A B, A <~> B A = B.


  Theorem wUnivalence_provably_parametric : h, wUnivalence h.

  Definition equiv_paths {A B} (p : A = B) : A <~> B
    := transport (Equiv A) p equiv_idmap.

  Definition Univalence := A B (p : A = B), IsEquiv (equiv_paths p).

  Definition coe {A B} (p : A = B) : A B := transport idmap p.

  Definition Univalence' := A B (p : A = B), IsEquiv (coe p).


  Definition UU' : Univalence' Univalence.
  Defined.



  Lemma paths_ok {A} {Aᵗ : A Type} {x y} {xᵗ : A y} (p : x = y)
    : paths A A x (transport A p^ x) y x p.

  Lemma paths_ok2 {A} {Aᵗ : A Type} {x y} {xᵗ : A y} (p q : x = y) e r
        (Hr : e # (paths_ok p) = r)
    : paths (x = y) (paths A A x (transport A p^ x) y x) p (paths_ok p) q r e.

  Definition ap_idmap {A} {Aᵗ : A Type} {x y xyᵗ} (p : x = y)
             (pᵗ : paths A A x x y y p)
    : ap A A A A idmap (fun uidmap) x x y y p p = (ap_idmap p)^ # p.

  Definition U'U : Univalence Univalence'.
  Defined.

  Theorem Univalence'_provably_parametric : h : Univalence', Univalence' h.

  Definition Univalence_wFunext : Univalence wFunext.
  Admitted.

  Theorem Univalence_provably_parametric : h : Univalence, Univalence h.
End Axioms.