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).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).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 struct_pred (m: members) {A: ident * type -> Type} (P: forall it, A it -> val -> mpred) (v: compact_prod (map A m)) (p: val): mpred.(* when unfold, do cbv [struct_pred list_rect]. *)

Definition union_pred (m: members) {A: ident * type -> Type} (P: forall it, A it -> val -> mpred) (v: compact_sum (map A m)) (p: val): mpred.Definition array_Prop {A: Type} (d:A) (lo hi: Z) (P: Z -> A -> Prop) (v: list A) : Prop :=
   Zlength v = hi-lo /\ Forallz P 0 v.Definition struct_Prop (m: members) {A: ident * type -> Type}
                             (P: forall it, A it -> Prop) (v: compact_prod (map A m)) : Prop.Definition union_Prop (m: members) {A: ident * type -> Type}
               (P: forall it, A it -> Prop) (v: compact_sum (map A m)): Prop.

(* Specifications: *)
Lemma array_pred_len_0: forall {A}{d: Inhabitant A} lo hi P p, hi = lo -> array_pred lo hi P nil p = emp.
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: 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.
Lemma struct_pred_ext: forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p, members_no_replicate m = true -> (forall i d0 d1, in_members i m -> P0 _ (proj_struct i m v0 d0) p = P1 _ (proj_struct i m v1 d1) p) -> struct_pred m P0 v0 p = struct_pred m P1 v1 p.
Lemma struct_pred_not_member: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p, let P' it := if ident_eq i (fst it) then fun _ _ => emp else P it in ~ in_members i m -> struct_pred m P v p = struct_pred m P' v p.
Lemma struct_pred_proj: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p d, let P' it := if ident_eq i (fst it) then fun _ _ => emp else P it in members_no_replicate m = true -> in_members i m -> struct_pred m P v p = P _ (proj_struct i m v d) p * struct_pred m P' v p.
Lemma struct_pred_upd: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p v0, let P' it := if ident_eq i (fst it) then fun _ _ => emp else P it in members_no_replicate m = true -> in_members i m -> struct_pred m P (upd_struct i m v v0) p = P _ v0 p * struct_pred m P' v p.
Lemma at_offset_struct_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p ofs, at_offset (struct_pred m P v) ofs p = struct_pred m (fun it v => at_offset (P it v) ofs) v p.
Lemma corable_andp_struct_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p Q, corable Q -> Q && struct_pred m P v p = match m with | nil => Q && emp | _ => struct_pred m (fun it v p => Q && P it v p) v p end.
Lemma struct_pred_sepcon: forall m {A} (P Q: forall it, A it -> val -> mpred) v p, struct_pred m P v p * struct_pred m Q v p = struct_pred m (fun it => P it * Q it) v p.
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).
Lemma union_pred_ext: forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p, members_no_replicate m = true -> (forall it, members_union_inj v0 it <-> members_union_inj v1 it) -> (forall i d0 d1, members_union_inj v0 (i, field_type i m) -> members_union_inj v1 (i, field_type i m) -> P0 _ (proj_union i m v0 d0) p = P1 _ (proj_union i m v1 d1) p) -> union_pred m P0 v0 p = union_pred m P1 v1 p.
Lemma union_pred_upd: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p v0, members_no_replicate m = true -> in_members i m -> union_pred m P (upd_union i m v v0) p = P _ v0 p.
Lemma at_offset_union_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p ofs, at_offset (union_pred m P v) ofs p = union_pred m (fun it v => at_offset (P it v) ofs) v p.
Lemma andp_union_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p Q, Q && union_pred m P v p = match m with | nil => Q && emp | _ => union_pred m (fun it v p => Q && P it v p) v p end.
Lemma union_pred_sepcon: forall m {A} (P Q: forall it, A it -> val -> mpred) v p, union_pred m P v p * union_pred m Q v p = union_pred m (fun it => P it * Q it) v p.
Lemma struct_Prop_compact_prod_gen: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) (f: forall it, F it), members_no_replicate m = true -> (forall i, in_members i m -> P (i, field_type i m) (f (i, field_type i m))) -> struct_Prop m P (compact_prod_gen f m).
Lemma struct_Prop_proj: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) v i d, in_members i m -> struct_Prop m P v -> P (i, field_type i m) (proj_struct i m v d).
Lemma union_Prop_compact_sum_gen: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) (f: forall it, F it), members_no_replicate m = true -> (forall i, in_members i m -> P (i, field_type i m) (f (i, field_type i m))) -> union_Prop m P (compact_sum_gen (fun _ => true) f m).
Lemma union_Prop_proj: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) v i d, members_union_inj v (i, field_type i m) -> union_Prop m P v -> P (i, field_type i m) (proj_union i m v d).
Lemma memory_block_array_pred: forall {A}{d: Inhabitant A} sh t lo hi v b ofs, 0 <= ofs + sizeof t * lo /\ ofs + sizeof t * hi < Ptrofs.modulus -> 0 <= lo <= hi -> Zlength v = hi - lo -> array_pred lo hi (fun i _ p => memory_block sh (sizeof t) (offset_val (sizeof t * i) p)) v (Vptr b (Ptrofs.repr ofs)) = memory_block sh (sizeof t * (hi - lo)) (Vptr b (Ptrofs.repr (ofs + sizeof t * lo))).
Lemma memory_block_array_pred': forall {A}{d: Inhabitant A} (a: A) sh t z b ofs, 0 <= z -> 0 <= ofs /\ ofs + sizeof t * z < Ptrofs.modulus -> array_pred 0 z (fun i _ p => memory_block sh (sizeof t) (offset_val (sizeof t * i) p)) (list_repeat (Z.to_nat z) a) (Vptr b (Ptrofs.repr ofs)) = memory_block sh (sizeof t * z) (Vptr b (Ptrofs.repr ofs)).
Lemma memory_block_struct_pred: forall sh m sz {A} (v: compact_prod (map A m)) b ofs, (m = nil -> sz = 0) -> members_no_replicate m = true -> sizeof_struct cenv_cs 0 m <= sz < Ptrofs.modulus -> 0 <= ofs /\ ofs + sz < Ptrofs.modulus -> struct_pred m (fun it _ p => (memory_block sh (field_offset_next cenv_cs (fst it) m sz - field_offset cenv_cs (fst it) m)) (offset_val (field_offset cenv_cs (fst it) m) p)) v (Vptr b (Ptrofs.repr ofs)) = memory_block sh sz (Vptr b (Ptrofs.repr ofs)).
Lemma memory_block_union_pred: forall sh m sz {A} (v: compact_sum (map A m)) b ofs, (m = nil -> sz = 0) -> union_pred m (fun it _ => memory_block sh sz) v (Vptr b (Ptrofs.repr ofs)) = memory_block sh sz (Vptr b (Ptrofs.repr ofs)).