Ltac flatten_in_SEP PQR :=
match PQR with
| PROPx ?P (LOCALx ?Q (SEPx (?R))) =>
match R with context [(?R1 * ?R2) :: ?R'] =>
let n := constr:((length R - Datatypes.S (length R'))%nat) in
let n' := eval lazy beta zeta iota delta in n in
erewrite(@flatten_sepcon_in_SEP'' n' P Q R1 R2 R _ (eq_refl _));
[ |
let RR := fresh "RR" in set (RR := R);
let RR1 := fresh "RR1" in set (RR1 := R1);
let RR2 := fresh "RR2" in set (RR2 := R2);
unfold firstn, app, skipn; subst RR RR1 RR2; cbv beta iota;
apply eq_refl
]
end
end.
Ltac flatten_sepcon_in_SEP :=
match goal with
| |- semax _ ?PQR _ _ => flatten_in_SEP PQR
| |-  ENTAIL _, ?PQR |-- _ => flatten_in_SEP PQR
end.

(* Specifications: *)
Lemma semax_ff:
forall Espec {cs: compspecs} Delta c R,
@semax cs Espec Delta FF c R.
Lemma extract_prop_in_SEP:
forall n P1 Rn P Q R,
nth n R emp = prop P1 && Rn ->
PROPx P (LOCALx Q (SEPx R)) = PROPx (P1::P) (LOCALx Q (SEPx (replace_nth n R Rn))).
Lemma insert_SEP:
forall R1 P Q R, `R1 * PROPx P (LOCALx Q (SEPx R)) = PROPx P (LOCALx Q (SEPx (R1::R))).
Lemma delete_emp_in_SEP:
forall n (R: list mpred),
nth_error R n = Some emp ->
SEPx R = SEPx (firstn n R ++ list_drop (S n) R).