Hint Constructors context contextlist.
Hint Resolve context_compose contextlist_compose.
Definition reduction_ok (k: kind) (a: expr) (m: mem) (rd: reduction) : Prop :=
match k, rd with
| LV, Lred _ l' m' => lred ge e a m l' m'
| RV, Rred _ r' m' t => rred ge a m t r' m' /\ exists w', possible_trace w t w'
| RV, Callred _ fd args tyres m' => callred ge a m fd args tyres /\ m' = m
| LV, Stuckred => ~imm_safe_t k a m
| RV, Stuckred => ~imm_safe_t k a m
| _, _ => False
end.
Definition reducts_ok (k: kind) (a: expr) (m: mem) (ll: reducts expr) : Prop :=
(forall C rd,
In (C, rd) ll ->
exists a', exists k', context k' k C /\ a = C a' /\ reduction_ok k' a' m rd)
/\ (ll = nil -> match k with LV => is_loc a <> None | RV => is_val a <> None end).
Definition list_reducts_ok (al: exprlist) (m: mem) (ll: reducts exprlist) : Prop :=
(forall C rd,
In (C, rd) ll ->
exists a', exists k', contextlist k' C /\ al = C a' /\ reduction_ok k' a' m rd)
/\ (ll = nil -> is_val_list al <> None).
Ltac monadInv :=
match goal with
| [ H: match ?x with Some _ => _ | None => None end = Some ?y |- _ ] =>
destruct x eqn:?; [monadInv|discriminate]
| [ H: match ?x with left _ => _ | right _ => None end = Some ?y |- _ ] =>
destruct x; [monadInv|discriminate]
| _ => idtac
end.

Lemma wrong_kind_ok:
forall k a m,
k <> Cstrategy.expr_kind a ->
reducts_ok k a m stuck.