Library Tait.TaitEtaRed


Require Export TaitCore.
Require Export Eta.
Require Export WN.

Module RequirementsProofEtaRed <: Requirements.

 Inductive N (rhos:context)(rho:type)(r s:term) : Prop :=
   N_intro : forall t, WN r t -> eta_red t = s -> N rhos rho r s.

 Definition abstr (k:nat)(rho:type)(r:term) :=
  if is_eta_core r k then left_app r else \rho, sub_swap0 r k.

 Notation " \! k : rho , r " := (abstr k rho r) (at level 20, k at level 99).

 Lemma Ax1 : forall r s rhos rho sigma k,
  F rhos (rho-->sigma) r k ->
  N (rhos++ext_ctx rhos k rho) sigma (r;k) s ->
  N rhos (rho-->sigma) r (\!k:rho, s).
 Proof.
 intros.
 set (u:=r;k).
 assert (u=r;k).
  auto.
 clearbody u.
 rewrite <- H1 in H0.
 destruct H0.
 generalize H2 H1 H; clear H2 H1 H.
 generalize r s k rho sigma; clear r s k rho sigma.
 induction H0; intros.

 destruct l as [|t0 l0].
 inversion H1.
 destruct l' as [|t0' l0'].
 inversion H.
 destruct (@exists_last _ (t0::l0)) as [l (t,Htl)]; try discriminate.
  rewrite Htl in H; rewrite Htl in H1; clear Htl t0 l0.
 destruct (@exists_last _ (t0'::l0')) as [l' (t',Htl)]; try discriminate.
  rewrite Htl in H; rewrite Htl in H2; clear Htl t0' l0'.
 rewrite <- apps_app in H1; simpl in H1.
 injection H1; clear H1; intros; subst.
 destruct (WNs_last _ _ _ _ H); clear H; intros.
 assert (t'=[k]).
   inversion H2.
   replace [k] with ([k];;nil) in H; auto.
   assert (H5:=apps_form_unique2 _ _ _ _ H).
   intuition; subst.
   inversion H3; auto.
   replace [k] with ([k];;nil) in H; auto.
   replace (((\ rho0, r); s);; l0) with ((\ rho0, r);; (s::l0)) in H; auto.
   assert (H5:=apps_form_unique1 _ _ _ _ H).
   intuition; discriminate.
 subst; clear H2.
 exists (n;;l').
 apply WN_var; auto.
 rewrite <- apps_app; simpl.
 unfold abstr.
 simpl.
 unfold is_eta_core.
 simpl.
 destruct (term_dec [k] [k]); intuition.
 simpl.
 assert (occurs k (eta_red (n;;l'))=false).
  rewrite eta_red_occurs.
  apply WN_occurs with (n;;l); auto.
  eapply F_occurs; eauto.
 rewrite H; auto.

 discriminate.

 destruct l.
 clear IHWN.
 simpl in *.
 injection H1; clear H1; intros.
 subst.
 assert (rho0 = rho).
  destruct H.
  destruct H.
  simpl in H2; injection H2; auto.
 subst.
 assert (S1 : sub1 k = (map Var (k::nil))#0); auto.
 rewrite S1 in H0.
 destruct (WN_subk H0 (k::nil) 0 r) as [t0 (H2,H3)]; auto.
 rewrite <- S1 in H0; rewrite <- S1 in H2; clear S1.
 exists (\rho, t0).
 apply WN_abs; auto.
 subst t; rename t0 into t.
 rewrite eta_subk.
 unfold abstr; simpl.
 assert (occurs (S k) t = false).
  apply WN_occurs with r; auto.
  replace (occurs (S k) r) with (occurs k (\rho,r)); auto.
  eapply F_occurs; eauto.
 rewrite <- eta_core_sub; try rewrite eta_red_occurs; auto.
 dcase (is_eta_core (eta_red t) 0); intros.
 unfold is_eta_core in H2.
 destruct (eta_red t); simpl in H2; try discriminate.
 simpl.
 destruct (term_dec t0_2 [0]); simpl in H2; try discriminate.
 subst; simpl.
 rewrite (down_sub t0_1 0 [k]); auto.
 replace false with (negb true); auto; apply negb_sym; auto.
 rewrite sub_sub_swap0; auto.
 red; intros; rewrite eta_red_occurs.
 apply WN_occurs with r; auto.
 rewrite (S_pred n 0); try omega.
 change (occurs (pred n) (\rho, r) = false).
 apply F_occurs with rhos (rho-->sigma); split; destruct H; auto; omega.

 destruct (@exists_last _ (t0::l)) as [l' (t',Htl)]; try discriminate.
 rewrite Htl in H1; rewrite Htl in H0; rewrite Htl in IHWN; clear Htl t0 l.
 simpl in H1; rewrite <- apps_app in H1; simpl in H1.
 injection H1; clear H1; intros.
 subst t'.
 destruct (IHWN ((sub r s);;l') s0 k rho0 sigma); auto.
  rewrite <- apps_app; auto.
  subst r0.
  destruct H; red; intuition.
  elim H; intros.
  assert (CorTyp rhos ((\rho,r);s)).
   eapply CorTyp_apps;eauto.
  inversion H5; subst.
  inversion H8; subst.
  simpl in H11; injection H11; clear H1; intros.
  apply TypJ_apps with ((\ rho, r); s) sigma0; auto.
  replace rhos with (nil++rhos); auto.
  apply TypJ_sub1 with (rho::nil); auto.
  intros.
  simpl in H6.
  inversion H6; auto.
  inversion H12.
 exists t0; auto.
 subst.
 change (((\ rho, r); s);; l') with ((\rho,r);;(s::l')); auto.
 Qed.

 Inductive A (rhos:context): type -> term -> term -> Prop :=
 | AVar : forall rho k, A rhos rho [k] [k]
 | AApp : forall rho sigma r s r' s',
   A rhos (rho-->sigma) r s -> N rhos rho r' s' -> A rhos sigma (r;r') (s;s').
 Hint Constructors A.

 Inductive H' : term -> term -> Prop :=
  | H'_intro : forall rho r s l, H' ((\rho,r;s);;l) ((sub r s);;l).
 Hint Constructors H'.

 Definition H (rhos:context)(rho:type)(r s:term) := H' r s.
 Hint Unfold H.

 Lemma A_apps : forall rhos rho r s, A rhos rho r s ->
   exists n:nat, exists l, exists l', r = n;;l /\ s = n;;(map eta_red l') /\
     WNs l l'.
 Proof.
 induction 1.
 exists k; exists (nil:list term); exists (nil:list term); intuition.
 destruct IHA as [n (l,(l',(H2,(H3,H4))))].
 destruct H1.
 exists n; exists (l++r'::nil); exists (l'++t::nil).
 rewrite map_app; simpl.
 do 2 rewrite <- apps_app.
 subst; intuition.
 Qed.

 Lemma Ax2_gen : forall rhos r s rho, A rhos rho r s -> N rhos rho r s.
 Proof.
 intros.
 destruct (A_apps _ _ _ _ H0) as [n (l,(l',(H2,(H3,H4))))].
 exists (n;;l').
 subst; constructor; auto.
 subst.
 assert (forall l r, eta_red (r;;l) = (eta_red r);;(map eta_red l)).
 clear H0 H4 l rho n l l'.
 induction l.
 simpl; auto.
 simpl; intros; rewrite IHl; auto.
 rewrite H1; simpl; auto.
 Qed.

 Lemma Ax2 : forall rhos r s, A rhos Iota r s -> N rhos Iota r s.
 Proof.
 intros; apply Ax2_gen; auto.
 Qed.

 Lemma Ax3 : forall rhos rho k, TypJ rhos [k] rho -> A rhos rho [k] [k].
 Proof.
 auto.
 Qed.

 Lemma Ax4 : forall rhos rho sigma r r' s s', TypJ rhos s rho ->
  A rhos (rho-->sigma) r r' -> N rhos rho s s' -> A rhos sigma (r;s) (r';s').
 Proof.
 eauto.
 Qed.

 Lemma Ax5 :
   forall rhos rho r s t, H rhos rho r s -> N rhos rho s t -> N rhos rho r t.
 Proof.
 unfold H.
 destruct 1.
 destruct 1.
 exists t0; auto.
 generalize (WN_beta rho0 r s l H0); simpl; auto.
 Qed.

 Lemma Ax6 : forall rhos rho sigma r s rs,
  H rhos sigma ((sub (\rho,r) rs);s) (sub r ((s::rs)#(rs.(shift)))).
 Proof.
 intros; red; simpl.
 rewrite <- Sub_Sub_Ad_Hoc.
 exact (H'_intro rho _ _ nil).
 Qed.

 Lemma Ax7 : forall rhos rho sigma r s t,
  H rhos (rho-->sigma) r s -> H rhos sigma (r;t) (s;t).
 Proof.
 destruct 1; red.
 generalize (H'_intro rho0 r s (l++t::nil)).
 do 2 rewrite <- apps_app; auto.
 Qed.

 Lemma Ax_H_ext_ctx : forall rhos sigmas rho r s, TypJ rhos r rho ->
  H rhos rho r s -> H (rhos++sigmas) rho r s.
 Proof.
 auto.
 Qed.


End RequirementsProofEtaRed.

Module CompleteEtaRedProof :=
 NormalizationProof(RequirementsProofEtaRed).

Require Export TaitCoreNc.

Module CompleteEtaRedProofNc :=
 NormalizationProofNc(RequirementsProofEtaRed).