(* Hoare Logic *)

Definition h_assert := stack -> Prop.Inductive immed_safe: state -> Prop :=
| IS_stop: forall rho m, immed_safe (State rho m Cskip)
| IS_step: forall s s', step s s' -> immed_safe s.Inductive immed_safe: state -> Prop :=
| IS_stop: forall rho m, immed_safe (State rho m Cskip)
| IS_step: forall s s', step s s' -> immed_safe s.Inductive immed_safe: state -> Prop :=
| IS_stop: forall rho m, immed_safe (State rho m Cskip)
| IS_step: forall s s', step s s' -> immed_safe s.Definition safe (s: state) : Prop :=
  forall s', stepstar s s' -> immed_safe s'.Definition guard (P: h_assert) (c: command) :=
  forall rho,   P rho -> safe (State rho m0 c).Definition Hoare (P: h_assert) (c: command) (Q: h_assert) : Prop :=
   forall k, guard Q k -> guard P (Cseq c k).Definition subst (x:var) (v: option val) (P: h_assert) : h_assert :=
   fun rho => P (upd rho x v).

(* Specifications: *)
Lemma safe_step: forall s s', step s s' -> safe s' -> safe s.
Lemma upd_same: forall A B {EA: EqDec A} rho (x: A) (v: option B), upd rho x v x = v.
Lemma upd_other: forall A B {EA: EqDec A} rho (x y: A) (v: option B), x <> y -> upd rho x v y = rho y.
Lemma floyd_assign: forall (P: h_assert) (x: var) (e: expr), (forall rho, P rho -> exists v, eval e v rho) -> Hoare P (Cassign x e) (fun rho => exists v, exists x', eval (Evar x) v rho /\ subst x x' (eval e v) rho /\ subst x x' P rho).