Require Import CBN.CBN_CBPV CBN.weakStory.

Translation and substitution commute


Lemma subst_pointwise m n ( : fin m value n) s :
  ( i, star sstep (force ( i)) (force ( i)))
  star sstep ((eval s)[]) ((eval s)[]).
Proof.
  revert n . induction s; cbn; intros; eauto.
  all: try now (rewrite IHs; eauto).
  all: try now (rewrite , ; eauto).
  - rewrite IHs. reflexivity. auto_case.
    asimpl. unfold funcomp.
    change (( f)⟨ !) with ((( f)!)⟨).
    now rewrite H.
  - rewrite !eagerlet_substcomp, . asimpl.
    rewrite , . reflexivity.
    + auto_case.
      unfold funcomp.
      change (( f)⟨ x : fin n (↑ x) !) with (( f)! x : fin n (↑ x) ).
      now rewrite H.
    + auto_case.
      unfold funcomp.
      change (( f)⟨ x : fin n (↑ x) !) with (( f)! x : fin n (↑ x) ).
      now rewrite H.
    + eauto.
Qed.


Lemma subst_pres m n ( : fin m exp n) s :
  star sstep ((eval s)[eval_subst ]) (eval (s[])).
Proof.
  revert n . induction s; cbn; intros; eauto.
  - unfold eval_subst. destruct ( f); eauto.
  - now rewrite eval_subst_up_value_value, IHs.
  - now rewrite , .
  - now rewrite , .
  - now rewrite IHs.
  - now rewrite IHs.
  - rewrite !eagerlet_substcomp, .
    rewrite !eval_subst_up_value_value.
    eapply proper_eagerlet_star_ssstep_R. reflexivity.
    rewrite , .
    eapply refl_star. asimpl. f_equal.
    all: change (_ .: >> ) with (up_exp_exp ).
    all: rewrite eval_subst_up_value_value; asimpl.
    all: reflexivity.
Qed.


Strong reduction CBN


Reserved Notation "s ≫ t" (at level 60).

Set Implict Arguments.

