Module Leftmost.
(* ** Leftmost reduction *)
Reserved Notation "s '≻lm' t" (at level 50).
Inductive step_lm : term -> term -> Prop :=
| step_lmApp  s t     : app (lam s) (lam t) ≻lm subst s 0 (lam t)
| step_lmAppR s t  t' : t ≻lm t' -> app (lam s) t ≻lm app (lam s) t'
| step_lmAppL s s' t  : s ≻lm s' -> app s t ≻lm app s' t
where "s '≻lm' t" := (step_lm s t).
Hint Constructors step_lm : core.
Ltac inv_step_lm :=
match goal with
| H : step_lm (lam _) _ |- _ => inv H
| H : step_lm (var _) _ |- _ => inv H
| H : star step_lm (lam _) _ |- _ => inv H
| H : star step_lm (var _) _ |- _ => inv H
end.
(* *** Small-Step_Lm Time Measure *)
Instance pow_step_lm_congL k:
Proper ((pow step_lm k) ==> eq ==> (pow step_lm k)) app.
(* *** Small-Step_Lm Space Measure *)
Definition redWithMaxSizeL := redWithMaxSize size step_lm.
(* *** Big-Step_Lm Space Measure*)
Inductive spaceBS : nat -> term -> term -> Prop :=
spaceBSVal s : spaceBS (size (lam s)) (lam s) (lam s)
| spaceBSBeta (s s' t t' u : term) m1 m2 m3 m:
spaceBS m1 s (lam s') ->
spaceBS m2 t (lam t') ->
spaceBS m3 (subst s' 0 (lam t')) u ->
m = max (m1 + 1 + size t)
(max (size (lam s') + 1 + m2) m3) ->
spaceBS m (app s t) u.
End Leftmost.
Definition hasTime k s := exists t, evalIn k s t.
Definition hasSpace m s := maxP (fun m => exists s', s >* s' /\ m = size s' ) m.
(* TODO: decompose this into lemmata? *)

Lemma hasSpaceBeta s s' m1 t t' m2 m3:
hasSpace m1 s -> hasSpace m2 t ->
s >* lam s' -> eval t t' ->
hasSpace m3 (subst s' 0 t') ->
hasSpace (max m3 (m1+m2+1)) (app s t).