module AtomPool = Pool.Make(SortedList.String) type v = AtomPool.t let value = AtomPool.value let mk = AtomPool.mk module SList = SortedList.Make_transp(SortedList.Lift(AtomPool)) type t = Finite of unit SList.t | Cofinite of unit SList.t let empty = Finite [] let any = Cofinite [] let atom x = Finite [x] let cup s t = match (s,t) with | (Finite s, Finite t) -> Finite (SList.cup s t) | (Finite s, Cofinite t) -> Cofinite (SList.diff t s) | (Cofinite s, Finite t) -> Cofinite (SList.diff s t) | (Cofinite s, Cofinite t) -> Cofinite (SList.cap s t) let cap s t = match (s,t) with | (Finite s, Finite t) -> Finite (SList.cap s t) | (Finite s, Cofinite t) -> Finite (SList.diff s t) | (Cofinite s, Finite t) -> Finite (SList.diff t s) | (Cofinite s, Cofinite t) -> Cofinite (SList.cup s t) let diff s t = match (s,t) with | (Finite s, Cofinite t) -> Finite (SList.cap s t) | (Finite s, Finite t) -> Finite (SList.diff s t) | (Cofinite s, Cofinite t) -> Finite (SList.diff t s) | (Cofinite s, Finite t) -> Cofinite (SList.cup s t) let contains x = function | Finite s -> SList.mem s x | Cofinite s -> not (SList.mem s x) let is_empty = function | Finite [] -> true | _ -> false let is_atom = function | Finite [a] -> Some a | _ -> None let sample = function | Finite (x :: _) -> x | Cofinite l -> AtomPool.dummy_min | Finite [] -> raise Not_found let print_v ppf a = if a = AtomPool.dummy_min then Format.fprintf ppf "(almost any atom)" else Format.fprintf ppf "`%s" (value a) let print = function | Finite l -> List.map (fun x ppf -> print_v ppf x) l | Cofinite [] -> [ fun ppf -> Format.fprintf ppf "Atom" ] | Cofinite [h] -> [ fun ppf -> Format.fprintf ppf "@[Atom - %a@]" print_v h ] | Cofinite (h::t) -> [ fun ppf -> Format.fprintf ppf "@[Atom - ("; print_v ppf h; List.iter (fun x -> Format.fprintf ppf " |@ %a" print_v x) t; Format.fprintf ppf ")@]" ] (* TODO: clean what follow to re-use SList operations *) let rec hash_seq accu = function | t::rem -> hash_seq (accu * 17 + t) rem | [] -> accu let hash accu = function | Finite l -> hash_seq (accu + 1) l | Cofinite l -> hash_seq (accu + 3) l let rec equal_rec l1 l2 = (l1 == l2) || match (l1,l2) with | (x1::l1,x2::l2) -> (x1 == x2) && (equal_rec l1 l2) | _ -> false let equal t1 t2 = match (t1,t2) with | (Finite l1, Finite l2) -> equal_rec l1 l2 | (Cofinite l1, Cofinite l2) -> equal_rec l1 l2 | _ -> false