Library TypeJudgeECC


Require Import TypeECC.

Section Typage.

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

Scheme eq_typ_mind := Minimality for eq_typ Sort Prop
  with wf_mind := Minimality for wf Sort Prop.

  Lemma typ_wf : e t t' T, eq_typ e t t' T -> wf e.
Proof.
induction 1; trivial.
Qed.

  Lemma typ_refl : e t t' T, eq_typ e t t' T -> eq_typ e t t T.
Proof.
induction 1; intros.
 apply type_prop; trivial.
 apply type_kind; trivial.
 apply type_var; trivial.
 apply type_abs with U s1 s2 s3; trivial.
 apply type_app with V V' Ur' s1 s2 s3; trivial.
 apply type_prod with s1 s2; trivial.
 apply type_app with T T' U' s1 s2 s3; trivial.
   apply type_abs with U s1 s2 s3; trivial.
 apply type_red with T s; trivial.
 apply type_exp with T' s; trivial.
Qed.

  Lemma typ_thin :
    g A e t t' T,
   wf (A::g) ->
   eq_typ e t t' T ->
    n f,
   ins_in_env A n e f ->
   trunc n e g ->
   eq_typ f (lift_rec 1 t n) (lift_rec 1 t' n) (lift_rec 1 T n).
intros g A e t t' T H H0.
elim H0 using eq_typ_mind with (P0:=fun e => n f, ins_in_env A n e f ->
  trunc n e g -> wf f); simpl; intros.
 constructor; eauto.
 constructor; eauto.
 destruct (le_gt_dec n v); intros.
  constructor; eauto.
   apply ins_item_lift_ge with (1 := H4); trivial.
  constructor; eauto.
    apply ins_item_lift_lt with (1 := H4); trivial.
 apply type_abs with (lift_rec 1 U' (S n)) s1 s2 s3; eauto with coc.
 rewrite distr_lift_subst.
   apply type_app
     with (lift_rec 1 V n) (lift_rec 1 V' n) (lift_rec 1 Ur' (S n)) s1 s2 s3;
     eauto with coc.
 apply type_prod with s1 s2; eauto with coc.
 repeat rewrite distr_lift_subst.
   apply type_beta with (lift_rec 1 T' n) (lift_rec 1 U' (S n)) s1 s2 s3;
   auto with coc.
 apply type_red with (lift_rec 1 T0 n) s; auto with coc.
 apply type_exp with (lift_rec 1 T' n) s; auto with coc.
 inversion_clear H1; inversion H2; subst g; trivial.
 inversion H3; subst n; inversion H4; subst g.
  trivial.
  apply wf_var with (lift_rec 1 T' n0) s; auto.
Qed.

  Lemma typ_thinning :
    A e t t' T,
   wf (A::e) ->
   eq_typ e t t' T ->
   eq_typ (A::e) (lift 1 t) (lift 1 t') (lift 1 T).
intros.
unfold lift in |- *.
apply typ_thin with (1 := H) (2 := H0); auto with coc.
Qed.

  Lemma typ_thinning_n :
    f t t' T n e,
   wf e ->
   eq_typ f t t' T ->
   trunc n e f ->
   eq_typ e (lift n t) (lift n t') (lift n T).
induction n; simpl in |- *; intros.
 repeat rewrite lift0; inversion_clear H1; trivial.
  rewrite simpl_lift.
   pattern (lift (S n) t') in |- *.
    rewrite simpl_lift.
   pattern (lift (S n) T) in |- *.
    rewrite simpl_lift.
   inversion H1.
    subst e.
   apply typ_thinning; trivial.
   apply IHn; auto.
   inversion_clear H.
   apply typ_wf with (1 := H4).
Qed.

  Lemma typ_sub :
    g d t e u u' U,
   eq_typ e u u' U ->
    d' n f,
   eq_typ g d d' t ->
   sub_in_env d t n e f ->
   trunc n f g ->
   wf f ->
   eq_typ f (subst_rec d u n) (subst_rec d' u' n) (subst_rec d U n).
induction 1; simpl in *; intros.
 constructor; eauto.
 constructor; eauto.
 destruct (lt_eq_lt_dec n v) as [[fvar| eq_var]| bvar].
  constructor; eauto.
    apply sub_item_lift_sup with (1 := H2); trivial.
   subst v; rewrite sub_item_lift_eq with (1 := H2) (2 := H0).
    apply typ_thinning_n with g; eauto.
  constructor; eauto.
    apply nth_sub_inf with (1 := H2); trivial.
 assert (wf (subst_rec d T n :: f)).
  apply wf_var with (subst_rec d' T' n) s1; eauto.
  apply type_abs with (subst_rec d' U' (S n)) s1 s2 s3; eauto with coc.
  rewrite distr_subst.
   assert (wf (subst_rec d V n :: f)).
  apply wf_var with (subst_rec d' V' n) s1; eauto.
  apply
   type_app with
     (subst_rec d V n) (subst_rec d' V' n) (subst_rec d' Ur' (S n)) s1 s2 s3;
    eauto with coc.
 assert (wf (subst_rec d T n :: f)).
  apply wf_var with (subst_rec d' T' n) s1; eauto.
  apply type_prod with s1 s2; eauto with coc.
 repeat rewrite distr_subst.
   assert (wf (subst_rec d T n :: f)).
  apply wf_var with (subst_rec d' T' n) s1; eauto.
  apply type_beta with (subst_rec d' T' n) (subst_rec d' U' (S n)) s1 s2 s3;
   auto with coc.
 apply type_red with (subst_rec d T n) s; eauto with coc.
   apply IHeq_typ2; eauto.
   apply typ_refl with (1 := H1).
 apply type_exp with (subst_rec d T' n) s; eauto with coc.
   apply IHeq_typ2; eauto.
   apply typ_refl with (1 := H1).
Qed.

  Theorem substitution :
    e t u u' U d d',
   eq_typ (t :: (e:env)) u u' U ->
   eq_typ e d d' t ->
   eq_typ e (subst d u) (subst d' u') (subst d U).
Proof.
intros.
unfold subst in |- *.
apply typ_sub with (1 := H) (2 := H0); auto with coc.
apply typ_wf with (1 := H0).
Qed.

  Inductive red1_in_env : env -> env -> Prop :=
    | red1_env_hd : e t u s, eq_typ e t u (Srt s) ->
        red1_in_env (t :: e) (u :: e)
    | red1_env_tl :
         e f t, red1_in_env e f -> red1_in_env (t :: e) (t :: f).

  Hint Constructors red1_in_env: coc.

  Lemma red_item :
    n t e f,
   item_lift t e n ->
   red1_in_env e f ->
   wf f ->
   item_lift t f n \/
   ( g, trunc (S n) e g -> trunc (S n) f g) /\
   (exists2 u, exists s, eq_typ f t u (Srt s) & item_lift u f n).
simple induction n.
 do 4 intro.
   elim H.
   do 3 intro.
    rewrite H0.
   inversion_clear H1.
   intro.
   inversion_clear H1; intros.
  right.
    split; intros.
   inversion_clear H3; auto with coc.
   exists (lift 1 u).
    exists s.
      change (Srt s) with (lift 1 (Srt s)) in |- *.
      unfold lift in |- *; apply typ_thin with l u l; auto with coc.
    exists u; auto with coc.
  left.
    exists x; auto with coc.
 do 6 intro.
   elim H0.
   do 3 intro.
    rewrite H1.
   inversion_clear H2.
   intro.
   inversion_clear H2; intros.
  left.
    exists x; auto with coc.
  elim H with (lift (S n0) x) l f0; auto with coc; intros.
   left.
     elim H5; intros.
     exists x0; auto with coc.
      rewrite simpl_lift.
     pattern (lift (S (S n0)) x0) in |- *.
      rewrite simpl_lift.
     elim H6; auto with coc.
   right.
     elim H5.
     simple induction 2; intros.
     split; intros.
    inversion_clear H10; auto with coc.
    elim H9; intros.
      exists (lift (S (S n0)) x1).
      rewrite simpl_lift.
       pattern (lift (S (S n0)) x1) in |- *.
        rewrite simpl_lift.
       destruct H8.
       exists x2.
       change (Srt x2) with (lift_rec 1 (Srt x2) 0) in |- *.
       elim H1; unfold lift at 1 3 in |- *; apply typ_thin with f0 y f0;
        auto with coc.
        subst x0; trivial.
     exists x1; auto with coc.
   exists x; auto with coc.
   inversion_clear H2.
     apply typ_wf with (1 := H5).
Qed.

  Lemma typ_red_env :
    e t t' T, eq_typ e t t' T -> f, red1_in_env e f -> wf f ->
   eq_typ f t t' T.
induction 1; intros.
 apply type_prop; trivial.
 apply type_kind; trivial.
 elim red_item with (1 := H0) (2 := H1); auto with coc; intros.
  apply type_var; auto.
  destruct H3.
    destruct H4.
    destruct H4.
    apply type_exp with (2 := H4).
    apply type_var; trivial.
 assert (wf (T :: f)).
  apply wf_var with T' s1; auto.
  apply type_abs with U' s1 s2 s3; auto with coc.
 assert (wf (V :: f)).
  apply wf_var with V' s1; auto.
 apply type_app with V V' Ur' s1 s2 s3; auto with coc.
 assert (wf (T :: f)).
  apply wf_var with T' s1; auto.
  apply type_prod with s1 s2; auto with coc.
 assert (wf (T :: f)).
  apply wf_var with T' s1; auto.
  apply type_beta with T' U' s1 s2 s3; auto with coc.
 apply type_red with T s; auto with coc.
 apply type_exp with T' s; auto with coc.
Qed.

  Lemma typ_refl2 : e M M' T, eq_typ e M M' T -> eq_typ e M' M' T.
induction 1; intros.
 apply type_prop; trivial.
 apply type_kind; trivial.
 apply type_var; trivial.
 assert (wf (T' :: e)).
  apply wf_var with T' s1; trivial.
  assert (red1_in_env (T :: e) (T' :: e)).
   constructor 1 with s1; trivial.
   apply type_exp with (Prod T' U) s3; auto.
    apply type_abs with U' s1 s2 s3; auto.
     apply typ_red_env with (T :: e); auto.
     apply typ_red_env with (T :: e); auto.
    apply type_prod with s1 s2; auto.
      apply typ_refl with U'; trivial.
 assert (wf (V' :: e)).
  apply wf_var with V' s1; trivial.
  assert (red1_in_env (V :: e) (V' :: e)).
   constructor 1 with s1; trivial.
   apply type_exp with (subst v' Ur) s2.
    apply type_app with V V Ur s1 s2 s3; auto.
     apply typ_refl with V'; trivial.
     apply typ_refl with (1 := H2).
    change (Srt s2) with (subst v (Srt s2)) in |- *.
      apply substitution with V; trivial.
      apply typ_refl with (1 := H2).
 assert (wf (T' :: e)).
  apply wf_var with T' s1; trivial.
  assert (red1_in_env (T :: e) (T' :: e)).
   constructor 1 with s1; trivial.
   apply type_prod with s1 s2; auto.
     apply typ_red_env with (T :: e); auto.
 assert (wf (T' :: e)).
  apply wf_var with T' s1; trivial.
  assert (red1_in_env (T :: e) (T' :: e)).
   constructor 1 with s1; trivial.
   apply type_exp with (subst N' U) s2.
    apply substitution with T; auto.
    change (Srt s2) with (subst N (Srt s2)) in |- *.
      apply substitution with T; auto.
      apply typ_refl with (1 := H2).
 apply type_red with T s; auto.
 apply type_exp with T' s; auto.
Qed.

  Lemma wf_sort_lift :
    n e t, wf e -> item_lift t e n ->
   exists s, eq_typ e t 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.
change (Srt s) with (lift 1 (Srt s)).
apply typ_thinning; auto with coc.
apply wf_var with T' s; auto with coc.
apply typ_refl with (1:=H2).

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 (Srt x0) with (lift 1 (Srt x0)).
apply typ_thinning; auto with coc.
apply wf_var with T' s; auto with coc.

exists x; auto with coc.

inversion_clear H3.
apply typ_wf with (1:=H5).
Qed.

  Theorem type_case :
    e t t' T, eq_typ e t t' T ->
   exists s, eq_typ e T T (Srt s).
simple induction 1; intros; auto with coc.
 exists (kind 1); constructor; trivial.
 exists (kind (S (S n))); constructor; trivial.
 apply wf_sort_lift with (2 := H1); trivial.
 exists s3.
   apply typ_refl with (Prod T' U').
   apply type_prod with s1 s2; auto with coc.
 exists s2.
   apply typ_refl with (subst v' Ur').
   change (Srt s2) with (subst v (Srt s2)) in |- *.
   apply substitution with V; trivial.
 destruct s3.
   exists (kind(S n)); constructor.
   apply typ_wf with (1 := H0).
   exists (kind 0); constructor.
   apply typ_wf with (1 := H0).
 exists s2.
   apply typ_refl with (subst N' U').
   change (Srt s2) with (subst N (Srt s2)) in |- *.
   apply substitution with T0; trivial.
 exists s.
   apply typ_refl2 with (1 := H2).
 exists s.
   apply typ_refl with (1 := H2).
Qed.

Require Import Relation_Operators.

  Definition eq_typ_eq e :=
    clos_refl_sym_trans _ (fun x y => exists s, eq_typ e x y (Srt s)).
  Hint Unfold eq_typ_eq : coc.

  Lemma eq_typ_eq_red : e T T' s,
    eq_typ e T T' (Srt s) -> eq_typ_eq e T T'.
Proof.
red in |- *; intros; apply rst_step.
exists s; trivial.
Qed.

  Lemma eq_typ_eq_exp : e T T' s,
    eq_typ e T T' (Srt s) -> eq_typ_eq e T' T.
Proof.
red in |- *; intros; apply rst_sym; apply rst_step.
exists s; trivial.
Qed.

  Lemma type_conv_gen : e M M' T T',
    eq_typ_eq e T T' ->
    (eq_typ e M M' T -> eq_typ e M M' T') /\
    (eq_typ e M M' T' -> eq_typ e M M' T).
induction 1; intros.
 destruct H.
   split; intros.
  apply type_red with (2 := H); trivial.
  apply type_exp with (2 := H); trivial.
 auto.
 destruct IHclos_refl_sym_trans; auto.
 destruct IHclos_refl_sym_trans1.
   destruct IHclos_refl_sym_trans2.
   auto 10.
Qed.
  Lemma type_conv : e M M' T T',
    eq_typ e M M' T -> eq_typ_eq e T T' -> eq_typ e M M' T'.
intros.
elim type_conv_gen with (M := M) (M' := M') (1 := H0); intros; auto.
Qed.

  Definition inv_type (P : Prop) e t t' T :=
    match t with
    | Srt prop => eq_typ_eq e (Srt (kind 0)) T -> t' = Srt prop -> P
    | Srt (kind n) => eq_typ_eq e (Srt (kind (S n))) T -> t' = Srt (kind n) -> P
    | Ref n =>
         x, item_lift x e n -> eq_typ_eq e x T -> t' = Ref n -> P
    | Abs A M =>
         s1 s2 s3 A' M' U U',
        eq_typ e A A' (Srt s1) ->
        eq_typ (A :: e) M M' U ->
        eq_typ (A :: e) U U' (Srt s2) ->
        ecc_prod s1 s2 s3 = true ->
        eq_typ_eq e (Prod A U) T -> t' = Abs A' M' -> P
    | App u v =>
         u' v' Ur Ur' V V' s1 s2 s3,
        eq_typ e v v' V ->
        eq_typ e V V' (Srt s1) ->
        eq_typ e u u' (Prod V Ur) ->
        eq_typ (V::e) Ur Ur' (Srt s2) ->
        ecc_prod s1 s2 s3 = true ->
        t' = App u' v' \/
        (exists2 M, u=Abs V M &
         exists2 M', eq_typ (V::e) M M' Ur & t' = subst v' M') ->
        eq_typ_eq e (subst v Ur) T -> P
    | Prod A B =>
         A' B' s1 s2 s3,
        eq_typ e A A' (Srt s1) ->
        eq_typ (A :: e) B B' (Srt s2) ->
        ecc_prod s1 s2 s3 = true ->
        eq_typ_eq e (Srt s3) T -> t' = Prod A' B' -> P
    end.

  Lemma inv_type_conv :
    P e t t' U V, eq_typ_eq e U V ->
   inv_type P e t t' V -> inv_type P e t t' U.
do 7 intro.
cut ( x : term, eq_typ_eq e x U -> eq_typ_eq e x V).
 intro.
   case t; simpl in |- *; eauto.
   destruct s; simpl in |- *; eauto.
 unfold eq_typ_eq in *; intros.
   apply rst_trans with U; auto.
Qed.

  Theorem typ_inversion :
     P e t t' T, eq_typ e t t' T -> inv_type P e t t' T -> P.
simple induction 1; simpl in |- *; intros; eauto with coc sets.
 apply H9 with (Abs T' M') N' U U' T0 T' s1 s2 s3; auto with coc sets.
  apply type_abs with U' s1 s2 s3; trivial.
  right.
    exists M; trivial.
    exists M'; trivial.
 apply H1.
   apply inv_type_conv with T'; trivial.
   apply eq_typ_eq_red with s; trivial.
 apply H1.
   apply inv_type_conv with T0; trivial.
   apply eq_typ_eq_exp with s; trivial.
Qed.

End Typage.