Library TypeECC

Require Export ConvECC.
Require Export EnvECC.
Require Import Peano_dec.
Require Import Max.

Section Typage.

  Definition ecc_prod s1 s2 s3 :=
    match s2, s1, s3 with
      prop, _, prop => true
    | kind n, prop, kind n' => if eq_nat_dec n n' then true else false
    | kind n, kind m, kind n' => if eq_nat_dec (max n m) n' then true else false
    | _, _, _ => false
    end.

  Axiom ecc_prod_fun : s1 s2 s3 s1' s2' s3',
     ecc_prod s1 s2 s3 = true ->
     ecc_prod s1' s2' s3' = true ->
     s1 = s1' ->
     s2 = s2' ->
     s3 = s3'.

  Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var : e T s, typ e T (Srt s) -> wf (T :: e)
  with typ : env -> term -> term -> Prop :=
    | type_prop :
         e,
        wf e ->
        typ e (Srt prop) (Srt (kind 0))
    | type_kind :
         e n,
        wf e ->
        typ e (Srt (kind n)) (Srt (kind (S n)))
    | type_var :
         e v t,
        wf e ->
        item_lift t e v ->
        typ e (Ref v) t
    | type_abs :
         e T M U s1 s2 s3,
        typ e T (Srt s1) ->
        typ (T :: e) U (Srt s2) ->
        typ (T :: e) M U ->
        ecc_prod s1 s2 s3 = true ->
        typ e (Abs T M) (Prod T U)
    | type_app :
         e u v V Ur,
        typ e v V ->
        typ e u (Prod V Ur) ->
        typ e (App u v) (subst v Ur)
    | type_prod :
         e T U s1 s2 s3,
        typ e T (Srt s1) ->
        typ (T :: e) U (Srt s2) ->
        ecc_prod s1 s2 s3 = true ->
        typ e (Prod T U) (Srt s3)
    | type_conv :
         e t U V s,
        typ e t U ->
        conv U V ->
        typ e V (Srt s) ->
        typ e t V.

  Hint Resolve wf_nil type_prop type_kind type_var: coc.

Scheme typ_mind := Minimality for typ Sort Prop
  with wf_mind := Minimality for wf Sort Prop.

  Lemma typ_wf : e t T, typ e t T -> wf e.
simple induction 1; auto with coc.
Qed.

  Hint Resolve typ_wf: coc.

  Lemma wf_sort :
    n e f t,
   trunc (S n) e f -> wf e -> item t e n -> exists s, typ f t (Srt s).
simple induction n.
do 4 intro.
inversion_clear H.
inversion_clear H0.
intros.
inversion_clear H0.
inversion_clear H.
eauto with coc.

do 6 intro.
inversion_clear H0.
intros.
inversion_clear H2.
inversion_clear H0.
elim H with e0 f t; intros; eauto with coc.
Qed.

  Definition inv_type (P : Prop) e t T :=
    match t with
    | Srt prop => conv T (Srt (kind 0)) -> P
    | Srt (kind n) => conv T (Srt (kind (S n))) -> P
    | Ref n => x, item x e n -> conv T (lift (S n) x) -> P
    | Abs A M =>
         s1 s2 s3 U,
        typ e A (Srt s1) ->
        typ (A :: e) M U -> typ (A :: e) U (Srt s2) ->
        ecc_prod s1 s2 s3 = true -> conv T (Prod A U) -> P
    | App u v =>
         Ur V,
        typ e v V -> typ e u (Prod V Ur) -> conv T (subst v Ur) -> P
    | Prod A B =>
         s1 s2 s3,
        typ e A (Srt s1) -> typ (A :: e) B (Srt s2) ->
        ecc_prod s1 s2 s3 = true -> conv T (Srt s3) -> P
    end.

  Lemma inv_type_conv :
    P e t U V, conv U V -> inv_type P e t U -> inv_type P e t V.
do 6 intro.
cut ( x : term, conv V x -> conv U x).
intro.
case t; simpl in |- *; intros.
generalize H1.
elim s; auto with coc; intros.

apply H1 with x; auto with coc.

apply H1 with s1 s2 s3 U0; auto with coc.

apply H1 with Ur V0; auto with coc.

apply H1 with s1 s2 s3; auto with coc.

