type t = { mutable rank: int; mutable hash: int } let hash c = c.rank + 16 * c.hash let equal c1 c2 = c1 == c2 || (c1.rank == c2.rank && c1.hash == c2.hash) let compare c1 c2 = if (c1 == c2) then 0 else let c = c1.rank - c2.rank in if c !=0 then c else if c1.hash < c2.hash then (-1) else if c1.hash > c2.hash then (1) else 0 let pervasives = { rank = 0; hash = 0 } let current_ref = ref pervasives let current () = !current_ref let enter () = assert(!current_ref == pervasives); current_ref := { rank = max_int; hash = 0 } let leave () = assert(!current_ref != pervasives); current_ref := pervasives; () let set_hash t i1 i2 = t.rank <- i1; t.hash <- i2 let get_hash t = (t.rank,t.hash) let wrap f x = enter (); let r = try f x with exn -> leave (); raise exn in leave (); r let ctbl = Hashtbl.create 64 let register c s = if Hashtbl.mem ctbl c && Hashtbl.find ctbl c <> s then failwith (Printf.sprintf "Collision on descriptors for CDuce units: %s and %s" (Hashtbl.find ctbl c) s ); (* Printf.eprintf "Register %s\n" s; *) Hashtbl.add ctbl c s