(*      semax vars G (fun s => call P (map s vars)) f -> *)
Definition program_proved (p: program) :=
exists G, semax_func G p G
/\ table_get G 0 = Some  (0::nil, lift1 allocpool (eval (Var 0))).

(* Specifications: *)
Axiom semax_sound:
forall p, program_proved p -> forall n, run p n <> None.
Axiom semax_go:  forall vars G (P: funspec) x ys,
typecheck vars (Go x ys) = true ->
semax vars G (lift1 (cont P) (eval x) && lift1 (call P) (eval_list ys)) (Go x ys) .
Axiom semax_assign: forall x y c vars G P,
expcheck vars y = true ->
semax (vs_add x vars) G P c ->
semax vars G (|> subst' x (eval y) P) (Do x := y ; c).
Axiom semax_if: forall x c1 c2 vars G (P: assert),
expcheck vars x = true ->
semax vars G (local (lift2 neq (eval x) (lift0 0)) && P) c1 ->
semax vars G (local (lift2 eq (eval x) (lift0 0)) && P) c2 ->
semax vars G P (If x Then c1 Else c2).
Axiom 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 ((lift2 mapsto (eval y) (lift0 z) * TT) && |> subst' x (lift0 z) P)
(Do x := Mem y ; c).
Axiom semax_store: forall x y v c vars G (P: assert),
expcheck vars x = true ->
expcheck vars y = true ->
semax vars G (lift2 mapsto (eval x) (eval y) * P) c ->
semax vars G (lift2 mapsto (eval x) (lift0 v)  * P)  (Do Mem x  := y ; c).
Axiom semax_pre:
forall P P' vars G c, (forall s, P s |-- P' s) -> semax vars G P' c -> semax vars G P c.
Axiom 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 (EX v:A, (P v)) c.
Axiom semax_exp': forall A (any: A) vars G (P: A -> assert) c,
(forall v:A, semax vars G (P v) c) ->
semax vars G (EX v:A, (P v)) c.
Axiom semax_prop:
forall (R: Prop) vars G P c,
typecheck vars c = true ->
(R -> semax vars G P c) ->
semax vars G (!!R && P) c.
Axiom semax_G:
forall vars G P c, semax vars G (P && lift0 (funassert G)) c -> semax vars G P c.