(****************)
(* main methods *)
(****************)

Definition def h := if h is Def _ _ then true else false.Definition empty := @Def (finmap.nil _ _) is_true_true.Definition dom h : pred ptr := nosimpl
  (if h is Def f _ then mem (supp f) else pred0).Definition free x h : heap :=
  (if h is Def hs ns then Def (free_nullP x ns) else Undef).Definition look (x : ptr) h :=
  (if h is Def hs _ then
    if fnd x hs is Some d then d else dyn tt
  else dyn tt).Definition union2 h1 h2 := nosimpl
  (if (h1, h2) is (Def hs1 ns1, Def hs2 ns2) then
     if disj hs1 hs2 then
        Def (@un_nullP _ _ ns1 ns2)
     else Undef
  else Undef).(* Definition subheap h1 h2 p :=  *)
(*   if (h1, h2) is (Def hs1 _, Def hs2 _) then  *)
(*     all (fun x => p (look x h1) (look x h2)) (supp hs1) *)
(*   else false. *)

Definition subtract h1 h2 :=
  if h1 is (Def hs1 _) then
    foldl (fun h x => free x h) h2 (supp hs1)
  else Undef.Definition pick h :=
  if h is Def hs _ then head null (supp hs) else null.Definition pts A (x : ptr) (v : A) := upd empty x (dyn v).Notation "h1 :+ h2" := (union2 h1 h2) (at level 43, left associativity).Notation "h2 :- h1" := (subtract h1 h2) (at level 43, left associativity).Notation "x :-> v" := (pts x v) (at level 30).

Lemma last_inv A B (f : A -> B) (x1 x2 : A) (h : seq A) : f x1 = f x2 -> f (last x1 h) = f (last x2 h).