Require Import AggregateType.demo1.expr.
Require Import AggregateType.demo1.type_rec_functions.
Require Import AggregateType.demo1.path_rec_functions.
Definition field_at (t: type) (nf: list ident) (v: reptype (nested_field_type t nf)) (p: val) : Pred := data_at_rec (nested_field_type t nf) v (offset_val (nested_field_offset t nf) p).
Definition data_at (t: type) (v: reptype t) (p: val) : Pred := field_at t nil v p.
Definition field_address (t: type) (nf: list ident) (p: val) : val := offset_val (nested_field_offset t nf) p.
(* Unfolding Equations *)
Lemma data_at_field_at: forall t v p,
data_at t v p = field_at t nil v p.
Lemma field_at_Tint: forall t nf v1 v2 p,
nested_field_type t nf = Tint ->
field_at t nf v1 p = mapsto (field_address t nf p) v2.
unfold field_at, field_address.
apply JMeq_eq in H0. subst v1.
Lemma field_at_Tstruct: forall t nf id fs v p,
nested_field_type t nf = Tstruct id fs ->
members_no_replicate fs ->
(fix field_at_struct fs :=
field_at t (i0 :: nf) (proj_reptype _ (i0 :: nil) v) p *
simpl; revert v; rewrite H; simpl; clear H.
set (ofs := nested_field_offset t nf); clearbody ofs; clear t.
assert (forall i, in_members i fs -> field_type i fs = field_type i fs) by auto.
assert (forall i, in_members i fs -> JMeq (proj_struct i fs v) (proj_struct i fs v)) by (intros; apply JMeq_refl).
generalize fs at 1 4 8 9 11 12 13 14.
induction fs as [| [i0 t0] fs0]; auto.
+ rewrite offset_offset_val.
specialize (H i0 (or_introl eq_refl)).
specialize (H1 i0 (or_introl eq_refl)).
set (v0 := proj_struct i0 fs_full v') in *; clearbody v0; clear v'.
revert v0 H1; rewrite <- H; intros.
apply JMeq_eq in H1; rewrite <- H1.
destruct (ident_eq i0 i0); [auto | congruence].
rewrite <- H by (right; auto).
destruct (ident_eq i i0); [subst; destruct H0; tauto | auto].
eapply JMeq_trans; [| apply H1; right; auto].
destruct (ident_eq i i0); [subst; destruct H0; tauto | auto].
Lemma field_at_Tstruct': forall t nf id fs v p i,
nested_field_type t nf = Tstruct id fs ->
members_no_replicate fs ->
field_at t (i :: nf) (proj_reptype _ (i :: nil) v) p *
(fix field_at_struct fs :=
else field_at t (i0 :: nf) (proj_reptype _ (i0 :: nil) v) p) *
erewrite field_at_Tstruct by eauto.
(fix field_at_struct (fs0 : fieldlist) : Pred :=
(proj_reptype (nested_field_type t nf) (i0 :: nil) v) p *
(fix field_at_struct (fs0 : fieldlist) : Pred :=
(proj_reptype (nested_field_type t nf) (i0 :: nil) v) p) *
induction fs as [| [i0 t0] fs0].
+ split; [auto | intros []].
+ specialize (IHfs0 (proj2 H0)).
destruct IHfs0 as [IH0 IH1]; split.
specialize (IH0 (fun im => H (or_intror im))).
destruct (ident_eq i0 i); [simpl in H; subst; tauto | auto].
destruct (ident_eq i0 i).
* rewrite <- sepcon_assoc, (sepcon_comm (field_at t (i :: nf) _ _)), sepcon_assoc.
destruct H1; [subst; tauto | auto].
(* Ramification Premises for Nested Load/Store Rule *)
Lemma RP_one_layer: forall t nf f u v p,
legal_nested_field t (f :: nf) ->
(proj_gfield_reptype (nested_field_type t nf) f u) p *
(field_at t (f :: nf) v p -*
field_at t nf (upd_gfield_reptype (nested_field_type t nf) f u v) p).
unfold legal_field in H1.
remember (nested_field_type t nf) as t0 eqn:?H in H1.
destruct t0; [tauto | symmetry in H2].
pose proof legal_type_nested_field_type t nf H0 H.
rewrite H2 in H3; apply nested_pred_atom_pred in H3.
rewrite (field_at_Tstruct' t nf id fs u p f) by auto.
rewrite (field_at_Tstruct' t nf id fs (upd_gfield_reptype (nested_field_type t nf) f u v) p f); auto.
rewrite proj_upd_gfield_reptype_hit by (rewrite H2; auto).
match goal with | |- _ * ?A |-- _ => apply RAMIF_PLAIN.solve with A end; auto.
apply sepcon_derives; auto.
induction fs as [| [i0 t0] fs0]; auto.
+ destruct (ident_eq i0 f); auto.
rewrite proj_upd_gfield_reptype_miss by congruence.
Lemma RP_field: forall t nf u v p,
legal_nested_field t nf ->
data_at t u p |-- field_at t nf (proj_reptype t nf u) p *
(field_at t nf v p -* data_at t (upd_reptype t nf u v) p).
+ apply RAMIF_PLAIN.solve with emp.
rewrite sepcon_emp; apply derives_refl.
rewrite emp_sepcon; apply derives_refl.
specialize (IHnf (upd_gfield_reptype _ a (proj_reptype t nf u) v) H).
eapply RAMIF_PLAIN.trans; try eassumption.
apply RP_one_layer; simpl; auto.
Lemma RP_mapsto: forall t nf u v p w0 w1,
legal_nested_field t nf ->
nested_field_type t nf = Tint ->
JMeq (proj_reptype t nf u) w0 ->
data_at t u p |-- mapsto (field_address t nf p) w0 *
(mapsto (field_address t nf p) w1 -* data_at t (upd_reptype t nf u v) p).
pose proof RP_field t nf u v p H H0.
erewrite !(field_at_Tint t nf) in H4; eassumption.
Lemma Lemma1: forall t nf u p w,
legal_nested_field t nf ->
nested_field_type t nf = Tint ->
JMeq (proj_reptype t nf u) w ->
data_at t u p |-- mapsto (field_address t nf p) w * TT.
assert (JMeq (default_val (nested_field_type t nf)) Vundef) by (rewrite H1; auto).
pose proof RP_mapsto t nf u (default_val _) p w Vundef H H0 H1 H2 H3.
eapply derives_trans; [exact H4 |].
apply sepcon_derives; auto.
Lemma field_at_data_at: forall t nf v p,
field_at t nf v p = data_at _ v (field_address t nf p).
unfold data_at, field_at, field_address.
rewrite offset_offset_val.