Section SEMAX_PTREE.
Context {cs: compspecs}.
Definition proj_val t_root gfs v :=
repinject (nested_field_type t_root gfs) (proj_reptype t_root gfs v).
Definition upd_val t_root gfs v v0 :=
upd_reptype t_root gfs v (valinject (nested_field_type t_root gfs) v0).
End SEMAX_PTREE.
Ltac SEP_field_at_unify' gfs :=
match goal with
| |- field_at ?shl ?tl ?gfsl ?vl ?pl = field_at ?shr ?tr ?gfsr ?vr ?pr =>
unify tl tr;
unify (skipn (length gfs - length gfsl) gfs) gfsl;
unify gfsl gfsr;
unify shl shr;
unify vl vr;
generalize vl; intro;
rewrite <- ?field_at_offset_zero;
f_equal; (* this line is important to prevent blow-ups *)
reflexivity
end.
Ltac SEP_field_at_unify gfs :=
match goal with
| |- data_at _ _ _ _ = _ =>
unfold data_at; SEP_field_at_unify' gfs
| |- data_at_ _ _ _ = _ =>
unfold data_at_, field_at_; SEP_field_at_unify' gfs
| |- field_at _ _ _ _ _ = _ =>
SEP_field_at_unify' gfs
| |- field_at_ _ _ _ _ = _ =>
unfold field_at_; SEP_field_at_unify' gfs
end.
Ltac SEP_field_at_strong_unify' gfs :=
match goal with
| |- @field_at ?cs ?shl ?tl ?gfsl ?vl ?pl = ?Rv ?vr /\ (_ = fun v => field_at ?shr ?tr ?gfsr v ?pr) =>
unify tl tr;
unify (skipn (length gfs - length gfsl) gfs) gfsl;
unify gfsl gfsr;
unify shl shr;
unify vl vr;
split;
[ match type of vl with
| ?tv1 => unify Rv (fun v: tv1 => @field_at cs shl tl gfsl v pl)
end; reflexivity
| extensionality;
rewrite <- ?field_at_offset_zero; reflexivity]
| |- @data_at ?cs ?shl ?tl ?vl ?pl = ?Rv ?vr /\ (_ = fun v => field_at ?shr ?tr ?gfsr v ?pr) =>
unify tl tr;
unify gfsr (@nil gfield);
unify shl shr;
unify vl vr;
split;
[ match type of vl with
| ?tv1 => unify Rv (fun v: tv1 => @data_at cs shl tl v pl)
end; reflexivity
| extensionality;
unfold data_at;
rewrite <- ?field_at_offset_zero; reflexivity]
end.
Ltac SEP_field_at_strong_unify gfs :=
match goal with
| |- data_at_ ?sh ?t ?p = _ /\ _ =>
change (data_at_ sh t p) with (data_at sh t (default_val t) p);
SEP_field_at_strong_unify' gfs
| |- field_at_ _ _ _ _ = _ /\ _ =>
unfold field_at_; SEP_field_at_strong_unify' gfs
| _ => SEP_field_at_strong_unify' gfs
end.
(* simplifies a list expression into [e1; e2; ...] form without simplifying its elements *)
Ltac eval_list l :=
let l' := eval hnf in l in lazymatch l' with
| ?h :: ?tl => let tl' := eval_list tl in constr:(h :: tl')
| (@nil ?T) => constr:(@nil T)
end.
Ltac prove_gfs_suffix gfs :=
match goal with
| |- _ = ?gfs1 ++ ?gfs0 =>
let len := fresh "len" in
let gfs1' := eval_list (firstn ((length gfs - length gfs0)%nat) gfs) in
unify gfs1 gfs1';
reflexivity
end.
Ltac test_field_at_in_SEP :=
cbv beta;
match goal with
| |- ?A /\ ?gfs = _ ++ _ =>
split; [ match A with
| _ /\ _ => SEP_field_at_strong_unify gfs
| _ => SEP_field_at_unify gfs
end
| prove_gfs_suffix gfs]
end.
Ltac search_field_at_in_SEP := find_nth test_field_at_in_SEP.

Lemma quick_derives_right:
forall P Q : environ -> mpred,
TT |-- Q -> P |-- Q.