(*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.
Opaque member_dec.

Lemma compact_sum_inj_eq_spec: forall {A} a0 a1 (l: list A) F0 F1 (v0: compact_sum (map F0 (a0 :: a1 :: l))) (v1: compact_sum (map F1 (a0 :: a1 :: l))) H,
~ In a0 (a1 :: l) ->
((forall a, compact_sum_inj v0 a H <-> compact_sum_inj v1 a H) <->
match v0, v1 with
| inl _, inl _ => True
| inr v0, inr v1 => forall a, compact_sum_inj (v0: compact_sum (map F0 (a1 :: l))) a H <-> compact_sum_inj (v1: compact_sum (map F1 (a1 :: l))) a H
| _, _ => False
end).