(* The next line is "boilerplate", always required after importing an AST. *)
Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Definition Vprog : varspecs.  mk_varspecs prog. Defined.
(* Functional spec of this program.  *)
Definition sum_Z : list Z -> Z := fold_right Z.add 0.
(* Beginning of the API spec for the sumarray.c program *)
Definition sumarray_spec : ident * funspec :=
DECLARE _sumarray
WITH a: val, sh : share, contents : list Z, size: Z
PRE [ _a OF (tptr tuint), _n OF tint ]
PROP  (readable_share sh; 0 <= size <= Int.max_signed;
Forall (fun x => 0 <= x <= Int.max_unsigned) contents)
LOCAL (temp _a a; temp _n (Vint (Int.repr size)))
SEP   (data_at sh (tarray tuint size) (map Vint (map Int.repr contents)) a)
POST [ tuint ]
PROP () LOCAL(temp ret_temp  (Vint (Int.repr (sum_Z contents))))
SEP (data_at sh (tarray tuint size) (map Vint (map Int.repr contents)) a).
(* Note: It would also be reasonable to let [contents] have type [list int]. Then the [Forall] would not be needed in the PROP part of PRE. *)
(* The precondition of "int main(void){}" always looks like this. *)
Definition main_spec :=
DECLARE _main
WITH gv : globals
PRE  [] main_pre prog tt nil gv
POST [ tint ]
PROP()
LOCAL (temp ret_temp (Vint (Int.repr (1+2+3+4))))
SEP(TT).
(* Packaging the API spec all together. *)
Definition Gprog : funspecs :=
ltac:(with_library prog [sumarray_spec; main_spec]).

(** Proof that f_sumarray, the body of the sumarray() function, ** satisfies sumarray_spec, in the global context (Vprog,Gprog). **)
Lemma body_sumarray: semax_body Vprog Gprog f_sumarray sumarray_spec.