(* 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]).

(* Specifications: *)
Lemma sublist_nil1 : forall A i j (l : list A), j <= i -> sublist i j l = [].
Lemma Znth_In : forall A (d: Inhabitant A) i (l : list A) x (Hrange : 0 <= i < Zlength l)
(Hnth : Znth i l = x), In x l.
Lemma In_Znth : forall A (d: Inhabitant A) (l : list A) x,
In x l ->
exists i, 0 <= i < Zlength l /\ Znth i l = x.
Lemma sublist_of_nil : forall A i j, sublist i j (nil : list A) = [].
Fixpoint sorted2 l :=
match l with
| [] => True
| x :: rest => Forall (fun y => x <= y) rest /\ sorted2 rest
end.
Lemma sorted_equiv : forall l, sorted l <-> sorted2 l.
Lemma sorted_mono : forall l i j (Hsort : sorted l) (Hi : 0 <= i <= j)
(Hj : j < Zlength l),
Znth i l <= Znth j l.
Lemma In_sorted_range : forall lo hi x l (Hsort : sorted l) (Hlo : 0 <= lo <= hi)
(Hhi : hi <= Zlength l)
(Hin : In x (sublist lo hi l)),
Znth lo l <= x <= Znth (hi - 1) l.
Lemma In_sorted_gt : forall x i n l lo hi (Hsort : sorted l) (Hlo : lo >= 0)
(Hhi : hi <= Zlength l)
(Hin : In x (sublist lo hi l))
(Hi : lo <= i < hi) (Hn : Znth i l = n)
(Hgt : n < x),
In x (sublist (i + 1) hi l).
Lemma In_sorted_lt : forall x i n l lo hi (Hsort : sorted l) (Hlo : lo >= 0)
(Hhi : hi <= Zlength l)
(Hin : In x (sublist lo hi l))
(Hi : lo <= i < hi) (Hn : Znth i l = n)
(Hgt : x < n),
In x (sublist lo i l).
Lemma Znth_In_sublist : forall A (d: Inhabitant A) i (l : list A) lo hi
(Hlo : 0 <= lo <= i) (Hhi : i < hi <= Zlength l),
In (Znth i l) (sublist lo hi l).
Lemma sublist_In_sublist : forall A (l : list A) x lo hi lo' hi' (Hlo : 0 <= lo <= lo')
(Hhi : hi' <= hi), In x (sublist lo' hi' l) -> In x (sublist lo hi l).
Lemma body_search: semax_body Vprog Gprog f_search search_spec.
Definition four_contents := [1; 2; 3; 4].