diff options
author | Pierre-Marie Pédrot <pierre-marie.pedrot@inria.fr> | 2014-12-18 16:10:15 +0100 |
---|---|---|
committer | Pierre-Marie Pédrot <pierre-marie.pedrot@inria.fr> | 2014-12-18 18:29:29 +0100 |
commit | 3f36f6fe68e1170f3d8c374e708513f05cc99619 (patch) | |
tree | d19607582af6b66a79d325da132480ae766a6cce /kernel/univ.ml | |
parent | b49d803286ba9ed711313702bb4269c5e9c516fa (diff) |
Cleaning up universe list implementation in Univ.
We use private types to ensure apriori hashconsing, and get rid of the
use of recursive modules. The hash of the universe list is also inlined
into each node instead of relying on a supplementary indirection.
Diffstat (limited to 'kernel/univ.ml')
-rw-r--r-- | kernel/univ.ml | 343 |
1 files changed, 131 insertions, 212 deletions
diff --git a/kernel/univ.ml b/kernel/univ.ml index 2cac50fda..8dd733911 100644 --- a/kernel/univ.ml +++ b/kernel/univ.ml @@ -31,83 +31,59 @@ open Util union-find algorithm. The assertions $<$ and $\le$ are represented by adjacency lists *) -module Uid = struct - type t = int - - let make_maker () = - let _id = ref ~-1 in - fun () -> incr _id;!_id - - let dummy = -1 - let to_int id = id +module type Hashconsed = +sig + type t + val hash : t -> int + val equal : t -> t -> bool + val hcons : t -> t end -module Hcons = struct - - type 'a node = { id : Uid.t; key : int; node : 'a } - - module type S = - sig - type data - type t = data node - val make : data -> t - val node : t -> data - val hash : t -> int - val stats : unit -> unit - val init : unit -> unit - end - - module Make (H : Hashtbl.HashedType) : S with type data = H.t = +module HashedList (M : Hashconsed) : +sig + type t = private Nil | Cons of M.t * int * t + val nil : t + val cons : M.t -> t -> t +end = +struct + type t = Nil | Cons of M.t * int * t + module Self = struct - let uid_make = Uid.make_maker() - type data = H.t - type t = data node - let node t = t.node - let hash t = t.key - module WH = Weak.Make( struct - type _t = t - type t = _t - let hash = hash - let equal a b = a == b || H.equal a.node b.node - end) - let pool = WH.create 491 - - let total_count = ref 0 - let miss_count = ref 0 - let init () = - total_count := 0; - miss_count := 0 - - let make x = - incr total_count; - let cell = { id = Uid.dummy; key = H.hash x; node = x } in - try - WH.find pool cell - with - | Not_found -> - let cell = { cell with id = uid_make(); } in - incr miss_count; - WH.add pool cell; - cell - - let stats () = () + type _t = t + type t = _t + type u = (M.t -> M.t) + let hash = function Nil -> 0 | Cons (_, h, _) -> h + let equal l1 l2 = match l1, l2 with + | Nil, Nil -> true + | Cons (x1, _, l1), Cons (x2, _, l2) -> x1 == x2 && l1 == l2 + | _ -> false + let hashcons hc = function + | Nil -> Nil + | Cons (x, h, l) -> Cons (hc x, h, l) end + module Hcons = Hashcons.Make(Self) + let hcons = Hashcons.simple_hcons Hcons.generate Hcons.hcons M.hcons + (** No recursive call: the interface guarantees that all HLists from this + program are already hashconsed. If we get some external HList, we can + still reconstruct it by traversing it entirely. *) + let nil = Nil + let cons x l = + let h = M.hash x in + let hl = match l with Nil -> 0 | Cons (_, h, _) -> h in + let h = Hashset.Combine.combine h hl in + hcons (Cons (x, h, l)) end module HList = struct module type S = sig type elt - type 'a node = Nil | Cons of elt * 'a - type t - type data = t node + type t = private Nil | Cons of elt * int * t val hash : t -> int - val make : data -> t val nil : t + val cons : elt -> t -> t val is_nil : t -> bool val tip : elt -> t - val node : t -> t node - val cons : (* ?sorted:bool -> *) elt -> t -> t val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a val map : (elt -> elt) -> t -> t val smartmap : (elt -> elt) -> t -> t @@ -120,129 +96,68 @@ module HList = struct val compare : (elt -> elt -> int) -> t -> t -> int end - module Make (H : Hashtbl.HashedType) : S with type elt = H.t = + module Make (H : Hashconsed) : S with type elt = H.t = struct - type elt = H.t - type 'a node = Nil | Cons of elt * 'a - - module rec Node : Hcons.S with type data = Data.t = Hcons.Make(Data) + type elt = H.t + include HashedList(H) + + let hash = function Nil -> 0 | Cons (_, h, _) -> h + + let is_nil = function Nil -> true | Cons _ -> false + + let tip e = cons e nil + + let rec fold f l accu = match l with + | Nil -> accu + | Cons (x, _, l) -> fold f l (f x accu) + + let rec map f = function + | Nil -> nil + | Cons (x, _, l) -> cons (f x) (map f l) + + let smartmap = map + (** Apriori hashconsing ensures that the map is equal to its argument *) + + let rec exists f = function + | Nil -> false + | Cons (x, _, l) -> f x || exists f l + + let rec for_all f = function + | Nil -> true + | Cons (x, _, l) -> f x && for_all f l + + let rec for_all2 f l1 l2 = match l1, l2 with + | Nil, Nil -> true + | Cons (x1, _, l1), Cons (x2, _, l2) -> f x1 x2 && for_all2 f l1 l2 + | _ -> false + + let rec to_list = function + | Nil -> [] + | Cons (x, _, l) -> x :: to_list l + + let rec remove x = function + | Nil -> nil + | Cons (y, _, l) -> + if H.equal x y then l + else cons y (remove x l) + + let rec mem x = function + | Nil -> false + | Cons (y, _, l) -> H.equal x y || mem x l + + let rec compare cmp l1 l2 = match l1, l2 with + | Nil, Nil -> 0 + | Cons (x1, h1, l1), Cons (x2, h2, l2) -> + let c = Int.compare h1 h2 in + if c == 0 then + let c = cmp x1 x2 in + if c == 0 then + compare cmp l1 l2 + else c + else c + | Cons _, Nil -> 1 + | Nil, Cons _ -> -1 - and Data : Hashtbl.HashedType with type t = Node.t node = - struct - type t = Node.t node - let equal x y = - match x,y with - | _,_ when x==y -> true - | Cons (a,aa), Cons(b,bb) -> (aa==bb) && (H.equal a b) - | _ -> false - let hash = function - | Nil -> 0 - | Cons(a,aa) -> 17 + 65599 * (H.hash a) + 491 * (Uid.to_int aa.Hcons.id) - end - - type data = Data.t - type t = Node.t - let make = Node.make - let node x = x.Hcons.node - let hash x = x.Hcons.key - let nil = Node.make Nil - - let is_nil = - function { Hcons.node = Nil } -> true | _ -> false - - let cons e l = - Node.make(Cons(e, l)) - - let tip e = Node.make (Cons(e, nil)) - - let fold f l acc = - let rec loop acc l = match l.Hcons.node with - | Nil -> acc - | Cons (a, aa) -> loop (f a acc) aa - in - loop acc l - - let map f l = - let rec loop l = match l.Hcons.node with - | Nil -> l - | Cons(a, aa) -> cons (f a) (loop aa) - in - loop l - - let smartmap f l = - let rec loop l = match l.Hcons.node with - | Nil -> l - | Cons (a, aa) -> - let a' = f a in - if a' == a then - let aa' = loop aa in - if aa' == aa then l - else cons a aa' - else cons a' (loop aa) - in loop l - - let exists f l = - let rec loop l = match l.Hcons.node with - | Nil -> false - | Cons(a,aa) -> f a || loop aa - in - loop l - - let for_all f l = - let rec loop l = match l.Hcons.node with - | Nil -> true - | Cons(a,aa) -> f a && loop aa - in - loop l - - let for_all2 f l l' = - let rec loop l l' = match l.Hcons.node, l'.Hcons.node with - | Nil, Nil -> true - | Cons(a,aa), Cons(b,bb) -> f a b && loop aa bb - | _, _ -> false - in - loop l l' - - let to_list l = - let rec loop l = match l.Hcons.node with - | Nil -> [] - | Cons(a,aa) -> a :: loop aa - in - loop l - - let remove x l = - let rec loop l = match l.Hcons.node with - | Nil -> l - | Cons(a,aa) -> - if H.equal a x then aa - else cons a (loop aa) - in - loop l - - let rec mem e l = - match l.Hcons.node with - | Nil -> false - | Cons (x, ll) -> H.equal x e || mem e ll - - let rec compare cmp l1 l2 = - if l1 == l2 then 0 - else - let hl1 = hash l1 and hl2 = hash l2 in - let c = Int.compare hl1 hl2 in - if c == 0 then - let nl1 = node l1 in - let nl2 = node l2 in - if nl1 == nl2 then 0 - else - match nl1, nl2 with - | Nil, Nil -> assert false - | _, Nil -> 1 - | Nil, _ -> -1 - | Cons (x1,l1), Cons(x2,l2) -> - (match cmp x1 x2 with - | 0 -> compare cmp l1 l2 - | c -> c) - else c end end @@ -485,10 +400,12 @@ struct module HExpr = struct - include Hashcons.Make(ExprHash) + module H = Hashcons.Make(ExprHash) + + type t = ExprHash.t - let make = - Hashcons.simple_hcons generate hcons Level.hcons + let hcons = + Hashcons.simple_hcons H.generate H.hcons Level.hcons let hash = ExprHash.hash let equal x y = x == y || (let (u,n) = x and (v,n') = y in @@ -496,7 +413,7 @@ struct end - let hcons = HExpr.make + let hcons = HExpr.hcons let make l = hcons (l, 0) @@ -599,44 +516,45 @@ struct Huniv.compare (fun e1 e2 -> compare_expr e1 e2) x y else c - let hcons_unique = Huniv.make - let hcons x = hcons_unique x + let rec hcons = function + | Nil -> Huniv.nil + | Cons (x, _, l) -> Huniv.cons x (hcons l) let make l = Huniv.tip (Expr.make l) let tip x = Huniv.tip x - - let pr l = match node l with - | Cons (u, n) when is_nil n -> Expr.pr u + + let pr l = match l with + | Cons (u, _, Nil) -> Expr.pr u | _ -> str "max(" ++ hov 0 (prlist_with_sep pr_comma Expr.pr (to_list l)) ++ str ")" - let pr_with f l = match node l with - | Cons (u, n) when is_nil n -> Expr.pr_with f u + let pr_with f l = match l with + | Cons (u, _, Nil) -> Expr.pr_with f u | _ -> str "max(" ++ hov 0 (prlist_with_sep pr_comma (Expr.pr_with f) (to_list l)) ++ str ")" - let atom l = match node l with - | Cons (l, n) when is_nil n -> Some l + let atom l = match l with + | Cons (l, _, Nil) -> Some l | _ -> None - let is_level l = match node l with - | Cons (l, n) when is_nil n -> Expr.is_level l + let is_level l = match l with + | Cons (l, _, Nil) -> Expr.is_level l | _ -> false - let level l = match node l with - | Cons (l, n) when is_nil n -> Expr.level l + let level l = match l with + | Cons (l, _, Nil) -> Expr.level l | _ -> None let levels l = fold (fun x acc -> LSet.add (Expr.get_level x) acc) l LSet.empty let is_small u = - match node u with - | Cons (l, n) when is_nil n -> Expr.is_small l + match u with + | Cons (l, _, Nil) -> Expr.is_small l | _ -> false (* The lower predicative level of the hierarchy that contains (impredicative) @@ -664,10 +582,10 @@ struct Huniv.map (fun x -> Expr.addn n x) l let rec merge_univs l1 l2 = - match node l1, node l2 with + match l1, l2 with | Nil, _ -> l2 | _, Nil -> l1 - | Cons (h1, t1), Cons (h2, t2) -> + | Cons (h1, _, t1), Cons (h2, _, t2) -> (match Expr.super h1 h2 with | Inl true (* h1 < h2 *) -> merge_univs t1 l2 | Inl false -> merge_univs l1 t2 @@ -678,8 +596,8 @@ struct let sort u = let rec aux a l = - match node l with - | Cons (b, l') -> + match l with + | Cons (b, _, l') -> (match Expr.super a b with | Inl false -> aux a l' | Inl true -> l @@ -695,7 +613,7 @@ struct let sup x y = merge_univs x y let empty = nil - let is_empty n = is_nil n + let is_empty = function Nil -> true | Cons _ -> false let exists = Huniv.exists @@ -1448,9 +1366,10 @@ let check_univ_leq u v = Universe.for_all (fun u -> check_univ_leq_one u v) u let enforce_leq u v c = - match Huniv.node v with - | Universe.Huniv.Cons (v, n) when Universe.is_empty n -> - Universe.Huniv.fold (fun u -> constraint_add_leq u v) u c + let open Universe.Huniv in + match v with + | Cons (v, _, Nil) -> + fold (fun u -> constraint_add_leq u v) u c | _ -> anomaly (Pp.str"A universe bound can only be a variable") let enforce_leq u v c = @@ -2130,7 +2049,7 @@ let hcons_universe_set = let hcons_universe_context_set (v, c) = (hcons_universe_set v, hcons_constraints c) -let hcons_univ x = Universe.hcons (Huniv.node x) +let hcons_univ x = Universe.hcons x let explain_universe_inconsistency (o,u,v,p) = let pr_rel = function |