(*Require Import VST.floyd.fieldlist.*)
(*Require Import VST.floyd.aggregate_type.*)
Require Export VST.floyd.fieldlist.
Require Export VST.floyd.aggregate_type.
Open Scope Z.
Open Scope logic.
(******************************************  Definition and lemmas about rangespec  ******************************************)
Fixpoint rangespec (lo: Z) (n: nat) (P: Z -> val -> mpred): val -> mpred :=
match n with
| O => fun _ => emp
| S n' => P lo * rangespec (Z.succ lo) n' P
end.
Fixpoint fold_range' {A: Type} (f: Z -> A -> A) (zero: A) (lo: Z) (n: nat) : A :=
match n with
| O => zero
| S n' => f lo (fold_range' f  zero (Z.succ lo) n')
end.
Definition fold_range {A: Type} (f: Z -> A -> A) (zero: A) (lo hi: Z) : A :=
fold_range' f zero lo (Z.to_nat (hi-lo)).
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.

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.