From Undecidability.TM Require Import Util.TM_facts.

Set Default Proof Using "Type".

Section CaseChar2.
  Variable sig : finType.
  Variable (F : finType) (f : option sig option sig F).

  Definition CaseChar2_TM : TM sig 2 :=
    {|
      trans := '(_, sym) (Some (f sym[@] sym[@]), [| (None, Nmove); (None, Nmove) |]);
      start := None;
      halt := s match s with
                    | None false
                    | Some _ true
                    end;
    |}.

  Definition : pTM sig F 2 := (CaseChar2_TM; s match s with None f None None | Some y y end).

  Definition CaseChar2_Rel : pRel sig F 2 :=
     t '(y, t')
      y = f (current t[@]) (current t[@])
      t' = t.

  Definition CaseChar2_Sem : c(1) CaseChar2_Rel.
  Proof.
    intros t. destruct_tapes. cbn. unfold initc; cbn. cbv [step]; cbn. unfold current_chars; cbn.
    eexists (mk_mconfig _ _); cbv [step]; cbn. split. eauto. cbn. auto.
  Qed.


End CaseChar2.

Arguments : simpl never.
Arguments {sig F} f.
Arguments CaseChar2_Rel sig F f x y /.

Section ReadChar2.

  Variable sig : finType.

  Definition : pTM sig (option sig * option sig) 2 := pair.

  Definition ReadChar2_Rel : pRel sig (option sig * option sig) 2 :=
     t '(y, t')
      y = (current t[@], current t[@])
      t' = t.

  Lemma ReadChar2_Sem : c(1) ReadChar2_Rel.
  Proof.
    eapply RealiseIn_monotone.
    - apply CaseChar2_Sem.
    - reflexivity.
    - intros tin (yout, tout) (&). hnf. split; auto.
  Qed.


End ReadChar2.

Arguments : simpl never.
Arguments {sig}.
Arguments ReadChar2_Rel sig x y /.


Ltac smpl_TM_Duo :=
  once lazymatch goal with
  | [ |- _ _] eapply RealiseIn_Realise; eapply CaseChar2_Sem
  | [ |- _ c(_) _] eapply CaseChar2_Sem
  | [ |- ( _) _] eapply RealiseIn_TerminatesIn; eapply CaseChar2_Sem
  | [ |- _] eapply RealiseIn_Realise; eapply ReadChar2_Sem
  | [ |- c(_) _] eapply ReadChar2_Sem
  | [ |- () _] eapply RealiseIn_TerminatesIn; eapply ReadChar2_Sem
  end.

Smpl Add smpl_TM_Duo : TM_Correct.