(* note to Andrew: forward_for wouldn't work until we added True to the Prop in the following.*)
Definition fill_bin_Inv (b:Z) (p:val) (qNs:val*Z*Z) :=
(*  EX N:Z, EX s:Z, *)
PROPx (let '(q,N,s) := qNs in
[s = bin2sizeZ b; 0 <= N; s + N*(WORD+s) <= BIGBLOCK])
(LOCALx ([temp _q (let '(q,N,s):=qNs in q);
temp _p p;
temp _s (Vint (Int.repr (let '(q,N,s):=qNs in s)));
temp _b (Vint (Int.repr b))])
(SEPx ( let '(q,N,s):=qNs in
[mmlist s (Z.to_nat N) (offset_val s p) q;
memory_block Tsh (BIGBLOCK-(s+N*(WORD+s))) q] ))).
Definition fill_bin_preIncr (b:Z) (p:val) (qNs:val*Z*Z) :=
(*  EX N:Z, EX s:Z, William suggests localizing the lets so tactic pattern-matches may work *)
PROP ( let '(q,N,s) := qNs in
s = bin2sizeZ b /\ 0 <= N /\ s + N*(WORD+s) <= BIGBLOCK )
LOCAL (temp _q (let '(q,_,_) := qNs in q);
temp _p p;
temp _s (Vint (Int.repr (let '(_,_,s) := qNs in s)));
temp _b (Vint (Int.repr b)))
SEP (  let '(q,N,s) := qNs in
mmlist s (Z.to_nat N) (offset_val s p) q
* memory_block Tsh (BIGBLOCK - (s+N*(WORD+s)) - (WORD+s)) (offset_val (WORD+s) q)
* data_at Tsh tuint (Vint (Int.repr s)) q (* size *)
* data_at Tsh (tptr tvoid) (offset_val (WORD+s) q) (offset_val WORD q) (* next *)
* memory_block Tsh (s-WORD-WORD) (offset_val (WORD+WORD) q) (* rest of block *) ).

(* Specifications: *)
Lemma body_fill_bin: semax_body Vprog Gprog f_fill_bin fill_bin_spec.
(* TODO use freezer to frame over the loop (waste before the list): memory_block Tsh s p *)
(* TODO likely lemmas for malloc_small? Adding or removing at the head preserves mmlist (just unfold def, increment or decrement the length witness). If bin[i] is null then assigning an mmlist preserves mm_inv (induct on indices to get to i). *)
Lemma body_malloc_small:  semax_body Vprog Gprog f_malloc_small malloc_small_spec.