intros.
apply trans_conv_conv with V; auto with coc.
Qed.

  Theorem typ_inversion : P e t T, typ e t T -> inv_type P e t T -> P.
simple induction 1; simpl in |- *; intros.
auto with coc.

auto with coc.

elim H1; intros.
apply H2 with x; auto with coc.
rewrite H3; auto with coc.

apply H7 with s1 s2 s3 U; auto with coc.

apply H4 with Ur V; auto with coc.

apply H5 with s1 s2 s3; auto with coc.

apply H1.
apply inv_type_conv with V; auto with coc.
Qed.

  Lemma inv_typ_kind :
     e T n, typ e (Srt (kind n)) T -> conv T (Srt (kind (S n))).
intros.
apply typ_inversion with e (Srt (kind n)) T; simpl in |- *; auto with coc.
Qed.

  Lemma inv_typ_prop : e T, typ e (Srt prop) T -> conv T (Srt (kind 0)).
intros.
apply typ_inversion with e (Srt prop) T; simpl in |- *; auto with coc.
Qed.

  Lemma inv_typ_ref :
    (P : Prop) e T n,
   typ e (Ref n) T ->
   ( U : term, item U e n -> conv T (lift (S n) U) -> P) -> P.
intros.
apply typ_inversion with e (Ref n) T; simpl in |- *; intros; auto with coc.
apply H0 with x; auto with coc.
Qed.

  Lemma inv_typ_abs :
    (P : Prop) e A M U,
   typ e (Abs A M) U ->
   ( s1 s2 s3 T,
    typ e A (Srt s1) ->
    typ (A :: e) M T -> typ (A :: e) T (Srt s2) ->
    ecc_prod s1 s2 s3 = true -> conv (Prod A T) U -> P) ->
   P.
intros.
apply typ_inversion with e (Abs A M) U; simpl in |- *; auto with coc; intros.
apply H0 with s1 s2 s3 U0; auto with coc.
Qed.

  Lemma inv_typ_app :
    (P : Prop) e u v T,
   typ e (App u v) T ->
   ( V Ur, typ e u (Prod V Ur) -> typ e v V -> conv T (subst v Ur) -> P) ->
   P.
intros.
apply typ_inversion with e (App u v) T; simpl in |- *; auto with coc; intros.
apply H0 with V Ur; auto with coc.
Qed.

  Lemma inv_typ_prod :
    (P : Prop) e T U s,
   typ e (Prod T U) s ->
   ( s1 s2 s3,
    typ e T (Srt s1) -> typ (T :: e) U (Srt s2) -> ecc_prod s1 s2 s3 = true ->
    conv (Srt s3) s -> P) -> P.
intros.
apply typ_inversion with e (Prod T U) s; simpl in |- *; auto with coc; intros.
apply H0 with s1 s2 s3; auto with coc.
Qed.

  Lemma typ_weak_weak :
    A e t T,
   typ e t T ->
    n f,
   ins_in_env A n e f -> wf f -> typ f (lift_rec 1 t n) (lift_rec 1 T n).
simple induction 1; simpl in |- *; intros; auto with coc.
elim (le_gt_dec n v); intros; apply type_var; auto with coc.
apply ins_item_lift_ge with A e0; auto with coc.

apply ins_item_lift_lt with A e0; auto with coc.

cut (wf (lift_rec 1 T0 n :: f)).
intro.
apply type_abs with s1 s2 s3; auto with coc.

apply wf_var with s1; auto with coc.

rewrite distr_lift_subst.
apply type_app with (lift_rec 1 V n); auto with coc.

cut (wf (lift_rec 1 T0 n :: f)).
intro.
apply type_prod with s1 s2; auto with coc.

apply wf_var with s1; auto with coc.

apply type_conv with (lift_rec 1 U n) s; auto with coc.
Qed.

  Theorem thinning :
    e t T A,
   typ e t T -> wf (A :: e) -> typ (A :: e) (lift 1 t) (lift 1 T).
unfold lift in |- *.
intros.
inversion_clear H0.
apply typ_weak_weak with A e; auto with coc.
apply wf_var with s; auto with coc.
Qed.

  Lemma thinning_n :
    n e f t T,
   trunc n (e:env) (f:env) ->
   typ f t T -> wf e -> typ e (lift n t) (lift n T).
simple induction 1.
intros.
rewrite lift0.
rewrite lift0.
trivial.

