From Undecidability.L Require Export Util.L_facts.
Hint Resolve eval_converges : core.
(* * Step indexed evaluation *)
Inductive seval : nat -> term -> term -> Prop :=
| sevalR n s : seval n (lam s) (lam s)
| sevalS n s t u v w :
seval n s (lam u) -> seval n t (lam v) -> seval n (subst u 0 (lam v)) w -> seval (S n) (s t) w.
Local Notation "s '⇓' n t" := (seval n s t) (at level 51).
Proof with eauto using star_trans, star_trans_l, star_trans_r.
intros. induction H as [ | n s t u v w _ [IHe1 _] _ [IHe2 _] _ [IHe3 lam_w]].
- repeat econstructor.
- split...
transitivity ((lam u) t)...
transitivity ((lam u) (lam v))... now rewrite stepApp.
Qed.
Hint Resolve seval_eval : core.
(* Equivalence between step index evaluation and evaluation *)
Proof with eauto using seval_S, seval.
intros H; revert n t; induction H; intros n u A...
- inv A...
- inv A...
Qed.
(*  Evaluation as a function *)
Fixpoint eva (n : nat) (u : term) :=
match u with
| var n => None
| lam s => Some (lam s)
| app s t => match n with
| 0   => None
| S n => match eva n s, eva n t with
| Some (lam s), Some t => eva n (subst s 0 t)
|   _ , _ => None
end
end
end.
(* Equivalence between the evaluation function and step indexed evaluation *)
(* Omega diverges *)
(* If an application converges, both sides converge *)
(* Informative eval *)
Definition cChoice := constructive_indefinite_ground_description_nat_Acc.
Fixpoint stepf (s : term) : list term :=
match s with
| (lam _) => []
| var x => []
| app (lam s) (lam t) => [subst s 0 (lam t)]
| app s t => map (fun x => app x t) (stepf s) ++ map (fun x => app s x) (stepf t)
end.
Ltac stepf_tac :=
match goal with
| [ H : app _ _ ≻ ?t |- ?P ] => inv H
| [ H : var _ ≻ ?t |- ?P ] => inv H
| [ H : lam _ ≻ ?t |- ?P ] => inv H
| [ H : exists x, _ |- _ ] => destruct H
| [ H : _ /\ _ |- _ ] => destruct H
end + subst.
Fixpoint stepn (n : nat) s : list term :=
match n with
| 0 => [s]
|  S n => flat_map (stepn n) (stepf s)
end.

Lemma eval_rect (P : term -> term -> Type) (HR : forall s : term, P (lam s) (lam s))
(HS : forall s u t t' v : term,
eval s (lam u) ->
P s (lam u) ->
eval t t' ->
P t t' -> eval (subst u 0 t') v -> P (subst u 0 t') v -> P (s t) v):
forall s t : term, eval s t -> P s t.