Inductive Forallz {A} (P: Z -> A->Prop) : Z -> list A -> Prop :=
| Forallz_nil : forall i, Forallz P i nil
| Forallz_cons : forall i x l, P i x -> Forallz P (Z.succ i) l -> Forallz P i (x::l).
(******************************************  Definition of aggregate predicates.  ******************************************)
Definition array_pred {A: Type}{d: Inhabitant A}  (lo hi: Z) (P: Z -> A -> val -> mpred) (v: list A) (p: val) : mpred :=
!! (Zlength v = hi - lo) &&
rangespec lo (Z.to_nat (hi-lo)) (fun i => P i (Znth (i-lo) v)) p.
Definition struct_pred (m: members) {A: ident * type -> Type} (P: forall it, A it -> val -> mpred) (v: compact_prod (map A m)) (p: val): mpred.

(* Specifications: *)
Lemma array_pred_len_1: forall {A}{d: Inhabitant A} i P v p,
array_pred i (i + 1) P (v :: nil) p = P i v p.
Lemma split_array_pred: forall {A}{d: Inhabitant A} lo mid hi P v p,
lo <= mid <= hi ->
Zlength v = hi - lo ->
array_pred lo hi P v p =
array_pred lo mid P (sublist 0 (mid-lo) v) p *
array_pred mid hi P (sublist (mid-lo) (hi-lo) v) p.
Lemma array_pred_shift: forall {A}{d: Inhabitant A} (lo hi lo' hi' mv : Z) P' P v p,
lo - lo' = mv ->
hi - hi' = mv ->
(forall i i', lo <= i < hi -> i - i' = mv -> P' i' (Znth (i-lo) v) p = P i (Znth (i-lo) v) p) ->
array_pred lo' hi' P' v p = array_pred lo hi P v p.
Lemma array_pred_ext_derives: forall {A B} (dA: Inhabitant A) (dB: Inhabitant B)
lo hi P0 P1 (v0: list A) v1 p,
(Zlength v0 = hi - lo -> Zlength v1 = hi - lo) ->
(forall i, lo <= i < hi ->
P0 i (Znth (i-lo) v0) p |-- P1 i (Znth (i-lo) v1) p) ->
array_pred  lo hi P0 v0 p |-- array_pred lo hi P1 v1 p.
Lemma array_pred_ext: forall {A B} (dA: Inhabitant A) (dB: Inhabitant B) lo hi P0 P1
(v0: list A) (v1: list B) p,
Zlength v0 = Zlength v1 ->
(forall i, lo <= i < hi ->
P0 i (Znth (i-lo) v0) p = P1 i (Znth (i-lo) v1) p) ->
array_pred lo hi P0 v0 p = array_pred lo hi P1 v1 p.
Lemma at_offset_array_pred: forall  {A} {d: Inhabitant A} lo hi P v ofs p,
at_offset (array_pred lo hi P v) ofs p = array_pred lo hi (fun i v => at_offset (P i v) ofs) v p.
Lemma array_pred_sepcon: forall  {A} {d: Inhabitant A} lo hi P Q v p,
array_pred lo hi P v p * array_pred lo hi Q v p = array_pred lo hi (P * Q) v p.