Module SortZ := Mergesort.Sort(ZOrder).Definition Zlist_complement (n: nat) (al: list Z) : list Z :=
  let bl := SortZ.sort al
  in Zlist_complement' 0 n bl.(* Compute Zlist_complement 9 [4;5;3]. *)

Ltac find_freeze1 comp id A :=
lazymatch goal with
| fr := @abbreviate mpred _ |- semax _ (PROPx _ (LOCALx _ (SEPx ?R))) _ _ =>
  match R with context [fr :: ?R'] =>
    let L := constr:(Zlength R - (Z.succ (Zlength R'))) in
     let L := eval cbn in L in
      let A' := constr:(L::A) in
        unfold abbreviate in fr; subst fr; find_freeze1 comp id A'
   end
| |- semax _ (PROPx _ (LOCALx _ (SEPx ?R))) _ _ => 
            let A' := constr:(if comp then Zlist_complement (length R) A 
                                     else A) in
            let A' := eval compute in A' in
            freeze_tac A' id
end.Ltac freezer i := find_freeze1  false i (@nil Z).Ltac complement_freezer i := find_freeze1 true i (@nil Z).

(* Specifications: *)
Lemma flatten_emp_in_mpreds': forall n (R: list mpred), nth_error R n = Some emp -> SEPx R = SEPx (firstn n R ++ skipn (S n) R).
Lemma flatten_emp_in_SEP': forall n P Q (R: list mpred) R', nth_error R n = Some emp -> R' = firstn n R ++ skipn (S n) R -> PROPx P (LOCALx Q (SEPx R)) = PROPx P (LOCALx Q (SEPx R')).