Add LoadPath "../..".
Definition world := (nat * ((var -> option adr)*(adr -> option adr)))%type.
Instance Join_world: Join world :=
Join_prod nat (Join_equiv nat)
_
(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 age_world (w: world) : option world :=
match fst w with S n => Some (n, snd w) | O => None end.
Definition level_world (w: world) : nat := fst w.
Instance ag_world: ageable world := mkAgeable _ _ _ af_world.
Instance Age_world : Age_alg world.
constructor.
intros [nx x] [ny y] [nz z] [nx' x'] [? ?] ?; simpl in *. destruct H; subst.
unfold age in H1. simpl in H1. unfold age_world in H1. simpl in H1.
destruct nz; inv H1. unfold age; simpl. unfold age_world; simpl.
exists (nx', y); exists (nx', z); split; auto; split; auto.
intros [nx x] [ny y] [nz z] [nz' z'] [? ?] ?; simpl in *. destruct H; subst.
unfold age in H1. simpl in H1. unfold age_world in H1. simpl in H1.
destruct nz; inv H1. unfold age; simpl. unfold age_world; simpl.
exists (nz', x); exists (nz', y); split; auto; split; auto.
intros [nx x] [nx' x'] [ny' y'] [nz' z'] [? ?] ?; simpl in *. destruct H; subst.
unfold age in H1. simpl in H1. unfold age_world in H1. simpl in H1.
destruct nx; inv H1. unfold age; simpl. unfold age_world; simpl.
exists (S nz', y'); exists (S nz', z'); split; auto; split; auto.
intros [nz z] [nx' x'] [ny' y'] [nz' z'] [? ?] ?; simpl in *. destruct H; subst.
unfold age in H1. simpl in H1. unfold age_world in H1. simpl in H1.
destruct nz; inv H1. unfold age; simpl. unfold age_world; simpl.
exists (S nz', x'); exists (S nz', y'); split; auto; split; auto.
Qed.
Definition den (lev: nat) (s: state) : world := (lev, (table_get (fst s), table_get (snd s))).
Obligation Tactic := (try solve [repeat intro; match goal with H: age _ _ |- _ => inv H end]).
Program Definition defined (y: var) : pred world :=
fun w => exists v, fst (snd w) y = Some v.
Next Obligation.
intros. intro; intros.
unfold age in H;  destruct a; destruct a'; simpl in H. destruct n; inv H.
auto.
Qed.
Definition fun_set (f: nat -> option nat) (x: nat) (y: option nat) :=
fun i => if eq_dec i x then y else f i.
Program Definition subst (x y: var) (P: pred world) : pred world :=
fun w => P (fst w, (fun_set (fst (snd w)) x (fst (snd w) y), snd (snd w))).
Next Obligation.
intros. intro; intros.
unfold age in H;  destruct a; destruct a'; simpl in H. destruct n; inv H.
simpl in *. eapply pred_hereditary; eauto.
unfold age; simpl. unfold age_world; simpl. auto.
Qed.
Program Definition mapsto (x y: var) : pred world :=
fun w =>
exists ax, fst (snd w) x = Some ax /\
exists ay, fst (snd w) y = Some ay /\
forall a, if eq_dec a ax then snd (snd w) a = Some ay else snd (snd w) a = None.
Next Obligation.
intros. intro; intros.
unfold age in H;  destruct a; destruct a'; simpl in H. destruct n; inv H.
simpl in *. auto.
Qed.
Program Definition equal (x y: var) : pred world :=
fun w => fst (snd w) x = fst (snd w) y.
Next Obligation.
intros. intro; intros.
unfold age in H;  destruct a; destruct a'; simpl in H. destruct n; inv H.
simpl in *. auto.
Qed.
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 lev stk hp v, P (lev, (stk,hp)) -> P (lev, (fun_set stk x v, hp)).
Definition subset (S1 S2: var -> Prop) :=
forall x, S1 x -> S2 x.
Inductive safeN: nat -> (list command * state) -> Prop :=
| safe0: forall cs, safeN 0 cs
| safe_step: forall n cs1 cs2, step' cs1 cs2 -> safeN n cs2 -> safeN (S n) cs1
| safe_halt: forall n s, safeN (S n) (nil, s).
Definition guards (P: pred world) (k: list command) : Prop :=
forall lev s, P (den lev s) -> safeN lev (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).

Lemma semax_pre_post:
forall P P' c Q' Q,
P |-- P' -> Q' |-- Q -> semax P' c Q' -> semax P c Q.