Definition world := ((var -> option adr)*(adr -> option adr))%type.Instance Join_world: Join world :=
   Join_prod
     (var -> option adr) (Join_equiv _)
     (adr -> option adr) (Join_fun adr (option adr) (Join_lower (Join_discrete adr))).Instance Perm_world : Perm_alg world := _.Instance Sep_world : Perm_alg world := _.Instance Canc_world : Perm_alg world := _.Instance Disj_world : Perm_alg world := _.Definition den (s: state) : world := (table_get (fst s), table_get (snd s)).Definition defined (y: var) : pred world :=
   fun w => exists v, fst w y = Some v.Definition fun_set (f: nat -> option nat) (x: nat) (y: option nat) :=
   fun i => if eq_dec i x then y else f i.Definition subst (x y: var) (P: pred world) : pred world :=
   fun w => P (fun_set (fst w) x (fst w y), snd w).Definition mapsto (x y: var) : pred world :=
 fun w =>
    exists ax, fst w x = Some ax /\
    exists ay, fst w y = Some ay /\
    forall a, if eq_dec a ax then snd w a = Some ay else snd w a = None.Definition equal (x y: var) : pred world :=
            fun w => fst w x = fst w y.Inductive modvars : command -> var -> Prop :=
| mod_assign: forall x y, modvars (Assign x y) x
| mod_load: forall x y, modvars (Load x y) x
| mod_seq1: forall x c1 c2, modvars c1 x -> modvars (Seq c1 c2) x
| mod_seq2: forall x c1 c2, modvars c2 x -> modvars (Seq c1 c2) x.Inductive modvars : command -> var -> Prop :=
| mod_assign: forall x y, modvars (Assign x y) x
| mod_load: forall x y, modvars (Load x y) x
| mod_seq1: forall x c1 c2, modvars c1 x -> modvars (Seq c1 c2) x
| mod_seq2: forall x c1 c2, modvars c2 x -> modvars (Seq c1 c2) x.Inductive modvars : command -> var -> Prop :=
| mod_assign: forall x y, modvars (Assign x y) x
| mod_load: forall x y, modvars (Load x y) x
| mod_seq1: forall x c1 c2, modvars c1 x -> modvars (Seq c1 c2) x
| mod_seq2: forall x c1 c2, modvars c2 x -> modvars (Seq c1 c2) x.Inductive modvars : command -> var -> Prop :=
| mod_assign: forall x y, modvars (Assign x y) x
| mod_load: forall x y, modvars (Load x y) x
| mod_seq1: forall x c1 c2, modvars c1 x -> modvars (Seq c1 c2) x
| mod_seq2: forall x c1 c2, modvars c2 x -> modvars (Seq c1 c2) x.Inductive modvars : command -> var -> Prop :=
| mod_assign: forall x y, modvars (Assign x y) x
| mod_load: forall x y, modvars (Load x y) x
| mod_seq1: forall x c1 c2, modvars c1 x -> modvars (Seq c1 c2) x
| mod_seq2: forall x c1 c2, modvars c2 x -> modvars (Seq c1 c2) x.Definition nonfreevars (P: pred world) (x: var) : Prop :=
  forall stk hp v, P (stk,hp) -> P (fun_set stk x v, hp).Definition subset (S1 S2: var -> Prop) :=
  forall x, S1 x -> S2 x.Inductive safe: (list command * state) -> Prop :=
| safe_step: forall cs1 cs2, step' cs1 cs2 -> safe cs2 -> safe cs1
| safe_halt: forall s, safe (nil, s).Inductive safe: (list command * state) -> Prop :=
| safe_step: forall cs1 cs2, step' cs1 cs2 -> safe cs2 -> safe cs1
| safe_halt: forall s, safe (nil, s).Inductive safe: (list command * state) -> Prop :=
| safe_step: forall cs1 cs2, step' cs1 cs2 -> safe cs2 -> safe cs1
| safe_halt: forall s, safe (nil, s).Definition guards (P: pred world) (k: list command) : Prop :=
  forall s, P (den s) -> safe (k,s).Definition semax (P: pred world) (c: command) (Q: pred world) : Prop :=
  forall F, subset (modvars c) (nonfreevars F) ->
  forall k, guards (Q*F) k -> guards (P*F) (c :: k).

(* Specifications: *)
Lemma semax_assign: forall P x y, semax (defined y && subst x y P) (Assign x y) P.
Lemma semax_load: forall x y z, x <> y -> x <> z -> semax (mapsto y z) (Load x y) (mapsto y z && equal x z).
Lemma semax_store: forall x y z, semax (defined y && mapsto x z) (Store x y) (mapsto x y).
Lemma semax_seq: forall P c1 Q c2 R, semax P c1 Q -> semax Q c2 R -> semax P (Seq c1 c2) R.
Lemma frame: forall F P c Q, subset (modvars c) (nonfreevars F) -> semax P c Q -> semax (P * F) c (Q * F).