Library CoqInCoq.Strong_Norm


Require Import Termes.
Require Import Conv.
Require Import Types.
Require Import Class.
Require Import Can.
Require Import Int_term.
Require Import Int_typ.
Require Import Int_stab.

Load "ImpVar".

Inductive trm_in_int : envintPinttProp :=
  | int_nil : itt : intt, trm_in_int nil (TNl _) itt
  | int_cs :
       e (ip : intP) (itt : intt),
      trm_in_int e ip itt
       (y : Int_K) t T,
      int_typ T ip PROP t
      trm_in_int (T :: e) (TCs _ y ip) (shift_intt itt t).

  Hint Resolve int_nil int_cs: coc.

  Record int_adapt e (ip : intP) (itt : intt) : Prop :=
    {adapt_trm_in_int : trm_in_int e ip itt;
     int_can_adapt : can_adapt ip;
     adapt_class_equal : cls_of_int ip = class_env e}.

  Lemma int_sound :
    e t T,
   typ e t T
    (ip : intP) (it : intt),
   int_adapt e ip itint_typ T ip PROP (int_term t it 0).
simple induction 1; simpl in |- *; intros.
red in |- *; apply Acc_intro; intros.
inversion_clear H2.

red in |- *; apply Acc_intro; intros.
inversion_clear H2.

elim (le_gt_dec 0 v); [ intro Hle | intro Hgt ].
rewrite lift0.
elim minus_n_O with v.
elim H1; intros.
rewrite H3.
generalize ip it H2.
clear H3 Hle H2 it ip H1 t0.
elim H4.
intros l ip it (in_interp);
  
 inversion_clear in_interp; simpl in |- *; intros ip_can_adapted same_classes.
apply eq_cand_incl with (int_typ x ip0 PROP);
 auto with coc core arith datatypes.
unfold lift in |- ×.
apply lift_int_typ with y; auto with coc core arith datatypes.

intros l n y H1 H2 ip it (in_interp); inversion_clear in_interp;
 simpl in |- *; intros ip_can_adapted same_classes.
simpl in |- ×.
rewrite simpl_lift.
apply eq_cand_incl with (int_typ (lift (S n) x) ip0 PROP).
unfold lift at 2 in |- ×.
apply lift_int_typ with y0; auto with coc core arith datatypes.

apply H2.
apply Build_int_adapt; auto with coc core arith datatypes.
inversion_clear ip_can_adapted; auto with coc core arith datatypes.

injection same_classes; auto with coc core arith datatypes.

inversion_clear Hgt.

elim H6; intros in_interp ip_can_adapted same_classes.
apply Abs_sound; intros; auto with coc core arith datatypes.
apply int_typ_cr; auto with coc core arith datatypes.

simpl in |- *; intros.
change
  (is_can PROP
     (int_typ U (int_cons T0 ip (cv_skel (cl_term T0 (cls_of_int ip))) X)
        PROP)) in |- ×.
apply int_typ_cr.
unfold int_cons, ext_ik in |- ×.
generalize X H7 H8.
elim (cl_term T0 (cls_of_int ip)); auto with coc core arith datatypes.

unfold subst in |- ×.
rewrite int_term_subst; auto with coc core arith datatypes.
apply H5.
unfold int_cons, ext_ik in |- ×.
apply Build_int_adapt; auto with coc core arith datatypes.
generalize C H8 H9.
elim (cl_term T0 (cls_of_int ip)); auto with coc core arith datatypes.

simpl in |- ×.
pattern (cls_of_int ip) at 1 in |- ×.
rewrite same_classes.
unfold cls_of_int in |- ×.
pattern (cl_term T0 (class_env e0)) in |- ×.
apply class_typ_ord with s1; elim same_classes; simpl in |- *;
 auto with coc core arith datatypes.
rewrite same_classes.
elim skel_sound with e0 T0 (Srt s1); simpl in |- *;
 auto with coc core arith datatypes.
elim same_classes; auto with coc core arith datatypes.

apply H1 with ip; auto with coc core arith datatypes.

elim H4; intros in_interp ip_can_adapted same_classes.
elim type_case with e0 u (Prod V Ur); intros;
 auto with coc core arith datatypes.
inversion_clear H5.
apply inv_typ_prod with e0 V Ur (Srt x); auto with coc core arith datatypes;
 intros.
apply
 eq_cand_incl
  with
    (int_typ Ur
       (int_cons V ip (cv_skel (cl_term V (cls_of_int ip))) (int_typ v ip _))
       PROP).
replace PROP with
 (skel_int Ur
    (int_cons V ip (cv_skel (cl_term V (cls_of_int ip)))
       (int_typ v ip (cv_skel (cl_term V (cls_of_int ip)))))).
