diff --git a/src/core/decl.ml b/src/core/decl.ml index 91f296a1e2d413594834bb40441d6866110086a5..84a0e80a2031dceee24c71a0829de0e054a1f916 100644 --- a/src/core/decl.ml +++ b/src/core/decl.ml @@ -77,7 +77,7 @@ type prsymbol = { pr_name : ident; } -module Prop = StructMake (struct +module Prop = WeakStructMake (struct type t = prsymbol let tag pr = pr.pr_name.id_tag end) @@ -85,14 +85,12 @@ end) module Spr = Prop.S module Mpr = Prop.M module Hpr = Prop.H - -module Wpr = Hashweak.Make (struct - type t = prsymbol - let key pr = pr.pr_name.id_weak -end) +module Wpr = Prop.W let pr_equal = (==) +let pr_hash pr = id_hash pr.pr_name + let create_prsymbol n = { pr_name = id_register n } type ind_decl = lsymbol * (prsymbol * fmla) list @@ -113,8 +111,7 @@ type decl = { d_node : decl_node; d_syms : Sid.t; (* idents used in declaration *) d_news : Sid.t; (* idents introduced in declaration *) - d_weak : Hashweak.key; (* weak hashtable key *) - d_tag : int; + d_tag : Hashweak.tag; (* unique magical tag *) } and decl_node = @@ -154,17 +151,15 @@ module Hsdecl = Hashcons.Make (struct | _,_ -> false let hs_td (ts,td) = match td with - | Tabstract -> ts.ts_name.id_tag - | Talgebraic l -> - let tag fs = fs.ls_name.id_tag in - 1 + Hashcons.combine_list tag ts.ts_name.id_tag l + | Tabstract -> ts_hash ts + | Talgebraic l -> 1 + Hashcons.combine_list ls_hash (ts_hash ts) l - let hs_ld (ls,ld) = Hashcons.combine ls.ls_name.id_tag - (Hashcons.combine_option (fun (_,f) -> f.f_tag) ld) + let hs_ld (ls,ld) = Hashcons.combine (ls_hash ls) + (Hashcons.combine_option (fun (_,f) -> f_hash f) ld) - let hs_prop (pr,f) = Hashcons.combine pr.pr_name.id_tag f.f_tag + let hs_prop (pr,f) = Hashcons.combine (pr_hash pr) (f_hash f) - let hs_ind (ps,al) = Hashcons.combine_list hs_prop ps.ls_name.id_tag al + let hs_ind (ps,al) = Hashcons.combine_list hs_prop (ls_hash ps) al let hs_kind = function | Plemma -> 11 | Paxiom -> 13 | Pgoal -> 17 | Pskip -> 19 @@ -175,28 +170,30 @@ module Hsdecl = Hashcons.Make (struct | Dind l -> Hashcons.combine_list hs_ind 7 l | Dprop (k,pr,f) -> Hashcons.combine (hs_kind k) (hs_prop (pr,f)) - let tag n d = { d with d_tag = n } + let tag n d = { d with d_tag = Hashweak.create_tag n } end) -module Decl = StructMake (struct +module Decl = WeakStructMake (struct type t = decl let tag d = d.d_tag end) module Sdecl = Decl.S module Mdecl = Decl.M +module Wdecl = Decl.W let d_equal = (==) +let d_hash d = Hashweak.tag_hash d.d_tag + (** Declaration constructors *) let mk_decl node syms news = Hsdecl.hashcons { d_node = node; d_syms = syms; d_news = news; - d_weak = Hashweak.create_key (); - d_tag = -1; + d_tag = Hashweak.dummy_tag; } exception IllegalTypeAlias of tysymbol diff --git a/src/core/decl.mli b/src/core/decl.mli index 7a6271b9d2a81d4fcf1cdc0256cf812fa8147499..2113c2023fed0708de3c11540a7d4a34ff1a15a1 100644 --- a/src/core/decl.mli +++ b/src/core/decl.mli @@ -62,6 +62,8 @@ val create_prsymbol : preid -> prsymbol val pr_equal : prsymbol -> prsymbol -> bool +val pr_hash : prsymbol -> int + type ind_decl = lsymbol * (prsymbol * fmla) list (* Proposition declaration *) @@ -80,8 +82,7 @@ type decl = private { d_node : decl_node; d_syms : Sid.t; (* idents used in declaration *) d_news : Sid.t; (* idents introduced in declaration *) - d_weak : Hashweak.key; (* weak hashtable key *) - d_tag : int; + d_tag : Hashweak.tag; (* unique magical tag *) } and decl_node = @@ -92,8 +93,10 @@ and decl_node = module Sdecl : Set.S with type elt = decl module Mdecl : Map.S with type key = decl +module Wdecl : Hashweak.S with type key = decl val d_equal : decl -> decl -> bool +val d_hash : decl -> int (** {2 Declaration constructors} *) diff --git a/src/core/env.ml b/src/core/env.ml index 36d3863e67d7de126615d0383c0408f2aad6069f..32c57222bbb0912d614dd88d4546eab90fd63b29 100644 --- a/src/core/env.ml +++ b/src/core/env.ml @@ -25,16 +25,16 @@ open Theory type env = { env_retrieve : retrieve_theory; env_memo : (string list, theory Mnm.t) Hashtbl.t; - env_weak : Hashweak.key; + env_tag : Hashweak.tag; } and retrieve_theory = env -> string list -> theory Mnm.t -let create_env retrieve = +let create_env = let c = ref (-1) in fun retrieve -> let env = { env_retrieve = retrieve; env_memo = Hashtbl.create 17; - env_weak = Hashweak.create_key (); } + env_tag = (incr c; Hashweak.create_tag !c) } in let add th m = Mnm.add th.th_name.id_string th m in let m = Mnm.empty in @@ -62,7 +62,7 @@ let find_theory env sl s = with Not_found -> raise (TheoryNotFound (sl, s)) -let env_weak env = env.env_weak +let env_tag env = env.env_tag (** Parsers *) diff --git a/src/core/env.mli b/src/core/env.mli index 7973ebb418a0ab82c08478d2e5daebbd27ee67cf..f5e32cc9d8a50655f8fcf3abde6ab0fc9a62b8e9 100644 --- a/src/core/env.mli +++ b/src/core/env.mli @@ -23,7 +23,7 @@ open Theory type env -val env_weak : env -> Hashweak.key +val env_tag : env -> Hashweak.tag type retrieve_theory = env -> string list -> theory Mnm.t diff --git a/src/core/ident.ml b/src/core/ident.ml index 0f08d03a6a191566929607581107e8cd599a86db..7b53f2227ead296c5d575efee40aa40c1433d864 100644 --- a/src/core/ident.ml +++ b/src/core/ident.ml @@ -24,8 +24,7 @@ open Util type ident = { id_string : string; (* non-unique name *) id_origin : origin; (* origin of the ident *) - id_weak : Hashweak.key; (* weak hashtable key *) - id_tag : int; (* unique numeric tag *) + id_tag : Hashweak.tag; (* unique magical tag *) } and origin = @@ -33,7 +32,7 @@ and origin = | Derived of ident | Fresh -module Id = StructMake (struct +module Id = WeakStructMake (struct type t = ident let tag id = id.id_tag end) @@ -46,24 +45,24 @@ type preid = ident let id_equal = (==) -(* constructors *) +let id_hash id = Hashweak.tag_hash id.id_tag -let gentag = let r = ref 0 in fun () -> incr r; !r +(* constructors *) -let id_register id = { id with id_tag = gentag () } +let id_register = let r = ref 0 in fun id -> + { id with id_tag = (incr r; Hashweak.create_tag !r) } let create_ident name origin = { id_string = name; id_origin = origin; - id_weak = Hashweak.create_key (); - id_tag = -1 + id_tag = Hashweak.dummy_tag; } let id_fresh nm = create_ident nm Fresh let id_user nm loc = create_ident nm (User loc) let id_derive nm id = create_ident nm (Derived id) let id_clone id = create_ident id.id_string (Derived id) -let id_dup id = { id with id_tag = -1 } +let id_dup id = { id with id_tag = Hashweak.dummy_tag } let rec id_derived_from i1 i2 = id_equal i1 i2 || (match i1.id_origin with @@ -80,7 +79,7 @@ let rec id_from_user i = type ident_printer = { indices : (string, int) Hashtbl.t; - values : (int, string) Hashtbl.t; + values : string Hid.t; sanitizer : string -> string; blacklist : string list; } @@ -107,31 +106,31 @@ let create_ident_printer ?(sanitizer = same) sl = let indices = Hashtbl.create 1997 in List.iter (reserve indices) sl; { indices = indices; - values = Hashtbl.create 1997; + values = Hid.create 1997; sanitizer = sanitizer; blacklist = sl } let id_unique printer ?(sanitizer = same) id = try - Hashtbl.find printer.values id.id_tag + Hid.find printer.values id with Not_found -> let name = sanitizer (printer.sanitizer id.id_string) in let name = find_unique printer.indices name in - Hashtbl.replace printer.values id.id_tag name; + Hid.replace printer.values id name; name let string_unique printer s = find_unique printer.indices s let forget_id printer id = try - let name = Hashtbl.find printer.values id.id_tag in + let name = Hid.find printer.values id in Hashtbl.remove printer.indices name; - Hashtbl.remove printer.values id.id_tag + Hid.remove printer.values id with Not_found -> () let forget_all printer = + Hid.clear printer.values; Hashtbl.clear printer.indices; - Hashtbl.clear printer.values; List.iter (reserve printer.indices) printer.blacklist (** Sanitizers *) diff --git a/src/core/ident.mli b/src/core/ident.mli index daf226b461ee6c3c85400ba574421a4da78f9129..16049a845986ee2fdf293411d4b012714a48ef57 100644 --- a/src/core/ident.mli +++ b/src/core/ident.mli @@ -22,8 +22,7 @@ type ident = private { id_string : string; (* non-unique name *) id_origin : origin; (* origin of the ident *) - id_weak : Hashweak.key; (* weak hashtable key *) - id_tag : int; (* unique numeric tag *) + id_tag : Hashweak.tag; (* unique magical tag *) } and origin = @@ -37,6 +36,8 @@ module Hid : Hashtbl.S with type key = ident val id_equal : ident -> ident -> bool +val id_hash : ident -> int + (* a user-created type of unregistered identifiers *) type preid diff --git a/src/core/task.ml b/src/core/task.ml index 0d22713a85d72213850219b9eadd53d6c761bf40..a42c48339334c6f58afc4db045119bf51f40ae28 100644 --- a/src/core/task.ml +++ b/src/core/task.ml @@ -27,23 +27,21 @@ open Theory (** Clone and meta history *) type tdecl_set = { - tds_set : Stdecl.t; - tds_weak : Hashweak.key; - tds_tag : int; + tds_set : Stdecl.t; + tds_tag : Hashweak.tag; } module Hstds = Hashcons.Make (struct type t = tdecl_set let equal s1 s2 = Stdecl.equal s1.tds_set s2.tds_set - let hs_td td acc = Hashcons.combine acc td.td_tag + let hs_td td acc = Hashcons.combine acc (td_hash td) let hash s = Stdecl.fold hs_td s.tds_set 0 - let tag n s = { s with tds_tag = n } + let tag n s = { s with tds_tag = Hashweak.create_tag n } end) let mk_tds s = Hstds.hashcons { - tds_set = s; - tds_weak = Hashweak.create_key (); - tds_tag = -1 + tds_set = s; + tds_tag = Hashweak.dummy_tag; } let empty_tds = mk_tds Stdecl.empty @@ -51,6 +49,7 @@ let tds_add td s = mk_tds (Stdecl.add td s.tds_set) let tds_singleton td = mk_tds (Stdecl.singleton td) let tds_equal = (==) +let tds_hash tds = Hashweak.tag_hash tds.tds_tag type clone_map = tdecl_set Mid.t type meta_map = tdecl_set Mmeta.t @@ -76,29 +75,29 @@ and task_hd = { task_known : known_map; (* known identifiers *) task_clone : clone_map; (* cloning history *) task_meta : meta_map; (* meta properties *) - task_weak : Hashweak.key; (* weak hashtable key *) - task_tag : int; (* unique task tag *) + task_tag : Hashweak.tag; (* unique magical tag *) } let task_hd_equal = (==) +let task_hd_hash t = Hashweak.tag_hash t.task_tag + let task_equal t1 t2 = match t1, t2 with | Some t1, Some t2 -> task_hd_equal t1 t2 | None, None -> true | _ -> false +let task_hash t = option_apply 0 (fun t -> task_hd_hash t + 1) t + module Hstask = Hashcons.Make (struct type t = task_hd let equal t1 t2 = td_equal t1.task_decl t2.task_decl && task_equal t1.task_prev t2.task_prev - let hash task = - let decl = task.task_decl.td_tag in - let prev = option_apply 0 (fun t -> t.task_tag + 1) task.task_prev in - Hashcons.combine decl prev + let hash t = Hashcons.combine (td_hash t.task_decl) (task_hash t.task_prev) - let tag i task = { task with task_tag = i } + let tag i task = { task with task_tag = Hashweak.create_tag i } end) let mk_task decl prev known clone meta = Some (Hstask.hashcons { @@ -107,8 +106,7 @@ let mk_task decl prev known clone meta = Some (Hstask.hashcons { task_known = known; task_clone = clone; task_meta = meta; - task_weak = Hashweak.create_key (); - task_tag = -1; + task_tag = Hashweak.dummy_tag; }) let task_known = option_apply Mid.empty (fun t -> t.task_known) diff --git a/src/core/task.mli b/src/core/task.mli index fab3671a52fae55c49031ff39968382af4c72e3d..319e5a2f851283bd8ecde013578e78bc1683baec 100644 --- a/src/core/task.mli +++ b/src/core/task.mli @@ -27,12 +27,12 @@ open Theory (** Clone and meta history *) type tdecl_set = private { - tds_set : Stdecl.t; - tds_weak : Hashweak.key; - tds_tag : int; + tds_set : Stdecl.t; + tds_tag : Hashweak.tag; } val tds_equal : tdecl_set -> tdecl_set -> bool +val tds_hash : tdecl_set -> int type clone_map = tdecl_set Mid.t type meta_map = tdecl_set Mmeta.t @@ -47,13 +47,15 @@ and task_hd = private { task_known : known_map; (* known identifiers *) task_clone : clone_map; (* cloning history *) task_meta : meta_map; (* meta properties *) - task_weak : Hashweak.key; (* weak hashtable key *) - task_tag : int; (* unique task tag *) + task_tag : Hashweak.tag; (* unique magical tag *) } val task_equal : task -> task -> bool val task_hd_equal : task_hd -> task_hd -> bool +val task_hash : task -> int +val task_hd_hash : task_hd -> int + val task_known : task -> known_map val task_clone : task -> clone_map val task_meta : task -> meta_map diff --git a/src/core/term.ml b/src/core/term.ml index 0e50708353dac977a3aed3901d9315de022fa1d4..6a2d710169840c8b43ce18cff86284fd332827d7 100644 --- a/src/core/term.ml +++ b/src/core/term.ml @@ -28,7 +28,7 @@ type vsymbol = { vs_ty : ty; } -module Vsym = StructMake (struct +module Vsym = WeakStructMake (struct type t = vsymbol let tag vs = vs.vs_name.id_tag end) @@ -39,6 +39,8 @@ module Hvs = Vsym.H let vs_equal = (==) +let vs_hash vs = id_hash vs.vs_name + let create_vsymbol name ty = { vs_name = id_register name; vs_ty = ty; @@ -54,7 +56,7 @@ type lsymbol = { ls_value : ty option; } -module Lsym = StructMake (struct +module Lsym = WeakStructMake (struct type t = lsymbol let tag ls = ls.ls_name.id_tag end) @@ -62,14 +64,12 @@ end) module Sls = Lsym.S module Mls = Lsym.M module Hls = Lsym.H - -module Wls = Hashweak.Make (struct - type t = lsymbol - let key ls = ls.ls_name.id_weak -end) +module Wls = Lsym.W let ls_equal = (==) +let ls_hash ls = id_hash ls.ls_name + let create_lsymbol name args value = { ls_name = id_register name; ls_args = args; @@ -104,6 +104,8 @@ and pattern_node = let pat_equal = (==) +let pat_hash p = p.pat_tag + module Hspat = Hashcons.Make (struct type t = pattern @@ -121,16 +123,14 @@ module Hspat = Hashcons.Make (struct let equal p1 p2 = equal_node p1.pat_node p2.pat_node && ty_equal p1.pat_ty p2.pat_ty - let hash_pattern p = p.pat_tag - let hash_node = function | Pwild -> 0 - | Pvar v -> v.vs_name.id_tag - | Papp (s, pl) -> Hashcons.combine_list hash_pattern s.ls_name.id_tag pl - | Por (p, q) -> Hashcons.combine (hash_pattern p) (hash_pattern q) - | Pas (p, v) -> Hashcons.combine (hash_pattern p) v.vs_name.id_tag + | Pvar v -> vs_hash v + | Papp (s, pl) -> Hashcons.combine_list pat_hash (ls_hash s) pl + | Por (p, q) -> Hashcons.combine (pat_hash p) (pat_hash q) + | Pas (p, v) -> Hashcons.combine (pat_hash p) (vs_hash v) - let hash p = Hashcons.combine (hash_node p.pat_node) p.pat_ty.ty_tag + let hash p = Hashcons.combine (hash_node p.pat_node) (ty_hash p.pat_ty) let tag n p = { p with pat_tag = n } end) @@ -333,6 +333,9 @@ and expr = let t_equal = (==) let f_equal = (==) +let t_hash t = t.t_tag +let f_hash f = f.f_tag + (* expr and trigger equality *) let e_equal e1 e2 = match e1, e2 with @@ -364,7 +367,7 @@ let bnd_equal b1 b2 = b1.bv_bound = b2.bv_bound && Mint.equal t_equal b1.bv_defer b2.bv_defer let bnd_hash bv = - Mint.fold (fun i t a -> Hashcons.combine2 i t.t_tag a) bv.bv_defer + Mint.fold (fun i t a -> Hashcons.combine2 i (t_hash t) a) bv.bv_defer let bnd_map fn bv = { bv with bv_defer = Mint.map fn bv.bv_defer } let bnd_fold fn acc bv = Mint.fold (fun _ t a -> fn a t) bv.bv_defer acc @@ -412,29 +415,27 @@ module Hsterm = Hashcons.Make (struct list_all2 (=) t1.t_label t2.t_label let t_hash_branch (p,b,t) = - Hashcons.combine p.pat_tag (bnd_hash b t.t_tag) + Hashcons.combine (pat_hash p) (bnd_hash b (t_hash t)) let t_hash_bound (v,b,t) = - Hashcons.combine v.vs_name.id_tag (bnd_hash b t.t_tag) + Hashcons.combine (vs_hash v) (bnd_hash b (t_hash t)) let f_hash_bound (v,b,f) = - Hashcons.combine v.vs_name.id_tag (bnd_hash b f.f_tag) - - let t_hash t = t.t_tag + Hashcons.combine (vs_hash v) (bnd_hash b (f_hash f)) let t_hash_node = function | Tbvar n -> n - | Tvar v -> v.vs_name.id_tag + | Tvar v -> vs_hash v | Tconst c -> Hashtbl.hash c - | Tapp (f,tl) -> Hashcons.combine_list t_hash (f.ls_name.id_tag) tl - | Tif (f,t,e) -> Hashcons.combine2 f.f_tag t.t_tag e.t_tag - | Tlet (t,bt) -> Hashcons.combine t.t_tag (t_hash_bound bt) - | Tcase (t,bl) -> Hashcons.combine_list t_hash_branch t.t_tag bl + | Tapp (f,tl) -> Hashcons.combine_list t_hash (ls_hash f) tl + | Tif (f,t,e) -> Hashcons.combine2 (f_hash f) (t_hash t) (t_hash e) + | Tlet (t,bt) -> Hashcons.combine (t_hash t) (t_hash_bound bt) + | Tcase (t,bl) -> Hashcons.combine_list t_hash_branch (t_hash t) bl | Teps f -> f_hash_bound f let hash t = Hashcons.combine (t_hash_node t.t_node) - (Hashcons.combine_list Hashtbl.hash t.t_ty.ty_tag t.t_label) + (Hashcons.combine_list Hashtbl.hash (ty_hash t.t_ty) t.t_label) let tag n t = { t with t_tag = n } @@ -484,34 +485,30 @@ module Hsfmla = Hashcons.Make (struct f_equal_node f1.f_node f2.f_node && list_all2 (=) f1.f_label f2.f_label - let v_hash v = v.vs_name.id_tag - - let t_hash t = t.t_tag - let f_hash_branch (p,b,f) = - Hashcons.combine p.pat_tag (bnd_hash b f.f_tag) + Hashcons.combine (pat_hash p) (bnd_hash b (f_hash f)) let f_hash_bound (v,b,f) = - Hashcons.combine v.vs_name.id_tag (bnd_hash b f.f_tag) + Hashcons.combine (vs_hash v) (bnd_hash b (f_hash f)) - let tr_hash = function Term t -> t.t_tag | Fmla f -> f.f_tag + let e_hash = function Term t -> t_hash t | Fmla f -> f_hash f let f_hash_quant (vl,b,tl,f) = - let h = bnd_hash b f.f_tag in - let h = Hashcons.combine_list v_hash h vl in - List.fold_left (Hashcons.combine_list tr_hash) h tl + let h = bnd_hash b (f_hash f) in + let h = Hashcons.combine_list vs_hash h vl in + List.fold_left (Hashcons.combine_list e_hash) h tl let f_hash_node = function - | Fapp (p,tl) -> Hashcons.combine_list t_hash p.ls_name.id_tag tl + | Fapp (p,tl) -> Hashcons.combine_list t_hash (ls_hash p) tl | Fquant (q,bf) -> Hashcons.combine (Hashtbl.hash q) (f_hash_quant bf) | Fbinop (op,f1,f2) -> - Hashcons.combine2 (Hashtbl.hash op) f1.f_tag f2.f_tag - | Fnot f -> Hashcons.combine 1 f.f_tag + Hashcons.combine2 (Hashtbl.hash op) (f_hash f1) (f_hash f2) + | Fnot f -> Hashcons.combine 1 (f_hash f) | Ftrue -> 0 | Ffalse -> 1 - | Fif (f1,f2,f3) -> Hashcons.combine2 f1.f_tag f2.f_tag f3.f_tag - | Flet (t,bf) -> Hashcons.combine t.t_tag (f_hash_bound bf) - | Fcase (t,bl) -> Hashcons.combine_list f_hash_branch t.t_tag bl + | Fif (f1,f2,f3) -> Hashcons.combine2 (f_hash f1) (f_hash f2) (f_hash f3) + | Flet (t,bf) -> Hashcons.combine (t_hash t) (f_hash_bound bf) + | Fcase (t,bl) -> Hashcons.combine_list f_hash_branch (t_hash t) bl let hash f = Hashcons.combine_list Hashtbl.hash (f_hash_node f.f_node) f.f_label diff --git a/src/core/term.mli b/src/core/term.mli index 1bd4a08ad60ca100ea7b83fe112bb2438669c36c..2fdc9be08bdfb07052103622df5521ab3b8da7be 100644 --- a/src/core/term.mli +++ b/src/core/term.mli @@ -34,6 +34,7 @@ module Mvs : Map.S with type key = vsymbol module Hvs : Hashtbl.S with type key = vsymbol val vs_equal : vsymbol -> vsymbol -> bool +val vs_hash : vsymbol -> int val create_vsymbol : preid -> ty -> vsymbol @@ -51,6 +52,7 @@ module Hls : Hashtbl.S with type key = lsymbol module Wls : Hashweak.S with type key = lsymbol val ls_equal : lsymbol -> lsymbol -> bool +val ls_hash : lsymbol -> int val create_lsymbol : preid -> ty list -> ty option -> lsymbol val create_fsymbol : preid -> ty list -> ty -> lsymbol @@ -84,6 +86,7 @@ and pattern_node = private | Pas of pattern * vsymbol val pat_equal : pattern -> pattern -> bool +val pat_hash : pattern -> int (** smart constructors for patterns *) @@ -172,10 +175,13 @@ and expr = and trigger = expr list -module Mterm : Map.S with type key = term module Sterm : Set.S with type elt = term -module Mfmla : Map.S with type key = fmla +module Mterm : Map.S with type key = term +module Hterm : Hashtbl.S with type key = term + module Sfmla : Set.S with type elt = fmla +module Mfmla : Map.S with type key = fmla +module Hfmla : Hashtbl.S with type key = fmla val t_equal : term -> term -> bool val f_equal : fmla -> fmla -> bool @@ -183,6 +189,9 @@ val e_equal : expr -> expr -> bool val tr_equal : trigger list -> trigger list -> bool +val t_hash : term -> int +val f_hash : fmla -> int + (** close bindings *) val t_close_bound : vsymbol -> term -> term_bound diff --git a/src/core/theory.ml b/src/core/theory.ml index 63ae4b84df6e265a95771f7b8dccff94e66e8201..73622fbd8aaaa05970b17fd7e65762d6f8440dd8 100644 --- a/src/core/theory.ml +++ b/src/core/theory.ml @@ -109,7 +109,9 @@ module Smeta = SMmeta.S module Mmeta = SMmeta.M module Hmeta = SMmeta.H -let meta_equal m1 m2 = m1.meta_tag = m2.meta_tag +let meta_equal = (==) + +let meta_hash m = m.meta_tag exception KnownMeta of meta exception UnknownMeta of string @@ -193,23 +195,23 @@ module Hstdecl = Hashcons.Make (struct t1 = t2 && list_all2 eq_marg al1 al2 | _,_ -> false - let hs_cl_ts _ ts acc = Hashcons.combine acc ts.ts_name.id_tag - let hs_cl_ls _ ls acc = Hashcons.combine acc ls.ls_name.id_tag - let hs_cl_pr _ pr acc = Hashcons.combine acc pr.pr_name.id_tag + let hs_cl_ts _ ts acc = Hashcons.combine acc (ts_hash ts) + let hs_cl_ls _ ls acc = Hashcons.combine acc (ls_hash ls) + let hs_cl_pr _ pr acc = Hashcons.combine acc (pr_hash pr) let hs_ta = function - | MAts ts -> ts.ts_name.id_tag - | MAls ls -> ls.ls_name.id_tag - | MApr pr -> pr.pr_name.id_tag + | MAts ts -> ts_hash ts + | MAls ls -> ls_hash ls + | MApr pr -> pr_hash pr | MAstr s -> Hashtbl.hash s | MAint i -> Hashtbl.hash i let hash td = match td.td_node with - | Decl d -> d.d_tag - | Use th -> th.th_name.id_tag + | Decl d -> d_hash d + | Use th -> id_hash th.th_name | Clone (th,tm,lm,pm) -> Mts.fold hs_cl_ts tm (Mls.fold hs_cl_ls lm - (Mpr.fold hs_cl_pr pm th.th_name.id_tag)) + (Mpr.fold hs_cl_pr pm (id_hash th.th_name))) | Meta (t,al) -> Hashcons.combine_list hs_ta (Hashtbl.hash t) al let tag n td = { td with td_tag = n } @@ -228,6 +230,7 @@ module Mtdecl = Tdecl.M module Htdecl = Tdecl.H let td_equal = (==) +let td_hash td = td.td_tag (** Constructors and utilities *) diff --git a/src/core/theory.mli b/src/core/theory.mli index 109bcfff0bc3e99ee3a5c2f8265947313d7c52f7..c4892467998bebf8dab1db44dd1c1ee220bd28d3 100644 --- a/src/core/theory.mli +++ b/src/core/theory.mli @@ -66,6 +66,7 @@ module Mmeta : Map.S with type key = meta module Hmeta : Hashtbl.S with type key = meta val meta_equal : meta -> meta -> bool +val meta_hash : meta -> int val register_meta : string -> meta_arg_type list -> meta val register_meta_excl : string -> meta_arg_type list -> meta @@ -100,6 +101,7 @@ module Mtdecl : Map.S with type key = tdecl module Htdecl : Hashtbl.S with type key = tdecl val td_equal : tdecl -> tdecl -> bool +val td_hash : tdecl -> int (** Constructors and utilities *) @@ -132,7 +134,6 @@ val add_ind_decls : theory_uc -> ind_decl list -> theory_uc (** Use *) val create_use : theory -> tdecl - val use_export : theory_uc -> theory -> theory_uc (** Clone *) diff --git a/src/core/trans.ml b/src/core/trans.ml index 27881566c7e2d920e519d4fbf584a87e757ce74f..f7a95074eb6ec950307c649271e94438b72b50d1 100644 --- a/src/core/trans.ml +++ b/src/core/trans.ml @@ -44,13 +44,13 @@ let apply f x = f x module Wtask = Hashweak.Make (struct type t = task_hd - let key t = t.task_weak + let tag t = t.task_tag end) -let store fn = Wtask.memoize_option fn +let store fn = Wtask.memoize_option 63 fn let fold fn v = - let h = Wtask.create () in + let h = Wtask.create 63 in let rewind acc task = (* Format.printf "%c%d." (match task.task_decl.td_node with @@ -82,13 +82,8 @@ let fold_map_l fn v t = conv_res (List.rev_map snd) (fold_l fn (v, t)) let map fn = fold (fun t1 t2 -> fn t1 t2) let map_l fn = fold_l (fun t1 t2 -> fn t1 t2) -module Wdecl = Hashweak.Make (struct - type t = decl - let key d = d.d_weak -end) - let gen_decl add fn = - let fn = Wdecl.memoize fn in + let fn = Wdecl.memoize 63 fn in let fn task acc = match task.task_decl.td_node with | Decl d -> List.fold_left add acc (fn d) | _ -> add_tdecl acc task.task_decl @@ -96,7 +91,7 @@ let gen_decl add fn = map fn let gen_decl_l add fn = - let fn = Wdecl.memoize fn in + let fn = Wdecl.memoize 63 fn in let fn task acc = match task.task_decl.td_node with | Decl d -> List.rev_map (List.fold_left add acc) (fn d) | _ -> [add_tdecl acc task.task_decl] @@ -113,7 +108,7 @@ let apply_to_goal fn d = match d.d_node with | _ -> assert false let gen_goal add fn = - let fn = Wdecl.memoize (apply_to_goal fn) in + let fn = Wdecl.memoize 5 (apply_to_goal fn) in let rec pass task = match task with | Some { task_decl = { td_node = Decl d }; task_prev = prev } -> List.fold_left add prev (fn d) @@ -124,7 +119,7 @@ let gen_goal add fn = pass let gen_goal_l add fn = - let fn = Wdecl.memoize (apply_to_goal fn) in + let fn = Wdecl.memoize 5 (apply_to_goal fn) in let rec pass task = match task with | Some { task_decl = { td_node = Decl d }; task_prev = prev } -> List.rev_map (List.fold_left add prev) (fn d) @@ -145,15 +140,15 @@ let rewrite fnT fnF = decl (fun d -> [decl_map fnT fnF d]) module Wtds = Hashweak.Make (struct type t = tdecl_set - let key s = s.tds_weak + let tag s = s.tds_tag end) let on_theory th fn = - let fn = Wtds.memoize fn in + let fn = Wtds.memoize 17 fn in fun task -> fn (find_clone task th) task let on_meta t fn = - let fn = Wtds.memoize fn in + let fn = Wtds.memoize 17 fn in fun task -> fn (find_meta task t) task let on_theories tl fn = @@ -179,7 +174,7 @@ open Env module Wenv = Hashweak.Make (struct type t = env - let key = env_weak + let tag = env_tag end) exception UnknownTrans of string @@ -198,11 +193,11 @@ let register_transform_l s p = let register_env_transform s p = if Hashtbl.mem transforms s then raise (KnownTrans s); - Hashtbl.replace transforms s (Wenv.memoize p) + Hashtbl.replace transforms s (Wenv.memoize 3 p) let register_env_transform_l s p = if Hashtbl.mem transforms_l s then raise (KnownTrans s); - Hashtbl.replace transforms_l s (Wenv.memoize p) + Hashtbl.replace transforms_l s (Wenv.memoize 3 p) let lookup_transform s = try Hashtbl.find transforms s with Not_found -> raise (UnknownTrans s) diff --git a/src/core/ty.ml b/src/core/ty.ml index 7f6aa1d85a8d9e2599844ad92c2610641438b846..bc52d3cc6894e4482976d0edffb80379a3522e4d 100644 --- a/src/core/ty.ml +++ b/src/core/ty.ml @@ -26,7 +26,7 @@ type tvsymbol = { tv_name : ident; } -module Tvar = StructMake (struct +module Tvar = WeakStructMake (struct type t = tvsymbol let tag tv = tv.tv_name.id_tag end) @@ -37,6 +37,8 @@ module Htv = Tvar.H let tv_equal = (==) +let tv_hash tv = id_hash tv.tv_name + let create_tvsymbol n = { tv_name = id_register n } (* type symbols and types *) @@ -49,15 +51,14 @@ type tysymbol = { and ty = { ty_node : ty_node; - ty_weak : Hashweak.key; - ty_tag : int; + ty_tag : Hashweak.tag; } and ty_node = | Tyvar of tvsymbol | Tyapp of tysymbol * ty list -module Tsym = StructMake (struct +module Tsym = WeakStructMake (struct type t = tysymbol let tag ts = ts.ts_name.id_tag end) @@ -65,15 +66,14 @@ end) module Sts = Tsym.S module Mts = Tsym.M module Hts = Tsym.H - -module Wts = Hashweak.Make (struct - type t = tysymbol - let key ts = ts.ts_name.id_weak -end) +module Wts = Tsym.W let ts_equal = (==) let ty_equal = (==) +let ts_hash ts = id_hash ts.ts_name +let ty_hash ty = Hashweak.tag_hash ty.ty_tag + let mk_ts name args def = { ts_name = name; ts_args = args; @@ -91,35 +91,26 @@ module Hsty = Hashcons.Make (struct ts_equal s1 s2 && List.for_all2 ty_equal l1 l2 | _ -> false - let hash_ty ty = ty.ty_tag - let hash ty = match ty.ty_node with - | Tyvar v -> v.tv_name.id_tag - | Tyapp (s,tl) -> Hashcons.combine_list hash_ty s.ts_name.id_tag tl + | Tyvar v -> tv_hash v + | Tyapp (s,tl) -> Hashcons.combine_list ty_hash (ts_hash s) tl - let tag n ty = { ty with ty_tag = n } + let tag n ty = { ty with ty_tag = Hashweak.create_tag n } end) -module Tty = struct +module Ty = WeakStructMake (struct type t = ty let tag ty = ty.ty_tag -end - -module Ty = StructMake (Tty) +end) module Sty = Ty.S module Mty = Ty.M module Hty = Ty.H - -module Wty = Hashweak.Make (struct - type t = ty - let key ty = ty.ty_weak -end) +module Wty = Ty.W let mk_ty n = { ty_node = n; - ty_weak = Hashweak.create_key (); - ty_tag = -1 + ty_tag = Hashweak.dummy_tag; } let ty_var n = Hsty.hashcons (mk_ty (Tyvar n)) diff --git a/src/core/ty.mli b/src/core/ty.mli index 2bdeced92d02bec26a3c1e6b0caef8b1da9e00f8..070292a5f9200660763e3a3fa5c8099871f871bb 100644 --- a/src/core/ty.mli +++ b/src/core/ty.mli @@ -31,6 +31,8 @@ module Htv : Hashtbl.S with type key = tvsymbol val tv_equal : tvsymbol -> tvsymbol -> bool +val tv_hash : tvsymbol -> int + val create_tvsymbol : preid -> tvsymbol (* type symbols and types *) @@ -43,8 +45,7 @@ type tysymbol = private { and ty = private { ty_node : ty_node; - ty_weak : Hashweak.key; - ty_tag : int; + ty_tag : Hashweak.tag; } and ty_node = private @@ -56,8 +57,6 @@ module Mts : Map.S with type key = tysymbol module Hts : Hashtbl.S with type key = tysymbol module Wts : Hashweak.S with type key = tysymbol -module Tty : Util.Tagged with type t = ty - module Sty : Set.S with type elt = ty module Mty : Map.S with type key = ty module Hty : Hashtbl.S with type key = ty @@ -66,6 +65,9 @@ module Wty : Hashweak.S with type key = ty val ts_equal : tysymbol -> tysymbol -> bool val ty_equal : ty -> ty -> bool +val ts_hash : tysymbol -> int +val ty_hash : ty -> int + exception BadTypeArity of tysymbol * int * int exception DuplicateTypeVar of tvsymbol exception UnboundTypeVar of tvsymbol diff --git a/src/programs/pgm_effect.ml b/src/programs/pgm_effect.ml index a531f037ab4fb4b147b65dea0c8ea3e675027105..f3955de0ddaff6d7f19459c81a31c94af7c43e7d 100644 --- a/src/programs/pgm_effect.ml +++ b/src/programs/pgm_effect.ml @@ -49,21 +49,11 @@ module Reference = struct type t = reference - module Vsym = OrderedHash(struct - type t = vsymbol - let tag vs = vs.vs_name.id_tag - end) - - module Lsym = OrderedHash(struct - type t = lsymbol - let tag ls = ls.ls_name.id_tag - end) - let compare r1 r2 = match r1, r2 with - | Rlocal v1, Rlocal v2 -> Vsym.compare v1 v2 - | Rglobal l1, Rglobal l2 -> Lsym.compare l1 l2 - | Rlocal _, Rglobal _ -> -1 - | Rglobal _, Rlocal _ -> 1 + | Rlocal v1, Rlocal v2 -> compare (vs_hash v1) (vs_hash v2) + | Rglobal l1, Rglobal l2 -> compare (ls_hash l1) (ls_hash l2) + | Rlocal _, Rglobal _ -> -1 + | Rglobal _, Rlocal _ -> 1 let equal r1 r2 = compare r1 r2 = 0 diff --git a/src/transform/encoding_bridge.ml b/src/transform/encoding_bridge.ml index efb226ff391f892c82d7760e1ae5eb1a66226ebd..b7fe1e1f151ab98d5ab57aeb18867e81ed229bdd 100644 --- a/src/transform/encoding_bridge.ml +++ b/src/transform/encoding_bridge.ml @@ -70,7 +70,7 @@ let load_prelude kept env = task_tdecls task in task, { kept = kept; - clone_builtin = Wts.memoize clone_builtin; + clone_builtin = Wts.memoize 7 clone_builtin; specials = specials; trans_lsymbol = Hls.create 17; trans_tsymbol = trans_tsymbol} diff --git a/src/transform/encoding_instantiate.ml b/src/transform/encoding_instantiate.ml index 8cc33066178bea224bb0072d169f2871087b4565..347707adc4e06b0b5157a8570f77e9693a2f4398 100644 --- a/src/transform/encoding_instantiate.ml +++ b/src/transform/encoding_instantiate.ml @@ -40,7 +40,11 @@ let ty_dumb = ty_var tv_dumb instantié. Un tag sur un logique polymorphe doit être un tag sur toute la famille de fonctions *) -module OHTyl = OrderedHashList(Tty) +module OHTyl = OrderedHashList(struct + type t = ty + let tag = ty_hash +end) + module Mtyl = Map.Make(OHTyl) type tenv_aux = { diff --git a/src/transform/encoding_simple.ml b/src/transform/encoding_simple.ml index 826b866ade994d7ed19ccb330e439f01070ecac0..24e6fe9ce92a2835ad243659802315c8e505598d 100644 --- a/src/transform/encoding_simple.ml +++ b/src/transform/encoding_simple.ml @@ -69,7 +69,7 @@ let init_tenv kept = in task, { kept = kept; - declare_kept = Wts.memoize declare_kept; + declare_kept = Wts.memoize 7 declare_kept; specials = specials; ty_uni = ty_uni; trans_lsymbol = Hls.create 17 } diff --git a/src/transform/hypothesis_selection.ml b/src/transform/hypothesis_selection.ml index 8555aca012cab167f08bf3fb500b6082bfa8ab66..cf50fb74cda0d47d1826c0b81160aefff3507986 100644 --- a/src/transform/hypothesis_selection.ml +++ b/src/transform/hypothesis_selection.ml @@ -38,41 +38,29 @@ end open Graph module GP = Graph.Persistent.Digraph.ConcreteLabeled( struct - type t = Term.lsymbol - let compare x y = compare x.ls_name.id_tag y.ls_name.id_tag - let hash x = x.ls_name.id_tag - let equal x y = x.ls_name.id_tag = y.ls_name.id_tag + type t = lsymbol + let compare x y = compare (ls_hash x) (ls_hash y) + let hash = ls_hash + let equal = ls_equal end)(Int_Dft) (** a way to compare/hash expressions *) module ExprNode = struct type t = Term.expr + let compare x y = match x,y with - | Term t1, Term t2 -> compare t1.t_tag t2.t_tag - | Fmla f1, Fmla f2 -> compare f1.f_tag f2.f_tag + | Term t1, Term t2 -> compare (t_hash t1) (t_hash t2) + | Fmla f1, Fmla f2 -> compare (f_hash f1) (f_hash f2) | Term _, Fmla _ -> -1 | Fmla _, Term _ -> 1 + let hash x = match x with - | Term t -> t.t_tag - | Fmla f -> f.f_tag + | Term t -> 2 * (t_hash t) + | Fmla f -> 2 * (f_hash f) + 1 + let equal x y = compare x y == 0 end module GC = Graph.Persistent.Graph.Concrete(ExprNode) -module SymbHashtbl = - Hashtbl.Make(struct type t = Term.lsymbol - let equal x y = x.ls_name.id_tag = y.ls_name.id_tag - let hash x = x.ls_name.id_tag - end) -module FmlaHashtbl = - Hashtbl.Make(struct type t = Term.fmla - let equal x y = x.f_tag = y.f_tag - let hash x = x.f_tag - end) -module TermHashtbl = - Hashtbl.Make(struct type t = Term.term - let equal x y = x.t_tag = y.t_tag - let hash x = x.t_tag - end) module Sls = Set.Make(GP.V) module Sexpr = Set.Make(ExprNode) @@ -189,12 +177,12 @@ module NF = struct (* add memoization, one day ? *) let var,_,f = f_open_quant f_bound in traverse fmlaTable old_fmla (var@vars) f | _ -> - if FmlaHashtbl.mem fmlaTable fmla then - [[FmlaHashtbl.find fmlaTable fmla]] + if Hfmla.mem fmlaTable fmla then + [[Hfmla.find fmlaTable fmla]] else let new_fmla = create_fmla vars in - FmlaHashtbl.add fmlaTable old_fmla new_fmla; - FmlaHashtbl.add fmlaTable new_fmla new_fmla; + Hfmla.add fmlaTable old_fmla new_fmla; + Hfmla.add fmlaTable new_fmla new_fmla; [[new_fmla]] (** skips prenex quantifiers *) @@ -244,21 +232,21 @@ end (** module used to compute the graph of relations between constants *) module GraphConstant = struct - + (** memoizing for formulae and terms, and then expressions *) let rec findF fTbl fmla = try - FmlaHashtbl.find fTbl fmla + Hfmla.find fTbl fmla with Not_found -> let new_v = GC.V.create (Fmla fmla) in - FmlaHashtbl.add fTbl fmla new_v; + Hfmla.add fTbl fmla new_v; (* Format.eprintf "generating new vertex : %a@." Pretty.print_fmla fmla; *) new_v and findT tTbl term = try - TermHashtbl.find tTbl term + Hterm.find tTbl term with Not_found -> let new_v = GC.V.create (Term term) in - TermHashtbl.add tTbl term new_v; + Hterm.add tTbl term new_v; (* Format.eprintf "generating new vertex : %a@." Pretty.print_fmla fmla; *) new_v @@ -321,7 +309,7 @@ module GraphConstant = struct List.fold_left (analyse_clause fTbl tTbl) gc clauses (** processes a single task_head. *) - let update fmlaTable fTbl tTbl gc task_head = + let update fmlaTable fTbl tTbl gc task_head = match task_head.task_decl.Theory.td_node with | Theory.Decl {d_node = Dprop(_,_,prop_decl)} -> analyse_prop fmlaTable fTbl tTbl gc prop_decl @@ -349,10 +337,10 @@ module GraphPredicate = struct with Exit p -> p let find symbTbl x = try - SymbHashtbl.find symbTbl x + Hls.find symbTbl x with Not_found -> let new_v = GP.V.create x in - SymbHashtbl.add symbTbl x new_v; + Hls.add symbTbl x new_v; (* Format.eprintf "generating new vertex : %a@." Pretty.print_ls x; *) new_v @@ -524,7 +512,7 @@ module Select = struct | (_,`Negative) -> true | (_,`Positive) -> false in let find_secure symbTbl x = - try SymbHashtbl.find symbTbl x + try Hls.find symbTbl x with Not_found -> Format.eprintf "failure finding %a !@." Pretty.print_ls x; raise Not_found in @@ -555,7 +543,7 @@ module Select = struct List.fold_left Util.merge_list [] (List.map (build_relevant_variables gc) goal_clauses) in function fmla -> - let rec is_close_enough x l count = match (l,count) with + let rec is_close_enough x l count = match (l,count) with | _,n when n < 0 -> false | y::_,_ when Sexpr.mem x y -> true | _::ys,count -> is_close_enough x ys (count-1) @@ -609,7 +597,7 @@ let transformation fmlaTable fTbl tTbl symbTbl task = (* first, collect data in 2 graphes *) let (gc,gp,goal_option) = Trans.apply (collect_info fmlaTable fTbl tTbl symbTbl) task in - Format.fprintf Format.err_formatter "graph: @\n@\n%a@\n@." Dot_.fprint_graph gc; + Format.fprintf Format.err_formatter "graph: @\n@\n%a@\n@." Dot_.fprint_graph gc; (* get the goal *) let goal_fmla = match goal_option with | None -> failwith "no goal !" @@ -622,10 +610,10 @@ let transformation fmlaTable fTbl tTbl symbTbl task = (** the transformation to be registered *) let hypothesis_selection = (* create lots of hashtables... *) - let fmlaTable = FmlaHashtbl.create 17 in - let fTbl = FmlaHashtbl.create 17 in - let tTbl = TermHashtbl.create 17 in - let symbTbl = SymbHashtbl.create 17 in + let fmlaTable = Hfmla.create 17 in + let fTbl = Hfmla.create 17 in + let tTbl = Hterm.create 17 in + let symbTbl = Hls.create 17 in Trans.store (transformation fmlaTable fTbl tTbl symbTbl) let _ = Trans.register_transform "hypothesis_selection" hypothesis_selection diff --git a/src/util/hashweak.ml b/src/util/hashweak.ml index eb9121f32576b3e1ab840de39e0d38b7b24df003..bf37dba99f3b6d16d9caada8ecc10ca1a303d91e 100644 --- a/src/util/hashweak.ml +++ b/src/util/hashweak.ml @@ -17,17 +17,19 @@ (* *) (**************************************************************************) -module Weak : sig +module type S = sig type key type 'a t - val create_key : unit -> key - - val create : unit -> 'a t + val create : int -> 'a t (* create a hashtbl with weak keys *) + val clear : 'a t -> unit + + val copy : 'a t -> 'a t + val find : 'a t -> key -> 'a (* find the value bound to a key. Raises Not_found if there is no binding *) @@ -38,90 +40,121 @@ module Weak : sig val set : 'a t -> key -> 'a -> unit (* bind the key _once_ with the given value *) -end = struct - - type key = ((int,Obj.t) Hashtbl.t) Lazy.t + val remove : 'a t -> key -> unit + (* remove the value *) - type 'a t = int + val iter : (key -> 'a -> unit) -> 'a t -> unit - let create_key () = lazy (Hashtbl.create 3) + val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b - let create = let c = ref (-1) in fun () -> incr c; !c + val iterk : (key -> unit) -> 'a t -> unit - let find t k = Obj.obj (Hashtbl.find (Lazy.force k) t) - let mem t k = Hashtbl.mem (Lazy.force k) t - let set t k v = Hashtbl.replace (Lazy.force k) t (Obj.repr v) + val foldk : (key -> 'b -> 'b) -> 'a t -> 'b -> 'b -end - -include Weak - -module type S = sig + val length : 'a t -> int - type key + val memoize : int -> (key -> 'a) -> (key -> 'a) + (* create a memoizing function *) - type 'a t + val memoize_option : int -> (key option -> 'a) -> (key option -> 'a) + (* memoizing functions on option types *) - val create : unit -> 'a t - (* create a hashtbl with weak keys *) +end - val find : 'a t -> key -> 'a - (* find the value bound to a key. - Raises Not_found if there is no binding *) +type tag = { + tag_map : ((int,Obj.t) Hashtbl.t) Lazy.t; + tag_tag : int; +} - val mem : 'a t -> key -> bool - (* test if a key is bound *) +let create_tag tag = { + tag_map = lazy (Hashtbl.create 3); + tag_tag = tag; +} - val set : 'a t -> key -> 'a -> unit - (* bind the key _once_ with the given value *) +let dummy_tag = { + tag_map = lazy (failwith "dummy tag"); + tag_tag = -1; +} - val memoize : (key -> 'a) -> (key -> 'a) - (* create a memoizing function *) +let tag_hash k = assert (k != dummy_tag); k.tag_tag - val memoize_option : (key option -> 'a) -> (key option -> 'a) - (* memoizing functions on option types *) +let tag_equal k1 k2 = k1.tag_tag = k2.tag_tag -end +let tag_compare k1 k2 = Pervasives.compare k1.tag_tag k2.tag_tag module type Weakey = sig type t - val key : t -> Weak.key + val tag : t -> tag end module Make (S : Weakey) = struct type key = S.t - type 'a t = 'a Weak.t + module H = Weak.Make (struct + type t = S.t + let hash k = (S.tag k).tag_tag + let equal k1 k2 = S.tag k1 == S.tag k2 + end) + + type 'a t = { + tbl_set : H.t; + tbl_tag : int; + } + + let tag_map k = Lazy.force (S.tag k).tag_map + + let find (t : 'a t) k : 'a = + Obj.obj (Hashtbl.find (tag_map k) t.tbl_tag) + + let mem t k = Hashtbl.mem (tag_map k) t.tbl_tag + + let set (t : 'a t) k (v : 'a) = + Hashtbl.replace (tag_map k) t.tbl_tag (Obj.repr v); + H.add t.tbl_set k + + let remove t k = + Hashtbl.remove (tag_map k) t.tbl_tag; + H.remove t.tbl_set k + + let iterk fn t = H.iter fn t.tbl_set + let foldk fn t = H.fold fn t.tbl_set + + let iter fn t = H.iter (fun k -> fn k (find t k)) t.tbl_set + let fold fn t = H.fold (fun k -> fn k (find t k)) t.tbl_set + + let tbl_final t = iterk (fun k -> Hashtbl.remove (tag_map k) t.tbl_tag) t - let create = Weak.create + let create = let c = ref (-1) in fun n -> + let t = { + tbl_set = H.create n; + tbl_tag = (incr c; !c) } + in + Gc.finalise tbl_final t; + t - let set_key h = Weak.set h - let mem_key h = Weak.mem h - let find_key h = Weak.find h + let clear t = tbl_final t; H.clear t.tbl_set - let set_key h k v = - assert (not (mem_key h k)); - set_key h k v + let length t = H.count t.tbl_set - let set h e = set_key h (S.key e) - let mem h e = mem_key h (S.key e) - let find h e = find_key h (S.key e) + let copy t = + let t' = create (length t) in + iter (set t') t; + t' - let memoize fn = - let h = create () in fun e -> - let k = S.key e in - try find_key h k + let memoize n fn = + let h = create n in fun e -> + try find h e with Not_found -> let v = fn e in - set_key h k v; + set h e v; v - let memoize_option fn = + let memoize_option n fn = let v = lazy (fn None) in let fn e = fn (Some e) in - let fn = memoize fn in + let fn = memoize n fn in function | Some e -> fn e | None -> Lazy.force v diff --git a/src/util/hashweak.mli b/src/util/hashweak.mli index 9455b26f819143c3db6d620e5e6f00376bc05c06..4d5a2f3a0947233f9e5c9508c96961c4594d91de 100644 --- a/src/util/hashweak.mli +++ b/src/util/hashweak.mli @@ -19,24 +19,17 @@ (** Hashtable with weak key used for memoization *) -type key +type tag -type 'a t +val dummy_tag : tag -val create_key : unit -> key +val create_tag : int -> tag -val create : unit -> 'a t - (* create a hashtbl with weak keys *) +val tag_hash : tag -> int -val find : 'a t -> key -> 'a - (* find the value bound to a key. - Raises Not_found if there is no binding *) +val tag_equal : tag -> tag -> bool -val mem : 'a t -> key -> bool - (* test if a key is bound *) - -val set : 'a t -> key -> 'a -> unit - (* assign the key to the given value *) +val tag_compare : tag -> tag -> int module type S = sig @@ -44,9 +37,13 @@ module type S = sig type 'a t - val create : unit -> 'a t + val create : int -> 'a t (* create a hashtbl with weak keys *) + val clear : 'a t -> unit + + val copy : 'a t -> 'a t + val find : 'a t -> key -> 'a (* find the value bound to a key. Raises Not_found if there is no binding *) @@ -57,10 +54,23 @@ module type S = sig val set : 'a t -> key -> 'a -> unit (* bind the key _once_ with the given value *) - val memoize : (key -> 'a) -> (key -> 'a) + val remove : 'a t -> key -> unit + (* remove the value *) + + val iter : (key -> 'a -> unit) -> 'a t -> unit + + val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b + + val iterk : (key -> unit) -> 'a t -> unit + + val foldk : (key -> 'b -> 'b) -> 'a t -> 'b -> 'b + + val length : 'a t -> int + + val memoize : int -> (key -> 'a) -> (key -> 'a) (* create a memoizing function *) - val memoize_option : (key option -> 'a) -> (key option -> 'a) + val memoize_option : int -> (key option -> 'a) -> (key option -> 'a) (* memoizing functions on option types *) end @@ -68,7 +78,7 @@ end module type Weakey = sig type t - val key : t -> key + val tag : t -> tag end module Make (S : Weakey) : S with type key = S.t diff --git a/src/util/util.ml b/src/util/util.ml index 37d9e35ca768bfcf1176bb8216d55d70418960dc..f2e2043a2e442d123cc8da6933b7d778abf17075 100644 --- a/src/util/util.ml +++ b/src/util/util.ml @@ -148,6 +148,21 @@ struct module H = Hashtbl.Make(T) end +module MakeTagged (X : Hashweak.Weakey) = +struct + type t = X.t + let tag t = Hashweak.tag_hash (X.tag t) +end + +module WeakStructMake (X : Hashweak.Weakey) = +struct + module T = OrderedHash(MakeTagged(X)) + module S = Set.Make(T) + module M = Map.Make(T) + module H = Hashtbl.Make(T) + module W = Hashweak.Make(X) +end + (* memoization *) let memo ?(size=17) f = diff --git a/src/util/util.mli b/src/util/util.mli index 8932cf02768dbe49deb4a583ec55818348036d07..812c155124a2780996fb6c71ea889f902c554ea4 100644 --- a/src/util/util.mli +++ b/src/util/util.mli @@ -110,6 +110,14 @@ sig module H : Hashtbl.S with type key = X.t end +module WeakStructMake (X : Hashweak.Weakey) : +sig + module S : Set.S with type elt = X.t + module M : Map.S with type key = X.t + module H : Hashtbl.S with type key = X.t + module W : Hashweak.S with type key = X.t +end + (* memoization *) val memo : ?size:int -> ('a -> 'b) -> 'a -> 'b