Module Freezer : FREEZER.
Definition FRZ (p: mpred) := p.
Definition FRZL (ps:list mpred): mpred := fold_right sepcon emp ps.
Inductive FRZRw' (L1 G1: list mpred): Type :=
| FRZRw'_constr: forall F: mpred,
(fold_right sepcon emp G1) |-- fold_right sepcon emp L1 * F -> FRZRw' L1 G1.
Definition FRZRw := FRZRw'.
Definition FRZRw_constr:= FRZRw'_constr.
Definition FRZR (L1 G1: list mpred) {w: FRZRw L1 G1}: mpred :=
match w with
| FRZRw'_constr F _ => F
end.
Tactic Notation "freeze1_SEP" constr(n) :=
eapply (freeze1_SEP' (Z.to_nat n)); simpl.
Tactic Notation "freeze1_SEP" constr(n) constr(m) :=
(gather_SEP' (n::m::nil)); eapply (freeze1_SEP' (Z.to_nat 0)); simpl.
Tactic Notation "freeze1_SEP" constr(n) constr(m) constr(k)  :=
(gather_SEP' (n::m::k::nil)); eapply (freeze1_SEP' (Z.to_nat 0)); simpl.
Tactic Notation "freeze1_SEP" constr(n) constr(m) constr(k)  constr(p) :=
(gather_SEP' (n::m::k::p::nil)); eapply (freeze1_SEP' (Z.to_nat 0)); simpl.
Tactic Notation "freeze1_SEP" constr(n) constr(m) constr(k) constr(p) constr(q) :=
(gather_SEP' (n::m::k::p::q::nil)); eapply (freeze1_SEP' (Z.to_nat 0)); simpl.
(*******************freezing a list of mpreds ******************************)
Fixpoint delete_list {A: Type} (ns: list nat) (xs: list A) : list A :=
(* ns must already be sorted *)
match ns with
| nil => xs
| n::ns' => delete_nth n (delete_list ns' xs)
end.
Definition freezelist_nth (ns: list nat) (al: list mpred) : list mpred * list mpred :=
(map (fun i => my_nth i al emp) ns,
delete_list (SortNat.sort ns) al).
Function is_increasing (ns: list nat) (last: nat) {measure length ns}: bool  :=
match ns with
| nil => true
| a::nil => Nat.ltb a last
| a::b::ns' => andb (Nat.ltb a b) (is_increasing (b::ns') last)
end.
*)

(* This older version of freezelist_nth didn't work when the l list was not sorted Fixpoint freezelist_nth (l: list nat) (al: list mpred): (list mpred) * (list mpred) := match l with | nil => (nil,al) | (n::l') => let (xs, ys) := freezelist_nth l' al in (nth n ys emp::xs, delete_nth n ys) end. *)
Lemma FRZL_ax ps: FRZL ps = fold_right_sepcon ps.
Lemma fold_right_sepcon_deletenth': forall n (l:list (LiftEnviron mpred)),
@fold_right (environ -> mpred) (environ -> mpred) sepcon emp l =
nth n l emp * fold_right sepcon emp (delete_nth n l).