(*+ Definition of safety *)
(* We define safety based on specification of externals (acquire and release) *)
(* no need for an oracle, so it is unit *)
Definition Z := unit.
Record ext : Type := mkext {
ext_type : Type;
Pre : ext_type -> Z -> map -> Prop;
Post : ext_type -> Z -> map -> Prop
}.
Definition after_external : C -> option C :=
fun c =>
match c with
| acquire _ k => Some k
| release _ k => Some k
| _ => None
end.
(* [Hrel] is related to step indexing levels, and specify that the PURE of the maps coincide, which is always implied by joinability *)
Variable Hrel : nat -> map -> map -> Prop.

Axiom join_Hrel2 : forall m1 m2 m3 n, join m1 m2 m3 -> Hrel n m1 m3.
Inductive safeN_ (at_ext : C -> option ext) : nat -> Z -> C -> map -> Prop :=
safeN_0 : forall (z : Z) (c : C) (m : map), safeN_ at_ext 0 z c m
| safeN_step : forall (n : nat) (z : Z) (c c' : C') (m m' : map),
corestep c m c' m' ->
safeN_ at_ext n z (normal c') m' ->
safeN_ at_ext (S n) z (normal c) m
| safeN_external : forall (n : nat) (z : Z) (c : C) (m : map) (e : ext) (x : ext_type e),
at_ext c = Some e ->
Pre e x z m ->
(forall (m' : map) (z' : Z) (n' : nat),
n' <= n ->
Hrel n' m m' ->
Post e x z' m' ->
exists c' : C,
after_external c = Some c' /\
safeN_ at_ext n' z' c' m') ->
safeN_ at_ext (S n) z c m.