Module ConseqFacts :=
SeparationLogicFacts.GenConseqFacts
(SeparationLogicAsLogicSoundness.MainTheorem.CSHL_PracticalLogic.CSHL_MinimumLogic.CSHL_Def)
(Conseq).
(* OLD VERSION: Lemma semax_post': forall R' Espec {cs: compspecs} Delta R P c, R' |-- R -> @semax cs Espec Delta P c (normal_ret_assert R') -> @semax cs Espec Delta P c (normal_ret_assert R). *)
intros.
destruct Q as [?Q ?Q ?Q ?Q].
eapply semax_post; eauto; intros; apply andp_left2; simpl; auto; normalize.
Qed.
Ltac frame_SEP' L :=  (* this should be generalized to permit framing on LOCAL part too *)
grab_indexes_SEP L;
match goal with
| |- @semax _ _ (PROPx _ (LOCALx _ (SEPx ?R))) _ _ =>
rewrite <- (firstn_skipn (length L) R);
simpl length; unfold firstn, skipn;
eapply (semax_frame_PQR nil);
[ unfold closed_wrt_modvars;  auto 50 with closed
| ]
| |- ENTAIL _ , (PROPx _ (LOCALx _ (SEPx ?R))) |-- _ =>
rewrite <- (firstn_skipn (length L) R);
simpl length; unfold firstn, skipn;
apply derives_frame_PQR
end.
Tactic Notation "frame_SEP" constr(a) :=
frame_SEP' (a::nil).
Tactic Notation "frame_SEP" constr(a) constr(b) :=
frame_SEP' (a::b::nil).
Tactic Notation "frame_SEP" constr(a) constr(b) constr(c) :=
frame_SEP' (a::b::c::nil).
Tactic Notation "frame_SEP" constr(a) constr(b) constr(c) constr(d) :=
frame_SEP' (a::b::c::d::nil).
Tactic Notation "frame_SEP" constr(a) constr(b) constr(c) constr(d) constr(e) :=
frame_SEP' (a::b::c::d::e::nil).
Tactic Notation "frame_SEP" constr(a) constr(b) constr(c) constr(d) constr(e) constr(f) :=
frame_SEP' (a::b::c::d::e::f::nil).
Tactic Notation "frame_SEP" constr(a) constr(b) constr(c) constr(d) constr(e) constr(f) constr(g) :=
frame_SEP' (a::b::c::d::e::f::g::nil).
Tactic Notation "frame_SEP" constr(a) constr(b) constr(c) constr(d) constr(e) constr(f) constr(g) constr(h) :=
frame_SEP' (a::b::c::d::e::f::g::h::nil).
Tactic Notation "frame_SEP" constr(a) constr(b) constr(c) constr(d) constr(e) constr(f) constr(g) constr(h) constr(i) :=
frame_SEP' (a::b::c::d::e::f::g::h::i::nil).
Tactic Notation "frame_SEP" constr(a) constr(b) constr(c) constr(d) constr(e) constr(f) constr(g) constr(h) constr(i) constr(j) :=
frame_SEP' (a::b::c::d::e::f::g::h::i::j::nil).

Lemma gather_SEP:
forall R1 R2,
SEPx (R1 ++ R2) = SEPx (fold_right sepcon emp R1 :: R2).