(**************************************************************************) (* *) (* Copyright (C) 2010- *) (* François Bobot *) (* Jean-Christophe Filliâtre *) (* Claude Marché *) (* Andrei Paskevich *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software is distributed in the hope that it will be useful, *) (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) (* *) (**************************************************************************) (*s Hash tables for hash-consing. (Some code is borrowed from the ocaml standard library, which is copyright 1996 INRIA.) *) module type HashedType = sig type t val equal : t -> t -> bool val hash : t -> int val tag : int -> t -> t end module type S = sig type t val hashcons : t -> t val iter : (t -> unit) -> unit val stats : unit -> int * int * int * int * int * int end module Make(H : HashedType) : (S with type t = H.t) = struct type t = H.t module WH = Weak.Make (H) let next_tag = ref 0 let htable = WH.create 5003 let hashcons d = let d = H.tag !next_tag d in let o = WH.merge htable d in if o == d then incr next_tag; o let iter f = WH.iter f htable let stats () = WH.stats htable end let combine acc n = n * 65599 + acc let combine2 acc n1 n2 = combine acc (combine n1 n2) let combine3 acc n1 n2 n3 = combine acc (combine n1 (combine n2 n3)) let combine_list f = List.fold_left (fun acc x -> combine acc (f x)) let combine_option h = function None -> 0 | Some s -> (h s) + 1 let combine_pair h1 h2 (a1,a2) = combine (h1 a1) (h2 a2) type 'a hash_consed = { tag : int; node : 'a } module type HashedType_consed = sig type t val equal : t -> t -> bool val hash : t -> int end module type S_consed = sig type key val hashcons : key -> key hash_consed val iter : (key hash_consed -> unit) -> unit val stats : unit -> int * int * int * int * int * int end module Make_consed(H : HashedType_consed) : (S_consed with type key = H.t) = struct module M = Make(struct type t = H.t hash_consed let hash x = H.hash x.node let equal x y = H.equal x.node y.node let tag i x = {x with tag = i} end) include M type key = H.t let hashcons x = M.hashcons {tag = -1; node = x} end