unfold subst, int_cons in |- ×.
apply
 subst_int_typ
  with
    ip
    (ext_ik V ip (cv_skel (cl_term V (cls_of_int ip)))
       (int_typ v ip (cv_skel (cl_term V (cls_of_int ip)))))
    (V :: e0)
    (Srt s2); auto with coc core arith datatypes.
unfold ext_ik in |- ×.
rewrite same_classes.
cut (cl_term v (cls_of_int ip) = cl_term v (class_env e0)).
elim class_sound with e0 v V (Srt s1); intros;
 auto with coc core arith datatypes.

elim same_classes; auto with coc core arith datatypes.

simpl in |- ×.
unfold ext_ik in |- ×.
rewrite same_classes.
unfold cls_of_int in |- ×.
apply class_typ_ord with s1; elim same_classes; simpl in |- *;
 auto with coc core arith datatypes.
rewrite same_classes.
elim skel_sound with e0 V (Srt s1); simpl in |- *;
 auto with coc core arith datatypes.
elim same_classes; auto with coc core arith datatypes.

unfold ext_ik in |- ×.
red in |- *; red in |- *; auto with coc core arith datatypes.
apply Tfa2_cs; auto with coc core arith datatypes.
elim (cl_term V (cls_of_int ip)); auto with coc core arith datatypes.

change (int_inv ip) in |- ×.
apply adapt_int_inv; auto with coc core arith datatypes.

replace
 (cls_of_int
    (TCs Int_K
       (ext_ik V ip (cv_skel (cl_term V (cls_of_int ip)))
          (int_typ v ip (cv_skel (cl_term V (cls_of_int ip))))) ip)) with
 (class_env (V :: e0)).
apply class_typ_ord with s2; auto with coc core arith datatypes.
discriminate.

discriminate.

simpl in |- ×.
unfold cls_of_int at 1, ext_ik in |- ×.
rewrite same_classes.
pattern (cl_term V (class_env e0)) in |- ×.
apply class_typ_ord with s1; elim same_classes; simpl in |- *;
 auto with coc core arith datatypes.
rewrite same_classes.
elim skel_sound with e0 V (Srt s1); simpl in |- *;
 auto with coc core arith datatypes.
elim same_classes; auto with coc core arith datatypes.

unfold int_cons, skel_int in |- ×.
replace
 (cls_of_int
    (TCs Int_K
       (ext_ik V ip _ (int_typ v ip (cv_skel (cl_term V (cls_of_int ip)))))
       ip)) with (class_env (V :: e0)).
elim skel_sound with (V :: e0) Ur (Srt s2); simpl in |- *;
 auto with coc core arith datatypes.

simpl in |- ×.
unfold ext_ik in |- ×.
rewrite same_classes.
unfold cls_of_int in |- ×.
elim class_sound with e0 v V (Srt s1); auto with coc core arith datatypes.
simpl in |- ×.
elim same_classes; auto with coc core arith datatypes.

simpl in |- ×.
elim same_classes; auto with coc core arith datatypes.

unfold Pi in H3.
apply H3; auto with coc core arith datatypes.
apply int_typ_cr; auto with coc core arith datatypes.

discriminate H5.

apply sn_prod.
apply H1 with ip; auto with coc core arith datatypes.

apply sn_subst with (Ref 0).
unfold subst in |- ×.
rewrite int_term_subst.
elim H4; intros in_interp ip_can_adapted same_classes.
apply H3 with (def_cons T0 ip).
unfold def_cons, int_cons in |- ×.
apply Build_int_adapt.
apply int_cs; auto with coc core arith datatypes.
apply (var_in_cand 0 (int_typ T0 ip PROP));
 auto with coc core arith datatypes.
exact (int_typ_cr T0 ip ip_can_adapted PROP).

red in |- ×.
apply Tfa_cs; auto with coc core arith datatypes.
unfold ext_ik in |- ×.
elim (cl_term T0 (cls_of_int ip)); auto with coc core arith datatypes.

unfold ext_ik in |- ×.
rewrite same_classes.
unfold cls_of_int in |- ×.
simpl in |- ×.
pattern (cl_term T0 (class_env e0)) in |- ×.
apply class_typ_ord with s1; simpl in |- *; elim same_classes;
 auto with coc core arith datatypes.
rewrite same_classes.
elim skel_sound with e0 T0 (Srt s1); simpl in |- *;
 auto with coc core arith datatypes.
elim same_classes; auto with coc core arith datatypes.

cut (typ e0 U (Srt s)); auto with coc core arith datatypes.
intros.
apply eq_cand_incl with (int_typ U ip PROP);
 auto with coc core arith datatypes.
replace PROP with (skel_int U ip).
elim H5; intros in_interp ip_can_adapted same_classes.
apply conv_int_typ with e0 (Srt s); auto with coc core arith datatypes.
apply class_typ_ord with s; auto with coc core arith datatypes.
discriminate.

