(*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_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.