From Undecidability.TM.Combinators Require Export Switch If SequentialComposition StateWhile While Mirror.


Section Id.
  Variable (sig : finType) (n : ).
  Variable (F : finType).

  Variable (pM : pTM sig F n).

  Definition Id := pM.
End Id.

Section Relabel.
  Variable (sig : finType) (n : ).
  Variable F F' : finType.
  Variable pM : { M : TM sig n & state M F }.
  Variable p : F F'.

  Definition Relabel : pTM sig F' n :=
    ( pM; q p ( pM q)).

  Lemma Relabel_Realise R :
    pM R
    Relabel _y (R |_ y) ||_(p y).
  Proof.
    intros HRel.
    intros tin k outc HLoop.
    hnf in HRel. specialize HRel with (1 := HLoop).
    hnf. exists ( pM (cstate outc)). hnf. cbn. auto.
  Qed.


  Lemma Relabel_RealiseIn R k :
    pM c(k) R
    Relabel c(k) _y (R |_ y) ||_(p y).
  Proof. firstorder. Qed.

  Lemma Relabel_Terminates T :
     pM T
     Relabel T.
  Proof. firstorder. Qed.

End Relabel.

Arguments Relabel : simpl never.

Section Return.

  Variable (sig : finType) (n : ).
  Variable F : finType.
  Variable pM : { M : TM sig n & state M F }.
  Variable F' : finType.
  Variable p : F'.

  Definition Return := Relabel pM ( _ p).

  Lemma Return_Realise R :
    pM R
    Return (_f (R |_ f)) ||_ p.
  Proof. intros. intros tin k outc HLoop. hnf. split; hnf; eauto. exists ( pM (cstate outc)). hnf. eauto. Qed.

  Lemma Return_RealiseIn R k :
    pM c(k) R
    Return c(k) (_f (R |_ f)) ||_ p.
  Proof. firstorder. Qed.

  Lemma Return_Terminates T :
     pM T
     Return T.
  Proof. firstorder. Qed.

End Return.

Arguments Return : simpl never.



Local Ltac print e := idtac. Local Tactic Notation "print_str" string() := idtac. Local Tactic Notation "print2" ident() string() := idtac. Local Ltac print_type e := first [ let x := type of e in print x | print_str "Untyped:"; print e ].

Ltac print_goal_cbn :=
  match goal with
  | [ |- ?H ]
    let H' := eval cbn in H in print H'
  end.

Export Set Warnings "-unused-intro-pattern".

Ltac destruct_shelve e :=
  cbn in e;
  print_str "Input:";
  print_type e;
  print_str "Output:";
  print_goal_cbn;
  let := fresh "x" in
  let := fresh "x" in
  let := fresh "x" in
  let := fresh "x" in
  let := fresh "x" in
  let := fresh "x" in
  let := fresh "x" in
  let := fresh "x" in
  let := fresh "x" in
  first [ destruct e as [||||||||]; e "has 9 constructors"; [ try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve ]; shelve
        | destruct e as [|||||||]; e "has 8 constructors"; [ try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve ]; shelve
        | destruct e as [||||||]; e "has 7 constructors"; [ try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve ]; shelve
        | destruct e as [|||||]; e "has 6 constructors"; [ try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve ]; shelve
        | destruct e as [||||]; e "has 5 constructors"; [ try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve ]; shelve
        | destruct e as [|||]; e "has 4 constructors"; [ try destruct_shelve | try destruct_shelve | try destruct_shelve | try destruct_shelve ]; shelve
        | destruct e as [||]; e "has 3 constructors"; [ try destruct_shelve | try destruct_shelve | try destruct_shelve ]; shelve
        | destruct e as [|]; e "has 2 constructors"; [ try destruct_shelve | try destruct_shelve ]; shelve
        | destruct e as []; e "has 1 constructors"; [ try destruct_shelve ]; shelve
        | destruct e as []; e "has 0 constructors"; shelve
        ]
.


Ltac smpl_match_case_solve_RealiseIn :=
  eapply RealiseIn_monotone'; [ | shelve].

Definition TM_Correct_noSwitchAuto := unit.
Opaque TM_Correct_noSwitchAuto.
Ltac TM_Correct_noSwitchAuto := let f := fresh "flag" in assert (f := (tt:TM_Correct_noSwitchAuto)).

Ltac smpl_match_RealiseIn :=
  once lazymatch goal with
  | H : TM_Correct_noSwitchAuto |- _ eapply Switch_RealiseIn with (:= x _ );[TM_Correct| ]
  | [ |- Switch ? ? c(?) ?R]
    is_evar R;
    let := type of in
    let x := fresh "x" in
    match with
    | ?F _
      eapply (Switch_RealiseIn
                (F := FinType(EqType F))
                ( := ltac:(now ( intros x; destruct_shelve x))));
      [
        smpl_match_case_solve_RealiseIn
      | intros x; repeat destruct _; smpl_match_case_solve_RealiseIn
      ]
    end
  end
.

Ltac smpl_match_Realise :=
  once lazymatch goal with
  | H : TM_Correct_noSwitchAuto |- _ eapply Switch_Realise with (:= x _ );[TM_Correct| ]
  | [ |- Switch ? ? ?R]
    is_evar R;
    let := type of in
    let x := fresh "x" in
    match with
    | ?F _
      eapply (Switch_Realise
                (F := FinType(EqType F))
                ( := ltac:(now (intros x; destruct_shelve x))));
      [
      | intros x; repeat destruct _
      ]
    end
  end.

Ltac smpl_match_Terminates :=
  once lazymatch goal with
  | H : TM_Correct_noSwitchAuto |- _ eapply Switch_TerminatesIn with (:= x _ );[TM_Correct|TM_Correct | ]
  | [ |- (Switch ? ?) ?R]
    is_evar R;
    let := type of in
    let x := fresh "x" in
    match with
    | ?F _
      eapply (Switch_TerminatesIn
                (F := FinType(EqType F))
                ( := ltac:(now (intros x; destruct_shelve x))));
      [
      |
      | intros x; repeat destruct _
      ]
    end
  end.

Ltac smpl_TM_Combinators :=
  once lazymatch goal with
  | [ |- Switch _ _ _] smpl_match_Realise
  | [ |- Switch _ _ c(_) _] smpl_match_RealiseIn
  | [ |- (Switch _ _) _] smpl_match_Terminates
  | [ |- If _ _ _ _] eapply If_Realise
  | [ |- If _ _ _ c(_) _] eapply If_RealiseIn
  | [ |- (If _ _ _) _] eapply If_TerminatesIn
  | [ |- Seq _ _ _] eapply Seq_Realise
  | [ |- Seq _ _ c(_) _] eapply Seq_RealiseIn
  | [ |- (Seq _ _) _] eapply Seq_TerminatesIn
  | [ |- While _ _] eapply While_Realise
  | [ |- (While _) _] eapply While_TerminatesIn
  | [ |- StateWhile _ _ _] eapply StateWhile_Realise
  | [ |- (StateWhile _ _) _] eapply StateWhile_TerminatesIn
  | [ |- Relabel _ _ _] eapply Relabel_Realise
  | [ |- Relabel _ _ c(_) _] eapply Relabel_RealiseIn
  | [ |- (Relabel _ _) _] eapply Relabel_Terminates
  | [ |- Return _ _ _] eapply Return_Realise
  | [ |- Return _ _ c(_) _] eapply Return_RealiseIn
  | [ |- (Return _ _) _] eapply Return_Terminates
  end.

Smpl Add smpl_TM_Combinators : TM_Correct.