Section wp.
Variable t:terminationMeasure.
Variables G R:pred world.
Fixpoint is_basic (i:instruction) : bool :=
match i with
| instr_call _ => false
| instr_seq s1 s2 => andb (is_basic s1) (is_basic s2)
| _ => true
end.
Fixpoint wp (x:nat) (i:instruction) (POST:pred world) { struct i } : pred world :=
match i with
| instr_return => R
| instr_assert P => (G --> proj1_sig P) && POST
| instr_getlabel l v =>  box (setM v (value_label l)) POST
| instr_fetch_field v1 0 v2 =>
EX x1:value, EX x2:value,
store_op (fun r => r#v1 = Some (value_cons x1 x2)) && box (setM v2 x1) POST
| instr_fetch_field v1 1 v2 =>
EX x1:value, EX x2:value,
store_op (fun r => r#v1 = Some (value_cons x1 x2)) && box (setM v2 x2) POST
| instr_cons v1 v2 v3 =>
(EX x1:value, EX x2:value,
store_op (fun r => r#v1 = Some x1 /\ r#v2 = Some x2) &&
box (setM v3 (value_cons x1 x2)) POST)
| instr_if_nil v s1 s2 =>
EX val:value,
store_op (fun r => r#v = Some val) &&
(
((!!(val = value_label (L 0)) && wp x s1 POST))
||
((EX x1:value, (EX x2:value,
!!(val = (value_cons x1 x2)))) && wp x s2 POST)
)
| instr_call v =>
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 --> POST))
| instr_seq s1 s2 =>
if is_basic s1 then wp 0 s1 (wp x s2 POST) else
if is_basic s2 then wp x s1 (wp 0 s2 POST) else
EX n:nat, EX m:nat,
wp n s1 (wp m s2 POST) && !!(n+m = x)
| _ => FF
end.
End wp.

(* Specifications: *)
Lemma hoare_wp : forall i x t G R P Q,
boxy K.expandM G ->
P |-- wp t G R x i Q ->
hoare t x G R P i Q.