discriminate.

unfold skel_int in |- ×.
elim H5; intros in_interp ip_can_adapted same_classes.
rewrite same_classes.
elim skel_sound with e0 U (Srt s); simpl in |- *;
 auto with coc core arith datatypes.

elim type_case with e0 t0 U; intros; auto with coc core arith datatypes.
inversion_clear H6.
elim conv_sort with x s; auto with coc core arith datatypes.
apply typ_conv_conv with e0 U V; auto with coc core arith datatypes.

elim inv_typ_conv_kind with e0 V (Srt s); auto with coc core arith datatypes.
elim H6; auto with coc core arith datatypes.
Qed.

  Fixpoint def_intp e : intP :=
    match e with
    | nilTNl _
    | t :: fdef_cons t (def_intp f)
    end.

  Fixpoint def_intt e : natintt :=
    fun k
    match e with
    | nilfun pRef (k + p)
    | _ :: fshift_intt (def_intt f (S k)) (Ref k)
    end.

  Lemma def_intp_can : e, can_adapt (def_intp e).
simple induction e; simpl in |- *; auto with coc core arith datatypes; intros.
unfold def_cons, int_cons, ext_ik in |- ×.
elim (cl_term a (cls_of_int (def_intp l)));
 auto with coc core arith datatypes.
Qed.

  Lemma def_adapt :
    e, wf e k, int_adapt e (def_intp e) (def_intt e k).
simple induction e; simpl in |- *; intros.
apply Build_int_adapt; auto with coc core arith datatypes.

inversion_clear H0.
cut (wf l); intros.
elim H with (S k); trivial; intros in_interp ip_can_adapted same_classes.
unfold def_cons, int_cons in |- ×.
apply Build_int_adapt; auto with coc core arith datatypes.
apply int_cs; auto with coc core arith datatypes.
apply (var_in_cand k (int_typ a (def_intp l) PROP));
 auto with coc core arith datatypes.
change (is_can PROP (int_typ a (def_intp l) PROP)) in |- ×.
apply int_typ_cr; auto with coc core arith datatypes.

unfold ext_ik in |- ×.
rewrite same_classes.
pattern (cl_term a (class_env l)) in |- ×.
apply class_typ_ord with s; auto with coc core arith datatypes.

simpl in |- ×.
unfold ext_ik in |- ×.
rewrite same_classes.
pattern (cl_term a (class_env l)) in |- ×.
apply class_typ_ord with s; unfold cls_of_int in |- *; elim same_classes;
 auto with coc core arith datatypes.
simpl in |- ×.
rewrite same_classes.
elim skel_sound with l a (Srt s); auto with coc core arith datatypes.
simpl in |- *; auto with coc core arith datatypes.
elim same_classes; auto with coc core arith datatypes.

apply typ_wf with a (Srt s); auto with coc core arith datatypes.
Qed.

  Hint Resolve def_intp_can def_adapt: coc.

  Lemma def_intt_id : n e k, def_intt e k n = Ref (k + n).
simple induction n; simple destruct e; simpl in |- *;
 auto with coc core arith datatypes; intros.
replace (k + 0) with k; auto with coc core arith datatypes.

rewrite H.
replace (k + S n0) with (S (k + n0)); auto with coc core arith datatypes.
Qed.

  Lemma id_int_term : e t k, int_term t (def_intt e 0) k = t.
simple induction t; simpl in |- *; intros; auto with coc core arith datatypes.
elim (le_gt_dec k n); intros; auto with coc core arith datatypes.
rewrite def_intt_id.
simpl in |- *; unfold lift in |- ×.
rewrite lift_ref_ge; auto with coc core arith datatypes.

rewrite H; rewrite H0; auto with coc core arith datatypes.

rewrite H; rewrite H0; auto with coc core arith datatypes.

rewrite H; rewrite H0; auto with coc core arith datatypes.
Qed.

  Theorem str_norm : e t T, typ e t Tsn t.
intros.
cut (is_can PROP (int_typ T (def_intp e) PROP));
 auto with coc core arith datatypes.
simpl in |- *; intros.
cut (int_typ T (def_intp e) PROP t).
elim H0; auto with coc core arith datatypes.

elim id_int_term with e t 0.
apply int_sound with e; auto with coc core arith datatypes.
apply def_adapt.
apply typ_wf with t T; auto with coc core arith datatypes.

apply int_typ_cr; auto with coc core arith datatypes.
Qed.

  Lemma type_sn : e t T, typ e t Tsn T.
intros.
elim type_case with e t T; intros; auto with coc core arith datatypes.
elim H0; intros.
apply str_norm with e (Srt x); auto with coc core arith datatypes.

rewrite H0.
red in |- *; apply Acc_intro; intros.
inversion_clear H1.
Qed.