intros.
rewrite simpl_lift; auto with coc.
pattern (lift (S k) T) in |- *.
rewrite simpl_lift; auto with coc.
apply thinning; auto with coc.
apply H1; trivial.
inversion_clear H3.
eauto with coc.
Qed.

  Lemma wf_sort_lift :
    n e t, wf e -> item_lift t e n -> exists s, typ e t (Srt s).
simple induction n.
simple destruct e; intros.
elim H0; intros.
inversion_clear H2.

elim H0; intros.
rewrite H1.
inversion_clear H2.
inversion_clear H.
exists s.
replace (Srt s) with (lift 1 (Srt s)); auto with coc.
apply thinning; auto with coc.
apply wf_var with s; auto with coc.

intros.
elim H1; intros.
rewrite H2.
generalize H0.
inversion_clear H3; intros.
rewrite simpl_lift; auto with coc.
cut (wf l); intros.
elim H with l (lift (S n0) x); intros; auto with coc.
inversion_clear H3.
exists x0.
change (typ (y :: l) (lift 1 (lift (S n0) x)) (lift 1 (Srt x0))) in |- *.
apply thinning; auto with coc.
apply wf_var with s; auto with coc.

exists x; auto with coc.

inversion_clear H3.
eauto with coc.
Qed.

  Lemma typ_sub_weak :
    g d t e u U,
   typ g d t ->
   typ e u U ->
    f n,
   sub_in_env d t n e f ->
   wf f -> trunc n f g -> typ f (subst_rec d u n) (subst_rec d U n).
Proof.
simple induction 2; simpl in |- *; intros; auto with coc.
destruct (lt_eq_lt_dec n v) as [[fvar|eq_var]|bvar].
constructor; trivial.
apply sub_item_lift_sup with (1 := H3) (2 := fvar) (3 := H2).

subst v; rewrite sub_item_lift_eq with (1 := H3) (2 := H2).
apply thinning_n with g; auto with coc.

constructor; trivial.
apply nth_sub_inf with (1 := H3); trivial.

cut (wf (subst_rec d T n :: f)); intros.
apply type_abs with s1 s2 s3; auto with coc.

apply wf_var with s1; auto with coc.

rewrite distr_subst.
apply type_app with (subst_rec d V n); auto with coc.

cut (wf (subst_rec d T n :: f)); intros.
apply type_prod with s1 s2; auto with coc.

apply wf_var with s1; auto with coc.

apply type_conv with (subst_rec d U0 n) s; auto with coc.
Qed.

  Theorem substitution :
    e t u U d,
   typ (t :: (e:env)) u U -> typ e d t -> typ e (subst d u) (subst d U).
intros.
unfold subst in |- *.
apply typ_sub_weak with e t (t :: e); auto with coc.
apply typ_wf with d t; auto with coc.
Qed.

  Theorem type_case : e t T, typ e t T -> exists s, typ e T (Srt s).
simple induction 1; intros; auto with coc.
 exists (kind 1); auto with coc.
 exists (kind (S (S n))); auto with coc.
 elim wf_sort_lift with (2 := H1); trivial; intros.
   exists x; auto with coc.
 exists s3.
   apply type_prod with s1 s2; auto with coc.
 destruct H3.
   apply inv_typ_prod with (1 := H3); intros.
   exists s2.
   change (Srt s2) with (subst v (Srt s2)) in |- *.
   apply substitution with V; auto with coc.
 destruct s3.
  exists (kind (S n)); auto with coc.
    constructor.
    apply typ_wf with (1 := H0).
  exists (kind 0).
    constructor.
    apply typ_wf with (1 := H0).
 exists s; trivial.
Qed.

  Lemma typ_red_env :
    e t T, typ e t T ->
    f, red1_in_env red1 e f -> wf f -> typ f t T.
simple induction 1; intros; auto with coc.

elim red_item with (2 := H1) (3 := H2); auto with coc; intros.
inversion_clear H4.
inversion_clear H6.
elim H1; intros.
elim item_trunc with (1 := H8); intros.
elim wf_sort with (1 := H9) (3 := H8); eauto; intros.
apply type_conv with x x2; auto with coc.
rewrite H6.
replace (Srt x2) with (lift (S v) (Srt x2)); auto with coc.
apply thinning_n with x1; auto with coc.

cut (wf (T0 :: f)); intros.
apply type_abs with s1 s2 s3; auto with coc.

