Record funspec (B:Type) :=
{ fs_A  : B -> Type
; fs_t  : B -> termMeas
; fs_P  : forall b, fs_A b -> pred world
; fs_Q  : forall b, fs_A b -> pred world
}.
Definition funspec_assumptions B b n (fss:list (label*funspec B) ) : pred prog :=
ALL l:_, ALL fs:_, !!(In (l,fs) fss) -->
let P' a := fs_P B fs b a &&
store_op (fun r => exists n', proj1_sig (fs_t B fs b) r n' /\ n' < n)
in funptr l (fs_A B fs b) (fs_t B fs b) P' (fs_Q B fs b).

(* Specifications: *)
Lemma verify_true :
forall psi,
verify_prog psi TT.
Lemma verify_clique : forall psi G B (fss:list (label * funspec B)),
(forall l fs,
In (l,fs) fss ->
exists i, psi#l = Some i /\
forall b a n,
let Pr := fs_P B fs b a && store_op (fun r' => proj1_sig (fs_t B fs b) r' n) in
hoare n (funspec_assumptions B b n fss && G) (fs_Q B fs b a) Pr i FF) ->
verify_prog psi G ->
verify_prog
psi
((ALL b:B, ALL l:_, ALL fs:_,
!!(In (l,fs) fss) -->
funptr l (fs_A B fs b) (fs_t B fs b)
(fs_P B fs b) (fs_Q B fs b)) && G).
Lemma verify_func : forall psi l (G:pred prog) (B:Type) (A:B->Type) (P Q:forall b, A b -> pred world) i (t:B -> termMeas),
psi#l = Some i ->
(forall b a n,
let Pr  := P b a && store_op (fun r' => proj1_sig (t b) r' n) in
let Pr' a' := P b a' && store_op (fun r' => exists n', proj1_sig (t b) r' n' /\ n' < n) in
hoare n (funptr l (A b) (t b) Pr' (Q b) && G) (Q b a) Pr i FF) ->
verify_prog psi G ->
verify_prog psi
((ALL b:_, funptr l (A b) (t b) (P b) (Q b)) && G).
Lemma verify_func_simple : forall psi l (G:pred prog) (A:Type) (P Q:A -> pred world) i (t:termMeas),
psi#l = Some i ->
(forall a n,
let Pr  := P a && store_op (fun r' => proj1_sig t r' n) in
let Pr' a' := P a' && store_op (fun r' => exists n', proj1_sig t r' n' /\ n' < n) in
hoare n (funptr l A t Pr' Q && G) (Q a) Pr i FF) ->
verify_prog psi G ->
verify_prog psi (funptr l A t P Q && G).
Lemma end_assert_lemma : forall Q n p p' r r' stk,
stepN n p p' r (stk++(instr_assert Q ;; instr_return ;; instr_assert FF) :: nil) r' nil ->
stepstar p p' r stk r' nil /\ proj1_sig Q (p',r').
Lemma verify_true :
forall psi,
verify_prog psi TT.
Lemma verify_clique : forall psi G B (fss:list (label * funspec B)),
(forall l fs,
In (l,fs) fss ->
exists i, psi#l = Some i /\
forall b a n,
let Pr := fs_P B fs b a && store_op (fun r' => proj1_sig (fs_t B fs b) r' n) in
hoare n (funspec_assumptions B b n fss && G) (fs_Q B fs b a) Pr i FF) ->
verify_prog psi G ->
verify_prog
psi
((ALL b:B, ALL l:_, ALL fs:_,
!!(In (l,fs) fss) -->
funptr l (fs_A B fs b) (fs_t B fs b)
(fs_P B fs b) (fs_Q B fs b)) && G).
Lemma verify_func : forall psi l (G:pred prog) (B:Type) (A:B->Type) (P Q:forall b, A b -> pred world) i (t:B -> termMeas),
psi#l = Some i ->
(forall b a n,
let Pr  := P b a && store_op (fun r' => proj1_sig (t b) r' n) in
let Pr' a' := P b a' && store_op (fun r' => exists n', proj1_sig (t b) r' n' /\ n' < n) in
hoare n (funptr l (A b) (t b) Pr' (Q b) && G) (Q b a) Pr i FF) ->
verify_prog psi G ->
verify_prog psi
((ALL b:_, funptr l (A b) (t b) (P b) (Q b)) && G).
Lemma verify_func_simple : forall psi l (G:pred prog) (A:Type) (P Q:A -> pred world) i (t:termMeas),
psi#l = Some i ->
(forall a n,
let Pr  := P a && store_op (fun r' => proj1_sig t r' n) in
let Pr' a' := P a' && store_op (fun r' => exists n', proj1_sig t r' n' /\ n' < n) in
hoare n (funptr l A t Pr' Q && G) (Q a) Pr i FF) ->
verify_prog psi G ->
verify_prog psi (funptr l A t P Q && G).
Lemma end_assert_lemma : forall Q n p p' r r' stk,
stepN n p p' r (stk++(instr_assert Q ;; instr_return ;; instr_assert FF) :: nil) r' nil ->
stepstar p p' r stk r' nil /\ proj1_sig Q (p',r').