(*+ Hoare logic (single thread) *)
(** We now build a Hoare logic for a single thread based on the oracular semantics (it can assume that acquire will give back a good map, but has to provide back good maps at release.) *)
Definition safe_onethread G P c :=
forall m, m |= P -> forall oracle, safe step (G, oracle, m, c).
Definition semax G P c Q := forall F k,
safe_onethread G (Q ** F) k ->
safe_onethread G (P ** F) (c ++ k).

(* Specifications: *)
Lemma semax_app G P Q R c1 c2 : semax G P c1 Q -> semax G Q c2 R -> semax G P (c1++c2) R.
Lemma semax_nil G P : semax G P nil P.
Lemma semax_cons G P Q R i c : semax G P (i :: nil) Q -> semax G Q c R -> semax G P (i :: c) R.
Lemma updatemap_mapsto_ x n' n m :
(mapsto_ x m \/ mapsto x n' m) ->
exists m', updatemap m x n = Some m' /\ mapsto x n m'.
Lemma updatemap_mapsto_frame F x n m :
m |= mapsto_ x ** F ->
exists m', updatemap m x n = Some m' /\ m' |= mapsto x n ** F.
Lemma semax_set G x e : semax G (mapsto_ x) (set x e :: nil) (mapsto x e).
Lemma semax_assert G x n : n <> 0 -> semax G (mapsto x n) (assert x :: nil) (mapsto x n).
Lemma safe_onethread_implies G (P P' : pred) c :
imp P' P ->
safe_onethread G P c -> safe_onethread G P' c.
Lemma semax_frame G P c Q F : semax G P c Q -> semax G (P ** F) c (Q ** F).
Lemma semax_acquire' G l : (forall P, P \/ ~P) -> semax G emp (acquire l :: nil) (resinvs G l).
Lemma semax_pre G (P P' : pred) c Q :
imp P' P ->
semax G P c Q -> semax G P' c Q.
Lemma semax_post G P c (Q Q' : pred) :
imp Q Q' ->
semax G P c Q -> semax G P c Q'.
Lemma semax_acquire G l F :  (forall P, P \/ ~P) -> semax G F (acquire l :: nil) (resinvs G l ** F).
Lemma semax_release' G l : precise (resinvs G l) -> semax G (resinvs G l) (release l :: nil) emp.
Lemma semax_release G l F : precise (resinvs G l) -> semax G (resinvs G l ** F) (release l :: nil) F.
Lemma safe_nil G P : safe_onethread G P nil.
Lemma semax_safe G P c : semax G P c TT -> safe_onethread G P c.
Ltac forward :=
first [
apply semax_nil
| eapply semax_cons; [ eapply semax_set | ]
| eapply semax_cons; [ eapply semax_assert | ]
| eapply semax_cons; [ eapply semax_acquire' | ]
| eapply semax_cons; [ eapply semax_acquire | ]
| eapply semax_cons; [ eapply semax_release' | ]
| eapply semax_cons; [ eapply semax_release | ]
| eapply semax_cons
]; auto.