Inductive Step {n} : exp n exp n Prop :=
  | StepLam (M M' : exp (S n)) : @Step (S n) M M' Step (Lam M) (Lam M')

  | StepApp1 (M : exp n) M' N : Step M M' Step (App M N) (App M' N)
  | StepApp2 (M : exp n) N N' : Step N N' Step (App M N) (App M N')
  | StepAppLam (M : exp (S n)) M' (N: exp n): M' = M[N..] Step (App ((Lam M)) (N)) M'

  | StepPair1 (M M' N : exp n) : Step M M' Step (Pair M N) (Pair M' N)
  | StepPair2 (M N N' : exp n) : Step N N' Step (Pair M N) (Pair M N')

  | StepInj b (M M' : exp n) : Step M M' Step (Inj b M) (Inj b M')

  | StepProj b (M M' : exp n) : Step M M' Step (Proj b M) (Proj b M')
  | StepProjPair b (M M' : exp n) : Step (Proj b (Pair M M')) (if b then M else M')

  | StepCaseS1 (M : exp n) M' : Step M M' Step (CaseS M ) (CaseS M' )
  | StepCaseS2 (M : exp n) ( : exp (S n)) : @Step _ Step (CaseS M ) (CaseS M )
  | StepCaseS3 (M : exp n) : @Step (S n) Step (CaseS M ) (CaseS M )
  | StepCaseS b (M : exp n) : Step (CaseS (Inj b M) ) (if b then else )[M..]
where "s ≫ t" := (@Step _ s t).
Hint Constructors Step.

Forward simulation

Reduction tactic for beta reduction step
(* Duplicate, should remove at some point *)
Ltac reduce := econstructor 2; [ solve [eauto] | cbn ].

Ltac dostep :=
  match goal with
  | [ |- star _ _ _ ] econstructor; [ eapply sstepPrimitive; repeat econstructor | ]
  | [ |- plus _ _ _ ] eapply step_star_plus; [ eapply sstepPrimitive; repeat econstructor | ]
  end.

Lemma beta_step_preserved m (s : exp (S m)) (t : exp m) :
  star sstep ((eval s)[(thunk (eval t))..]) (eval (s[t..])).
Proof.
  rewrite (subst_pres _ _ (t..) s).
  erewrite subst_pointwise. reflexivity.
  intros []. cbn. reflexivity.
  cbn. destruct t; try reflexivity.
  cbn. now dostep.
Qed.


Lemma Step_preserved {n: } (s t : exp n) :
  Step s t (plus sstep) (eval s) (eval t).
Proof.
  induction 1; cbn; asimpl; try now trewrite IHStep.
  - dostep. subst. now rewrite beta_step_preserved.
  - destruct b; eauto.
  - trewrite IHStep; try reflexivity.
    hnf. intros.
    eapply proper_eagerlet_plus_sstep_L. eauto. intros; cbn; asimpl; eapply step_star_plus; eauto.
  - trewrite IHStep; try reflexivity.
    hnf. intros.
    eapply proper_eagerlet_plus_sstep_R; eauto.
    eapply plus_proper_sstep_caseS2; eauto.
    substify. now eapply plus_sstep_preserves.
  - trewrite IHStep; try reflexivity.
    hnf. intros.
    eapply proper_eagerlet_plus_sstep_R; eauto.
    eapply plus_proper_sstep_caseS3; eauto.
    substify. now eapply plus_sstep_preserves.
  - eapply step_star_plus. eauto.
    destruct b; now eapply beta_step_preserved.
Qed.


Lemma Steps_preserved {n: } (s t : exp n) :
  star Step s t (star sstep) (eval s) (eval t).
Proof.
  induction 1.
  - reflexivity.
  - rewrite IHstar. eapply plus_star. now eapply Step_preserved.
Qed.


Lemma terminal_step n (s : exp n) :
  Normal Step s Normal sstep (eval s).
Proof.
  intros ? ? ?; induction s; cbn in *.
  - inv . inv . inv .
  - inv . inv . inv .
  - inv . eapply IHs. intros ? ?. eapply H. eauto. eauto. inv .
  - inv .
    + eapply . intros ? ?. eapply H. eauto. eauto.
    + inv . eapply . intros ? ?. eapply H. eauto. eauto.
    + inv . destruct ; inv . eapply H. eauto.
      destruct (eval s1_1); inv .
  - inv .
    + eapply . intros ? ?. eapply H. eauto. eauto.
    + eapply . intros ? ?. eapply H. eauto. eauto.
    + inv .
  - inv .
    + eapply IHs. intros ? ?. eapply H. eauto. eauto.
    + inv . destruct s; inv . eapply H. eauto.
      destruct (eval ); inv .
  - inv . inv . inv .
    + eapply IHs. intros ? ?. eapply H. eauto. eauto.
    + inv .
  - destruct (eagerlet_inv (eval ) (caseS (var_value var_zero) (ren_comp ren_up (eval )) (ren_comp ren_up (eval )))) as [ [HH HHH ] | [V [] ] ].
    cbn in *. rewrite HH in .
    inv .
    + eapply . intros ? ?. eapply H. eauto. eauto.
    + inv . inv .
      * eapply step_ren_comp_inv in as (? & ? & ?); subst. 2:reflexivity.
        eapply . intros ? ?. eapply H. eauto. eauto.
      * eapply step_ren_comp_inv in as (? & ? & ?); subst. 2:reflexivity.
        eapply . intros ? ?. eapply H. eauto. eauto.
      * inv .
    + inv . destruct ; inv .
      * eapply HHH. cbn. eauto.
      * eapply H. eauto.
      * destruct (eval s1_1); inv .
    + destruct ; inv e.
      * inv . cbn in . inv .
        -- inv .
        -- asimpl in . eapply ; eauto. intros ? ?; eapply H; eauto.
        -- asimpl in . eapply ; eauto. intros ? ?; eapply H; eauto.
        -- inv .
      * eapply H. eauto.
      * destruct (eval s1_1); inv .
Qed.


Lemma evaluates_forward n (s t : exp n) :
  evaluates Step s t evaluates sstep (eval s) (eval t).
Proof.
  intros []. split.
  - clear . induction H.
    + reflexivity.
    + etransitivity; try eassumption.
      now eapply plus_star, Step_preserved.
  - now eapply terminal_step.
Qed.


Lemma SN_CBN n s :
  SN (@sstep n) (eval s) SN (@Step n) s.
Proof.
  intros. remember (eval s) as C eqn:E. revert s E.
  eapply SN_plus in H. induction H.
  econstructor. subst.
  intros ? ? % Step_preserved. eauto.
Qed.


Backward Simulation


Instance proper_Step_Pair n :
  Proper (star Step eq star Step) (@Pair n).
Proof.
  cbv. intros; subst. induction H; eauto.
Qed.


Instance proper_Step_Pair2 n :
  Proper (eq star Step star Step) (@Pair n).
Proof.
  cbv. intros; subst. induction ; eauto.
Qed.


Instance proper_Step_App n :
  Proper (star Step eq star Step) (@App n).
Proof.
  cbv. intros; subst. induction H; eauto.
Qed.


Instance proper_Step_App2 n :
  Proper (eq star Step star Step) (@App n).
Proof.
  cbv. intros; subst. induction ; eauto.
Qed.


Instance proper_Step_Lam n :
  Proper (star Step star Step) (@Lam n).
Proof.
  cbv. intros; subst. induction H; eauto.
Qed.


Instance proper_Step_Proj n :
  Proper (eq star Step star Step) (@Proj n).
Proof.
  cbv. intros; subst. induction ; eauto.
Qed.


Instance proper_Step_Inj n :
  Proper (eq star Step star Step) (@Inj n).
Proof.
  cbv. intros; subst. induction ; eauto.
Qed.


Instance proper_Step_Case n :
  Proper (star Step eq eq star Step) (@CaseS n).
Proof.
  cbv. intros; subst. induction H; eauto.
Qed.


Instance proper_Step_Case2 n :
  Proper (eq star Step eq star Step) (@CaseS n).
Proof.
  cbv. intros; subst. induction ; eauto.
Qed.


Instance proper_Step_Case3 n :
  Proper (eq eq star Step star Step) (@CaseS n).
Proof.
  cbv. intros; subst. induction ; eauto.
Qed.


Lemma Step_inj_inv n (s s'' : exp n) b :
  star Step (Inj b s) s'' s', s'' = Inj b s' star Step s s'.
Proof.
  remember (Inj b s) as t. intros H. revert s Heqt; induction H; intros; subst.
  - eauto.
  - inv H. edestruct IHstar as (? & &?); eauto.
Qed.


Lemma refines_to_eval n (C : comp n) s :
  C s t, C ↪* eval t star Step s t.
Proof.
  induction 1; cbn.
  - exists (var_exp x). cbn. eauto.
  - exists One. cbn. eauto.
  - destruct IHX as (t & ? & ?). exists (Lam t).
    rewrite H, . eauto.
  - destruct as ( & ? & ?).
    destruct as ( & ? & ?). exists (App ).
    rewrite H, , , . eauto.
  - destruct as ( & ? & ?).
    destruct as ( & ? & ?). exists (Pair ).
    rewrite H, , , . eauto.
  - destruct IHX as (t & ? & ?). exists (Proj b t).
    rewrite H, . eauto.
  - destruct IHX as (t & ? & ?). exists (Inj b t).
    rewrite H, . eauto.
  - destruct as (s' & ? & ?).
    destruct as ( & ? & ?).
    destruct as ( & ? & ?).
    exists (CaseS s' ). subst.
    rewrite H, , , , , . split. 2:eauto.
    now rewrite let_to_eagerlet.
  - destruct as (s' & ? & ?).
    destruct as ( & ? & ?).
    destruct as ( & ? & ?).
    inv .
    + eapply ret_star_inv in H as (? & ? & ?).
      inv . inv H. 2:inv . asimpl.
      eexists. split. 2: now rewrite , . cbn. asimpl. now rewrite , .
    + eapply ret_star_inv in H as (? & ? & ?). destruct s'; inv H.
      eapply inj_star_inv in as (? & ? & ?). inv H.
      eapply Step_inj_inv in as (? & ? & ?). inv H.
      destruct b; eexists; split.
      * rewrite , . rewrite at 1. econstructor. eauto. asimpl. eapply beta_step_preserved.
      * rewrite , . eauto.
      * rewrite , . rewrite at 1. econstructor. eauto. asimpl. eapply beta_step_preserved.
      * rewrite , . eauto.
      * destruct (eval ); inv .
  - destruct IHX as (t & ? & ?). eauto.
Qed.


Ltac slv HH := let H := fresh "H" in
  edestruct HH as (? & [] & H); eauto;
  try eexists; split; [ | now rewrite H]; (do 10 try econstructor); eauto.

Lemma refines_step n (C C' : comp n) s : sstep C C' C s t, inhab (C' t) star Step s t.
Proof.
  intros . revert C' . induction ; cbn; intros; inv .
  all: try solve [invp @sstep || invp @sstep_value || invp @pstep].
  all: try now slv IHrefines.
  all: try now slv .
  all: try now slv .
  - inv . slv .
  - inv H. inv H2_. eexists. split.
    + econstructor. eapply refines_beta; eauto.
    + eauto.
  - inv H. inv . destruct b; eauto.
  - inv . inv . slv IHrefines.
  - edestruct as (? & [] & H); eauto.
    eexists. split. 2: now rewrite H. asimpl. eauto.
  - inv . inv .
    + eapply step_ren_comp_inv in as (? & ? & ); eauto.
      edestruct as (? & [] & HH); eauto.
      eexists. split. 2: now rewrite HH. asimpl. eauto.
    + eapply step_ren_comp_inv in as (? & ? & ); eauto.
      edestruct as (? & [] & HH); eauto.
      eexists. split. 2: now rewrite HH. asimpl. eauto.
    + inv H.
  - inv H. inv H2_.
    + eexists. split. econstructor. repeat econstructor; eauto. reflexivity.
    + eexists. split. econstructor. repeat econstructor; eauto. reflexivity.
  - inv H2_. inv . inv . inv .
    edestruct as (? & [] & ?). eauto. inv .
    eexists. split. econstructor. 2:rewrite H. 2:reflexivity.
    destruct b.
    + eapply refines_help. eapply refines_CaseS2. 4: asimpl; cbn; now asimpl. all:eauto.
    + eapply refines_help. eapply refines_CaseS2. 4: asimpl; cbn; now asimpl. all:eauto.
  - asimpl in . inv H2_.
    * edestruct as (? & [] & ?). eauto.
      eexists. split. econstructor. eapply refines_help.
      eapply refines_CaseS2. 4: now asimpl. all:eauto. now rewrite H.
    * edestruct as (? & [] & ?). eauto.
       eexists. split. econstructor. 2:rewrite H. 2:reflexivity.
       destruct b.
       -- eapply refines_help. eapply refines_CaseS2. 4: asimpl; cbn; now asimpl. all:eauto.
       -- eapply refines_help. eapply refines_CaseS2. 4: asimpl; cbn; now asimpl. all:eauto.
  - asimpl in . inv H2_.
    + edestruct as (? & [] & ?). eauto.
      eexists. split. econstructor. eapply refines_help.
      eapply refines_CaseS2. 4: now asimpl. all:eauto. now rewrite H.
    + edestruct as (? & [] & ?). eauto.
      eexists. split. econstructor. 2:rewrite H. 2:reflexivity.
      destruct b.
      * eapply refines_help. eapply refines_CaseS2. 4: asimpl; cbn; now asimpl. all:eauto.
      * eapply refines_help. eapply refines_CaseS2. 4: asimpl; cbn; now asimpl. all:eauto.
  - asimpl in H. inv H. inv H2_.
    destruct b.
    + eexists. split. econstructor. eapply refines_beta; eauto. eauto.
    + eexists. split. econstructor. eapply refines_beta; eauto. eauto.
  - inv . eapply IHrefines in as (? & [] & ?). eauto.
  - inv H. eauto.
Qed.


Lemma refines_steps n (C C' : comp n) s : star sstep C C' C s t, inhab (C' t) star Step s t.
Proof.
  intros H. revert s; induction H; cbn; intros.
  - eauto.
  - eapply refines_step in H as (? & [] & ?); eauto.
    edestruct IHstar as (? & ? & ?); eauto.
Qed.


Lemma Steps_backwards {n: } (s : exp n) (C: comp n) :
   eval s ↪* C t : exp n, C ↪* eval t star Step s t.
Proof.
  intros. pose proof (trans_refines _ _ _ (trans_eval s)).
  eapply refines_steps in X as (t & [] & ?); eauto.
  eapply refines_to_eval in X as (t' & ? & ?). eauto.
Qed.


Require Import Confluence.

Notation "s ↪+ t" := (plus sstep s t) (at level 58).

Lemma confluence n :
  confluent (@Step n).
Proof.
  intros ? ? ? ? % Steps_preserved ? % Steps_preserved.
  eapply confluence in . specialize ( ) as [].
  eapply refines_steps in H as (? & [] & ?). 2:eapply trans_refines, trans_eval.
  eapply refines_steps in as (? & [] & ?). 2:eapply trans_refines, trans_eval.
  assert ( = ) as by (eapply refines_functional; eauto).
  firstorder.
Qed.


Lemma evaluates_backwards n (s : exp n) C :
  evaluates sstep (eval s) C t, C = eval t evaluates Step s t.
Proof.
  intros []. eapply Steps_backwards in H as (t & ? & ?).
  inv H.
  + exists t; repeat split; eauto. intros ? ?. eapply Step_preserved in H. inv H; eapply ; eauto.
  + firstorder.
Qed.