Module Type SEMAX.
Parameter mpred : Type.
Parameter Nm: NatDed mpred.  Existing Instance Nm.
Parameter Sm: SepLog mpred.  Existing Instance Sm.
Parameter Cm: ClassicalSep mpred.  Existing Instance Cm.
Parameter Im: Indir mpred.  Existing Instance Im.
Parameter Rm: RecIndir mpred.  Existing Instance Rm.
Parameter SIm: SepIndir mpred.  Existing Instance SIm.
Parameter SRm: SepRec mpred.  Existing Instance SRm.
Parameter mapsto: forall (v1 v2: adr), mpred.
Definition assert := env -> mpred.
Bind Scope logic with assert.
Definition funspec := (list var * assert)%type.
Definition funspecs := table adr funspec.
Definition call (P: list var * assert) (vl: list adr) : mpred :=
(!! (length vl = length (fst P)) && snd P (arguments (fst P) vl)).
Parameter cont: forall (nP: funspec)  (v: adr), mpred.
Definition funassert (G: funspecs) : mpred :=
(ALL  i:_, ALL P:_,  !! (table_get G i = Some P) --> cont P i)  &&
(ALL  i:_, ALL P:_,  cont P i --> !! exists P', table_get G i = Some P').
Parameter allocpool: forall (b: adr), mpred.
Parameter semax : varset -> funspecs -> assert -> control -> Prop.
Parameter semax_func: forall (G: funspecs) (p: program) (G': funspecs), Prop.
Definition program_proved (p: program) :=
exists G, semax_func G p G
/\ table_get G 0 = Some  (0::nil, fun s => allocpool (eval (Var 0) s)).

Axiom 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) .