(* Definition of the hoare relation and rules *)
Definition hoare (t:terminationMeasure) (n':nat) (G R P:pred world) (c:instruction) (Q:pred world) :=
forall t', termMeasure_incr t t' ->
forall p n k stk,
(forall s, G (p,(s,t'))) ->
(forall r', guards n R stk       (p,(r',t'))) ->
(forall r', guards n Q (k::stk)  (p,(r',t'))) ->
(forall r,  guards (n'+n) P ((c ;; k)::stk) (p,(r,t'))).

(* Specifications: *)
Lemma hoare_weaken : forall t t' x x' (G G' R R' P P' Q Q':pred world) i,
termMeasure_incr t t' ->
x <= x' ->
G' |-- G  ->
R  |-- R' ->
P' |-- P  ->
Q  |-- Q' ->
hoare t  x  G  R  P  i Q ->
hoare t' x' G' R' P' i Q'.
Lemma hoare_weaken_time : forall t x x' G R P i Q,
x <= x' ->
hoare t x G R P i Q ->
hoare t x' G R P i Q.
Lemma hoare_weaken_pre : forall t x G R P P' i Q,
P' |-- P ->
hoare t x G R P i Q ->
hoare t x G R P' i Q .
Lemma hoare_weaken_post : forall t x G R P i Q Q',
Q |-- Q' ->
hoare t x G R P i Q ->
hoare t x G R P i Q'.
Lemma hoare_ex_pre : forall t x G R T P i Q,
(forall z:T, hoare t x G R (P z) i Q) ->
hoare t x G R (exp P) i Q.
Lemma hoare_fact_pre : forall t x G R (X:Prop) P i Q,
(X -> hoare t x G R P i Q) ->
hoare t x G R (!!X && P) i Q.
Lemma hoare_return : forall t (G R:pred world),
hoare t 0 G R R instr_return FF.
Lemma hoare_getlabel : forall t l v (G R P:pred world),
hoare t 0 G R
(box (setM v (value_label l)) P)
(instr_getlabel l v)
P.
Lemma hoare_step_fetch0 : forall t v1 v2 x1 x2 (G R P:pred world),
hoare t 0 G R
(store_op (fun r => r#v1 = Some (value_cons x1 x2)) && box (setM v2 x1) P)
(instr_fetch_field v1 0 v2)
P.
Lemma hoare_step_fetch1 : forall t v1 v2 x1 x2 (G R P:pred world),
hoare t 0 G R
(store_op (fun r => r#v1 = Some (value_cons x1 x2)) && box (setM v2 x2) P)
(instr_fetch_field v1 1 v2)
P.
Lemma hoare_cons : forall t v1 v2 v3 x1 x2 (G R P:pred world),
hoare t 0 G R
(store_op (fun r => r#v1 = Some x1 /\ r#v2 = Some x2) &&
box (setM v3 (value_cons x1 x2)) P)
(instr_cons v1 v2 v3)
P.
Lemma hoare_if : forall t x v s1 s2 G R P Q,
P |-- store_op (fun r => match r#v with
| Some (value_label l) => l = L 0
| Some (value_cons _ _) => True
| _ => False
end) ->
hoare t x G R (P && store_op (fun r => r#v = Some (value_label (L 0)))) s1 Q ->
hoare t x G R (P && store_op (fun r => exists x1, exists x2, r#v = Some (value_cons x1 x2))) s2 Q ->
hoare t x G R P (instr_if_nil v s1 s2) Q.
Lemma hoare_call : forall t x G R v Q,
let wp :=
EX l:label, EX A:Type, EX lP:(A->pred world), EX lQ:(A -> pred world), EX n':nat, EX a:A,
store_op (fun r => r#v = Some (value_label l) /\ t l r = Some n' /\ n' < x) &&
(G --> funptr l A lP lQ) &&
lP a && (closed (lQ a --> Q))
in
hoare t x G R wp (instr_call v) Q.
Lemma hoare_assert : forall t (G R P:pred world) (Q:K.assert),
boxy K.expandM G ->
G && P |-- (proj1_sig Q) ->
hoare t 0 G R P (instr_assert Q) P.
Lemma hoare_seq : forall t x y G R P Q S i1 i2,
hoare t x G R P i1 Q ->
hoare t y G R Q i2 S ->
hoare t (x+y) G R P (i1 ;; i2) S.