Require Export VST.floyd.fieldlist.
Require Export VST.floyd.compact_prod_sum.
Require Export VST.floyd.sublist.
Definition proj_struct (i : ident) (m : members) {A: ident * type -> Type} (v: compact_prod (map A m)) (d: A (i, field_type i m)): A (i, field_type i m) :=
proj_compact_prod (i, field_type i m) m v d member_dec.
Definition proj_union (i : ident) (m : members) {A: ident * type -> Type} (v: compact_sum (map A m)) (d: A (i, field_type i m)): A (i, field_type i m) :=
proj_compact_sum (i, field_type i m) m v d member_dec.
Definition members_union_inj {m: members} {A} (v: compact_sum (map A m)) (it: ident * type): Prop :=
compact_sum_inj v it member_dec.
Definition upd_sublist {X: Type} (lo hi: Z) (l: list X) (l0: list X) : list X :=
firstn (Z.to_nat lo) l ++ l0 ++ skipn (Z.to_nat hi) l.
(* TODO: We should use the following two definition in replace_refill lemmas in the future. And avoid using compact prod/sum directly. *)
Definition upd_struct (i : ident) (m : members) {A: ident * type -> Type} (v: compact_prod (map A m)) (v0: A (i, field_type i m)): compact_prod (map A m) :=
upd_compact_prod _ v (i, field_type i m) v0 member_dec.
Definition upd_union (i : ident) (m : members) {A: ident * type -> Type} (v: compact_sum (map A m)) (v0: A (i, field_type i m)): compact_sum (map A m) :=
upd_compact_sum _ v (i, field_type i m) v0 member_dec.

(* Specifications: *)
Lemma proj_struct_JMeq: forall (i: ident) (m : members) {A1 A2: ident * type -> Type} (v1: compact_prod (map A1 m)) (v2: compact_prod (map A2 m)) (d1: A1 (i, field_type i m)) (d2: A2 (i, field_type i m)),
(forall i, in_members i m -> @eq Type (A1 (i, field_type i m)) (A2 (i, field_type i m))) ->
members_no_replicate m = true ->
in_members i m ->
JMeq v1 v2 ->
JMeq (proj_struct i m v1 d1) (proj_struct i m v2 d2).
Lemma members_union_inj_JMeq: forall (m : members) {A1 A2: ident * type -> Type} (v1: compact_sum (map A1 m)) (v2: compact_sum (map A2 m)),
(forall i, in_members i m -> @eq Type (A1 (i, field_type i m)) (A2 (i, field_type i m))) ->
members_no_replicate m = true ->
JMeq v1 v2 ->
(forall it, members_union_inj v1 it <-> members_union_inj v2 it).
Lemma proj_union_JMeq: forall (i: ident) (m : members) {A1 A2: ident * type -> Type} (v1: compact_sum (map A1 m)) (v2: compact_sum (map A2 m)) (d1: A1 (i, field_type i m)) (d2: A2 (i, field_type i m)),
(forall i, in_members i m -> @eq Type (A1 (i, field_type i m)) (A2 (i, field_type i m))) ->
members_no_replicate m = true ->
members_union_inj v1 (i, field_type i m) ->
JMeq v1 v2 ->
JMeq (proj_union i m v1 d1) (proj_union i m v2 d2).