apply wf_var with s1; auto with coc.

apply type_app with V; auto with coc.

cut (wf (T0 :: f)); intros.
apply type_prod with s1 s2; auto with coc.

apply wf_var with s1; auto with coc.

apply type_conv with U s; auto with coc.
Qed.

  Lemma subj_red : e t T, typ e t T -> u, red1 t u -> typ e u T.
simple induction 1; intros.
inversion_clear H1.

inversion_clear H1.

inversion_clear H2.

inversion_clear H7.
cut (wf (M' :: e0)); intros.
apply type_conv with (Prod M' U) s3; auto with coc.
apply type_abs with s1 s2 s3; auto with coc.
apply typ_red_env with (T0 :: e0); auto with coc.

apply typ_red_env with (T0 :: e0); auto with coc.

apply type_prod with s1 s2; auto with coc.

apply wf_var with s1; auto with coc.

apply type_abs with s1 s2 s3; auto with coc.

elim type_case with (1 := H2); intros.
apply inv_typ_prod with (1 := H5); intros.
generalize H2 H3; clear H2 H3.
inversion_clear H4; intros.
apply inv_typ_abs with (1 := H2); intros.
apply type_conv with (subst v T1) s2; auto with coc.
apply substitution with T0; auto with coc.
apply type_conv with V s0; auto with coc.
apply sym_conv.
apply inv_conv_prod_l with (1 := H13).

unfold subst in |- *.
apply conv_conv_subst; auto with coc.
apply inv_conv_prod_r with (1 := H13); auto with coc.

replace (Srt s2) with (subst v (Srt s2)); auto with coc.
apply substitution with V; auto with coc.

apply type_app with V; auto with coc.

apply type_conv with (subst N2 Ur) s2; auto with coc.
apply type_app with V; auto with coc.

unfold subst in |- *.
apply conv_conv_subst; auto with coc.

replace (Srt s2) with (subst v (Srt s2)); auto with coc.
apply substitution with V; auto with coc.

inversion_clear H5.
apply type_prod with s1 s2; auto with coc.
apply typ_red_env with (T0 :: e0); auto with coc.
apply wf_var with s1; auto with coc.

apply type_prod with s1 s2; auto with coc.

apply type_conv with U s; auto with coc.
Qed.

  Theorem subject_reduction :
    e t u, red t u -> T, typ e t T -> typ e u T.
simple induction 1; intros; auto with coc.
apply subj_red with P; intros; auto with coc.
Qed.

  Lemma type_reduction : e t T U, red T U -> typ e t T -> typ e t U.
intros.
elim type_case with (1 := H0); intros.
apply type_conv with T x; auto with coc.
apply subject_reduction with T; trivial.
Qed.

  Theorem typ_unique :
    e t T, typ e t T -> U, typ e t U -> conv T U.
simple induction 1; intros.
 apply sym_conv.
   apply inv_typ_prop with e0; auto with coc.
 apply sym_conv.
   apply inv_typ_kind with e0; auto with coc.
 apply inv_typ_ref with e0 U v; auto with coc; intros.
   elim H1; intros.
    rewrite H5.
   elim fun_item with (1 := H3) (2 := H6); auto with coc.
 apply inv_typ_abs with (1 := H7); intros.
   apply trans_conv_conv with (Prod T0 T1); auto with coc.
 apply inv_typ_app with (1 := H4); intros.
   apply trans_conv_conv with (subst v Ur0); auto with coc.
   unfold subst in |- *; apply conv_conv_subst; auto with coc.
   apply inv_conv_prod_r with (1 := H3 _ H5).
 apply inv_typ_prod with (1 := H5); intros.
   apply trans_conv_conv with (Srt s5); auto with coc.
    replace s5 with s3; auto with coc.
   apply ecc_prod_fun with (1 := H4) (2 := H8).
  apply conv_sort.
    auto.
  apply conv_sort; auto.
 apply trans_conv_conv with U; auto with coc.
Qed.

  Lemma typ_conv_conv :
    e u U v V, typ e u U -> typ e v V -> conv u v -> conv U V.
intros.
elim church_rosser with (1 := H1); auto with coc; intros.
apply typ_unique with e x.
apply subject_reduction with u; trivial.

apply subject_reduction with v; trivial.
Qed.

End Typage.