(* 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.
Fixpoint sorted (l : list Z) : Prop :=
match l with
| [] => True
| x::rest =>
match rest with [] => True | y::_ =>  x <= y /\ sorted rest end
end.
(* Beginning of the API spec for the bin_search.c program *)
Definition search_spec :=
DECLARE _search
WITH a: val, sh : share, contents : list Z, tgt : Z, lo : Z, hi : Z
PRE [ _a OF (tptr tint), _tgt OF tint, _lo OF tint, _hi OF tint ]
PROP  (readable_share sh;
0 <= lo <= Int.max_signed;
hi <= Zlength contents <= Int.max_signed;
Int.min_signed <= hi <= Int.max_signed / 2;
sorted contents;
Forall (fun x => Int.min_signed <= x <= Int.max_signed) contents;
Int.min_signed <= tgt <= Int.max_signed)
LOCAL (temp _a a; temp _tgt (Vint (Int.repr tgt));
temp _lo (Vint (Int.repr lo)); temp _hi (Vint (Int.repr hi)))
SEP   (data_at sh (tarray tint (Zlength contents)) (map Vint (map Int.repr contents)) a)
POST [ tint ]
EX i:Z,
PROP (if in_dec Z.eq_dec tgt (sublist lo hi contents) then Znth i contents = tgt else i = -1)
LOCAL (temp ret_temp  (Vint (Int.repr i)))
SEP (data_at sh (tarray tint (Zlength contents)) (map Vint (map Int.repr contents)) a).
(* The spec of "int main(void){}" always looks like this. *)
Definition main_spec :=
DECLARE _main
WITH gv: globals
PRE  [] main_pre prog nil gv
POST [ tint ] main_post prog nil gv.
(* Packaging the API spec all together. *)
Definition Gprog : funspecs :=
ltac:(with_library prog [search_spec; main_spec]).

Lemma body_search: semax_body Vprog Gprog f_search search_spec.
Definition four_contents := [1; 2; 3; 4].