(* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. *) open Import0 include Map_intf module Make (Key : sig type t [@@deriving compare, sexp_of] end) : S with type key = Key.t = struct module KeyMap = Core.Map.Make_plain (Key) module Key = KeyMap.Key type key = Key.t include KeyMap.Tree let compare = compare_direct let to_map t = Core.Map.Using_comparator.of_tree ~comparator:Key.comparator t let of_map m = Base.Map.Using_comparator.to_tree m let merge_skewed x y ~combine = of_map (Core.Map.merge_skewed (to_map x) (to_map y) ~combine) let map_endo t ~f = map_endo map t ~f let merge_endo t u ~f = let change = ref false in let t' = merge t u ~f:(fun ~key side -> let f_side = f ~key side in ( match (side, f_side) with | (`Both (data, _) | `Left data), Some data' when data' == data -> () | _ -> change := true ) ; f_side ) in if !change then t' else t let fold_until m ~init ~f ~finish = let fold m ~init ~f = let f ~key ~data s = f s (key, data) in fold m ~init ~f in let f s (k, v) = f ~key:k ~data:v s in Container.fold_until ~fold ~init ~f ~finish m let root_key_exn m = with_return @@ fun {return} -> binary_search_segmented m `Last_on_left ~segment_of:(fun ~key ~data:_ -> return key ) |> ignore ; raise (Not_found_s (Atom __LOC__)) let choose_exn m = with_return @@ fun {return} -> binary_search_segmented m `Last_on_left ~segment_of:(fun ~key ~data -> return (key, data) ) |> ignore ; raise (Not_found_s (Atom __LOC__)) let choose m = try Some (choose_exn m) with Not_found_s _ -> None let pop m = choose m |> Option.map ~f:(fun (k, v) -> (k, v, remove m k)) let pop_min_elt m = min_elt m |> Option.map ~f:(fun (k, v) -> (k, v, remove m k)) let is_singleton m = try let l, _, r = split m (root_key_exn m) in is_empty l && is_empty r with Not_found_s _ -> false let find_and_remove m k = let found = ref None in let m = change m k ~f:(fun v -> found := v ; None ) in Option.map ~f:(fun v -> (v, m)) !found let pp pp_k pp_v fs m = Format.fprintf fs "@[<1>[%a]@]" (List.pp ",@ " (fun fs (k, v) -> Format.fprintf fs "@[%a@ @<2>↦ %a@]" pp_k k pp_v v )) (to_alist m) let pp_diff ~data_equal pp_key pp_val pp_diff_val fs (x, y) = let pp_diff_elt fs = function | k, `Left v -> Format.fprintf fs "-- [@[%a@ @<2>↦ %a@]]" pp_key k pp_val v | k, `Right v -> Format.fprintf fs "++ [@[%a@ @<2>↦ %a@]]" pp_key k pp_val v | k, `Unequal vv -> Format.fprintf fs "[@[%a@ @<2>↦ %a@]]" pp_key k pp_diff_val vv in let sd = Sequence.to_list (symmetric_diff ~data_equal x y) in if not (List.is_empty sd) then Format.fprintf fs "[@[%a@]];@ " (List.pp ";@ " pp_diff_elt) sd end