Ltac drop_LOCAL n :=
first [apply (drop_LOCAL n) | apply (drop_LOCAL' n) | apply (drop_LOCAL'' n)];
unfold delete_nth.
Fixpoint find_LOCAL_index (name: ident) (current: nat) (l : list localdef) : option nat :=
match l with
| h :: t => match h with
| temp  i _   => if (i =? name)%positive then Some current else find_LOCAL_index name (S current) t
| lvar  i _ _ => if (i =? name)%positive then Some current else find_LOCAL_index name (S current) t
| gvars _ => find_LOCAL_index name (S current) t
end
| nil => None
end.
Ltac drop_LOCAL_by_name name := match goal with
| |- semax _ (PROPx ?P (LOCALx ?Q (SEPx ?R))) _ _ =>
let r := eval hnf in (find_LOCAL_index name O Q) in match r with
| Some ?i => drop_LOCAL i
| None => fail 1 "No variable named" name "found"
end
end.
Ltac drop_LOCALs l := match l with
| ?h :: ?t => drop_LOCAL_by_name h; drop_LOCALs t
| nil => idtac
end.
Ltac clean_up_app_carefully := (* useful after rewriting by SEP_PROP *)
repeat
match goal with
| |- context [@app Prop (?a :: ?b) ?c] =>
change (app (a::b) c) with (a :: app b c)
| |- context [@app (environ->Prop) (?a :: ?b) ?c] =>
change (app (a::b) c) with (a :: app b c)
| |- context [@app (lifted (LiftEnviron Prop)) (?a :: ?b) ?c] =>
change (app (a::b) c) with (a :: app b c)
| |- context [@app (environ->mpred) (?a :: ?b) ?c] =>
change (app (a::b) c) with (a :: app b c)
| |- context [@app (lifted (LiftEnviron mpred)) (?a :: ?b) ?c] =>
change (app (a::b) c) with (a :: app b c)
| |- context [@app Prop nil ?c] =>
change (app nil c) with c
| |- context [@app (environ->Prop) nil ?c] =>
change (app nil c) with c
| |- context [@app (lifted (LiftEnviron Prop)) nil ?c] =>
change (app nil c) with c
| |- context [@app (lifted (environ->mpred)) nil ?c] =>
change (app nil c) with c
| |- context [@app (lifted (LiftEnviron mpred)) nil ?c] =>
change (app nil c) with c
end.
Definition not_conj_notation (P: Prop) := True.
Ltac not_conj_notation :=
match goal with
| |- not_conj_notation (_ <= _ <= _)%Z => fail 1
| |- not_conj_notation (_ <= _ < _)%Z => fail 1
| |- not_conj_notation (_ < _ <= _)%Z => fail 1
| |- not_conj_notation (_ <= _ <= _)%nat => fail 1
| |- not_conj_notation (_ <= _ < _)%nat => fail 1
| |- not_conj_notation (_ < _ <= _)%nat => fail 1
| |- _ => apply Coq.Init.Logic.I
end.

(* Specifications: *)
Lemma split_first_PROP:
forall P Q R S,
not_conj_notation (P/\Q) ->
PROPx ((P/\Q)::R) S = PROPx (P::Q::R) S.