Definition semax vars (G: funspecs) (P: assert) (k: control) : Prop :=
typecheck vars k = true /\ forall n,  semax' (SemaxArg vars (fun s => P s && funassert G) k) n.
Definition semax_func (G: funspecs) (p: program) (G': funspecs) :=
match_specs p G' /\
forall n, believe_all semax' G p G' n.

(* Specifications: *)
Lemma semax_func_nil: forall G, semax_func G nil nil.
Lemma semax_G:
forall vars G P c, semax vars G (fun s => P s && funassert G) c -> semax vars G P c.
Lemma semax_go:  forall vars G (P: funspec) x ys,
typecheck vars (Go x ys) = true ->
semax vars G (fun s => cont P (eval x s) && call P (eval_list ys s)) (Go x ys) .
Lemma semax_assign: forall x y c vars G P,
expcheck vars y = true ->
semax (vs_add x vars) G P c ->
semax vars G (fun s => |> subst x (eval y s) P s) (Do x := y ; c).
Lemma semax_if: forall x c1 c2 vars G (P: assert),
expcheck vars x = true ->
semax vars G (fun s => !!(eval x s <> 0) && P s) c1 ->
semax vars G (fun s => !! (eval x s = 0) && P s) c2 ->
semax vars G P (If x Then c1 Else c2).
Lemma semax_load: forall x y z c vars G P,
expcheck vars y = true ->
semax (vs_add x vars) G P c ->
semax vars G (fun s => ((mapsto (eval y s) z) * TT) && |> subst x z P s)
(Do x := Mem y ; c).
Lemma semax_store: forall x y v c vars G (P: assert),
expcheck vars x = true ->
expcheck vars y = true ->
semax vars G (fun s => mapsto (eval x s) (eval y s) * P s) c ->
semax vars G (fun s => mapsto (eval x s) v  * P s)  (Do Mem x  := y ; c).
Lemma semax_pre:
forall P P' vars G c, (forall s, P s |-- P' s) -> semax vars G P' c -> semax vars G P c.
Lemma semax_exp: forall {A} vars G (P: A -> assert) c,
typecheck vars c = true ->
(forall v:A, semax vars G (P v) c) ->
semax vars G (fun s => EX v:A, (P v s)) c.
Lemma semax_exp': forall {A} (any: A) vars G (P: A -> assert) c,
(forall v:A, semax vars G (P v) c) ->
semax vars G (fun s => EX v:A, (P v s)) c.
Lemma semax_prop:
forall (R: Prop) vars G P c,
typecheck vars c = true ->
(R -> semax vars G P c) ->
semax vars G (fun s => !! R && P s) c.