(* Definition funptr' (l:label) (A:Type) (t:termMeas) (P Q: A -> pred world) : pred prog := EX c : instruction, code l c && ALL stk : stack, ALL n : nat, ALL x : A, |> ((embedWP (guardsn n (Q x) stk)) --> (ALL n' : nat, embedWP (evalTM t n'   --> guardsn (n+n') (P x) ((c;;instr_assert FF)::stk) ))). *)
Definition funptr' (l:label) (A:Type) (t:termMeas) (P Q: A -> pred world) : pred prog :=
EX c : instruction, code l c &&
ALL stk : stack,  ALL x : A,
embedWP (P x --> EX n:nat, evalTM t n &&
|>getsn n ((c;;instr_assert FF)::stk) stk (Q x)).
Definition funptr l A P Q : pred prog :=
EX t:termMeas,
funptr' l A t P Q &&
ALL x:A, (embedWP (P x --> EX n:nat, evalTM t n)).
(* Lemma hoare_call : forall G R v Q l A lP lQ a, let wp := store_op (fun r => r#v = Some (value_label l)) && prog_op (funptr l A lP lQ) && lP a && (closed (lQ a --> Q)) in hoare G R wp (instr_call v) Q. *)
Definition verify_prog (psi:program assert) (G:pred prog) :=
forall n, agedfrom (K.squash (n,psi)) && |>G |-- G.
(* Lemma verify_func_simple : forall psi l (G:pred prog) (A:Type) (P Q:A -> pred world) i (REL:A -> A -> Prop), well_founded REL -> psi#l = Some i -> (forall a, let Pr' a' := P a' && !!(REL a' a) in exists t:termMeas, hoare (funptr' l A t Pr' Q && G) (Q a) (P a) i FF) ->  verify_prog psi G -> verify_prog psi (funptr l A P Q  && G).  Lemma hoare_weaken_time : forall x x' G R P i Q, x <= x' -> hoare' x G R P i Q -> hoare' x' G R P i Q.  Lemma hoare_weaken_pre : forall x G R P P' i Q, prog_op G && P' |-- P -> hoare' x G R P i Q -> hoare' x G R P' i Q .  Lemma hoare_weaken_post : forall x G R P i Q Q', prog_op G && Q |-- Q' -> hoare' x G R P i Q -> hoare' x G R P i Q'.  Lemma hoare_ex_pre : forall x G R T P i Q, (forall z:T, hoare' x G R (P z) i Q) -> hoare' x G R (exp P) i Q.  Lemma hoare_ex_pre' : forall x G R T P i Q, hoare' x G R (exp P) i Q -> (forall z:T, hoare' x G R (P z) i Q).  Lemma hoare_fact_pre : forall x G R (X:Prop) P i Q, (X -> hoare' x G R P i Q) -> hoare' x G R (!!X && P) i Q.  Lemma hoare_return : forall G R, hoare' 0 G R R instr_return FF.  Lemma hoare_seq : forall x y G R P Q S i1 i2, hoare' x G R P i1 Q -> hoare' y G R Q i2 S -> hoare' (x+y) G R P (i1 ;; i2) S.    Lemma hoare_getlabel : forall l v G R P, hoare' 0 G R (box (setM v (value_label l)) P) (instr_getlabel l v) P.  Lemma hoare_call : forall x G R v Q l A t lP lQ a, let wp := store_op (fun r => r#v = Some (value_label l)) && evalTM t x && (prog_op (funptr' l A t lP lQ)) && lP a && (closed (lQ a --> Q)) in hoare' (S x) G R wp (instr_call v) Q.  Lemma hoare_call2 : forall G R v Q l A t lP lQ a, let wp := store_op (fun r => r#v = Some (value_label l)) && (prog_op (funptr' l A t lP lQ)) && lP a && (closed (lQ a --> Q)) in hoare G R wp (instr_call v) Q.  Lemma hoare_step_fetch0 : forall v1 v2 x1 x2 G R P, hoare 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 v1 v2 x1 x2 G R P, hoare 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 v1 v2 v3 x1 x2 G R P, hoare 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 x v s1 s2 P1 P2 G R Q, let wp := EX val:value, store_op (fun r => r#v = Some val) && (  ((!!(val = value_label (L 0)) && P1)) || ((EX x1:value, (EX x2:value, !!(val = (value_cons x1 x2)))) && P2) ) in hoare x G R P1 s1 Q -> hoare x G R P2 s2 Q -> hoare x G R wp (instr_if_nil v s1 s2) Q.  Lemma hoare_assert : forall G R P (Q:assert), prog_op G && P |-- Q -> hoare 0 G R P (instr_assert Q) P.   (* Verifying function bodies and entire programs *)
Definition verify_prog (psi:program assert) (G:pred prog) :=
forall n, agedfrom (K.squash (n,psi)) && |>G |-- G.

Lemma verify_complete : forall G psi,
verify_prog psi G ->
forall n, G (K.squash (n,psi)).