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.

Axiom semax_func_nil: forall G, semax_func G nil nil.
Axiom semax_func_cons:
forall  fs id f vars P (G G': funspecs),
inlist id (map (@fst adr (list var * control)) fs) = false ->
list_nodups vars = true ->
length vars = length (fst P) ->
semax vars G (fun s => call P (map s vars)) f ->
semax_func G fs G' ->
semax_func G ((id, (vars,f))::fs) ((id, P) :: G').