Inductive tm : Type :=
  | ttrue : tm
  | tfalse : tm
  | tif : tm -> tm -> tm -> tm
  | tzero : tm
  | tsucc : tm -> tm
  | tpred : tm -> tm
  | tiszero : tm -> tm.Inductive tm : Type :=
  | ttrue : tm
  | tfalse : tm
  | tif : tm -> tm -> tm -> tm
  | tzero : tm
  | tsucc : tm -> tm
  | tpred : tm -> tm
  | tiszero : tm -> tm.Inductive tm : Type :=
  | ttrue : tm
  | tfalse : tm
  | tif : tm -> tm -> tm -> tm
  | tzero : tm
  | tsucc : tm -> tm
  | tpred : tm -> tm
  | tiszero : tm -> tm.Inductive tm : Type :=
  | ttrue : tm
  | tfalse : tm
  | tif : tm -> tm -> tm -> tm
  | tzero : tm
  | tsucc : tm -> tm
  | tpred : tm -> tm
  | tiszero : tm -> tm.Inductive tm : Type :=
  | ttrue : tm
  | tfalse : tm
  | tif : tm -> tm -> tm -> tm
  | tzero : tm
  | tsucc : tm -> tm
  | tpred : tm -> tm
  | tiszero : tm -> tm.Inductive tm : Type :=
  | ttrue : tm
  | tfalse : tm
  | tif : tm -> tm -> tm -> tm
  | tzero : tm
  | tsucc : tm -> tm
  | tpred : tm -> tm
  | tiszero : tm -> tm.Inductive tm : Type :=
  | ttrue : tm
  | tfalse : tm
  | tif : tm -> tm -> tm -> tm
  | tzero : tm
  | tsucc : tm -> tm
  | tpred : tm -> tm
  | tiszero : tm -> tm.Inductive tm : Type :=
  | ttrue : tm
  | tfalse : tm
  | tif : tm -> tm -> tm -> tm
  | tzero : tm
  | tsucc : tm -> tm
  | tpred : tm -> tm
  | tiszero : tm -> tm.Instance eq_dec_tm (t1 t2 : tm) : Dec (t1 = t2).Inductive bvalue : tm -> Prop :=
  | bv_true : bvalue ttrue
  | bv_false : bvalue tfalse.Inductive bvalue : tm -> Prop :=
  | bv_true : bvalue ttrue
  | bv_false : bvalue tfalse.Inductive bvalue : tm -> Prop :=
  | bv_true : bvalue ttrue
  | bv_false : bvalue tfalse.Instance dec_bvalue t : Dec (bvalue t) :=
  {| dec := _ |}.Inductive nvalue : tm -> Prop :=
  | nv_zero : nvalue tzero
  | nv_succ : forall t, nvalue t -> nvalue (tsucc t).Inductive nvalue : tm -> Prop :=
  | nv_zero : nvalue tzero
  | nv_succ : forall t, nvalue t -> nvalue (tsucc t).Inductive nvalue : tm -> Prop :=
  | nv_zero : nvalue tzero
  | nv_succ : forall t, nvalue t -> nvalue (tsucc t).Instance dec_nvalue t : Dec (nvalue t) :=
  {| dec := _ |}.Definition value (t:tm) := bvalue t \/ nvalue t.Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Inductive step : tm -> tm -> Prop :=
  | ST_IfTrue : forall t1 t2,
      (tif ttrue t1 t2) ===> t1
  | ST_IfFalse : forall t1 t2,
      (tif tfalse t1 t2) ===> t2
  | ST_If : forall t1 t1' t2 t3,
      t1 ===> t1' ->
      (tif t1 t2 t3) ===> (tif t1' t2 t3)
  | ST_Succ : forall t1 t1',
      t1 ===> t1' ->
      (tsucc t1) ===> (tsucc t1')
  | ST_PredZero :
      (tpred tzero) ===> tzero
  | ST_PredSucc : forall t1,
      nvalue t1 ->
      (tpred (tsucc t1)) ===> t1
  | ST_Pred : forall t1 t1',
      t1 ===> t1' ->
      (tpred t1) ===> (tpred t1')
  | ST_IszeroZero :
      (tiszero tzero) ===> ttrue
  | ST_IszeroSucc : forall t1,
       nvalue t1 ->
      (tiszero (tsucc t1)) ===> tfalse
  | ST_Iszero : forall t1 t1',
      t1 ===> t1' ->
      (tiszero t1) ===> (tiszero t1')

where "t1 '===>' t2" := (step t1 t2).Definition success := "Proofs work!".Instance step_gen_correct t0 : SuchThatCorrect (fun t => step t0 t)
                                                  (@arbitraryST _ (fun t => step t0 t) _).Notation step_normal_form := (normal_form step).Definition stuck (t:tm) : Prop :=
  step_normal_form t /\ ~ value t.(* xistential rework - dummy step *)
Definition step_fun (t : tm) : option tm := Some t.Axiom step_fun_correct : forall t t',
    step_fun t = Some t' <-> step t t'.Instance dec_step (t : tm) : Dec (exists t', step t t') :=
  {| dec := _ |}.

(* Specifications: *)
Lemma value_is_nf : forall t, value t -> step_normal_form t.
Theorem step_deterministic: deterministic step.