(** * Uniformly confluent reduction semantics *)
(** ** One-step reduction *)
Inductive step : term -> term -> Prop :=
| stepApp  s t     : app (lambda s) (lambda t) ≻ subst s 0 (lambda t)
| stepAppR s t  t' : t ≻ t' -> app s t ≻ app s t'
| stepAppL s s' t  : s ≻ s' -> app s t ≻ app s' t
where "s '≻' t" := (step s t).
Hint Constructors step.
Ltac inv_step :=
match goal with
| H : step (app _ _) _ |- _ => inv H
| H : step (lambda _) _ |- _ => inv H
| H : step (var _) _ |- _ => inv H
end.
(** ** Reflexive-transitive closure and step-indexed closure *)
Inductive star : term -> term -> Prop :=
star_refl s : star s s
| star_step s u t : step s u -> star u t -> star s t.
Inductive stepn : nat -> term -> term -> Prop :=
stepn_refl s : stepn 0 s s
| stepn_step s u t n : step s u -> stepn n u t -> stepn (S n) s t.
Hint Constructors step star stepn evaluates.
Instance star_trans : Transitive star.
Notation "s '≻*' t" := (star s t) (at level 40).
Notation "s '≻^' n t" := (stepn n s t) (at level 40, n at level 5).
Instance star_app : Proper (star ==> star ==> star) app.

Lemma star_stepn s t : s ≻* t <-> exists n, stepn n s t.