Import Upstream version 20180207
[hcoop/debian/mlton.git] / lib / mlton / basic / hash-table.sml
CommitLineData
7f918cf1
CE
1(* Copyright (C) 1999-2006, 2008 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
3 *
4 * MLton is released under a BSD-style license.
5 * See the file MLton-LICENSE for details.
6 *)
7
8(* This code is not working -- it is not even in sources.cm *)
9structure HashTable: HASH_TABLE =
10struct
11
12structure Set = HashSet
13
14type ('a, 'b) t = ('a * 'b) Set.t
15
16fun ('a, 'b) new {equals, hash}: ('a, 'b) t =
17 Set.new {equals = fn ((a, _), (a', _)) => equals (a, a')
18 hash = hash o #1}
19
20local
21 open Set
22in
23 val size = size
24 val stats = stats
25end
26
27fun update (t, a, b) = Set.update (t, (a, b))
28
29fun peek (t, a) =
30 Option.map (Set.peek (t, Set.hash (t,
31
32fun update (T {buckets = ref buckets, equals, mask, ...}, w, a, b) =
33 let
34 val j = index (w, !mask)
35 val _ =
36 Array.update
37 (buckets, j,
38 (w, a, b)
39 :: List.fold (Array.sub (buckets, j), [], fn (z as (w', a', _), ac) =>
40 if Word.equals (w, w') andalso equals (a, a')
41 then ac
42 else z :: ac))
43 in ()
44 end
45
46fun peek(t, w, i) = peekGen(t, w, i, fn _ => NONE, SOME)
47
48fun lookupGen (table as T {buckets, numItems, ...}, w, i, x, yes) =
49 let
50 fun no (j, b) =
51 let val x = x ()
52 val _ = Int.inc numItems
53 val _ = Array.update (!buckets, j, (w, i, x) :: b)
54 val _ = maybeGrow table
55 in x
56 end
57 in peekGen (table, w, i, no, yes)
58 end
59
60fun lookupOrInsert (table, w, i, x) =
61 lookupGen (table, w, i, x, fn x => x)
62
63fun insertIfNew (table, w, i, x, yes) =
64 lookupGen (table, w, i, fn () => x, fn _ => yes ())
65
66fun foldi(T{buckets, ...}, b, f) =
67 Array.fold(!buckets, b, fn (r, b) =>
68 List.fold(r, b, fn ((_, i, x), b) => f(i, x, b)))
69
70fun listItemsi t = foldi(t, [], fn (i, x, l) => (i, x) :: l)
71
72fun layout lay t = List.layout lay (listItemsi t)
73
74fun fold(t, b, f) = foldi(t, b, fn (_, x, b) => f(x, b))
75
76fun foreachi(t, f) = foldi(t, (), fn (i, x, ()) => f(i, x))
77
78fun foreach(t, f) = foreachi(t, f o #2)
79
80fun foralli(t, f) =
81 DynamicWind.withEscape
82 (fn escape =>
83 (foreachi(t, fn z => if f z then () else escape false)
84 ; true))
85
86fun forall(t, f) = foralli(t, f o #2)
87
88fun listItems t = fold(t, [], op ::)
89
90fun appi(t, f) = foldi(t, (), fn (i, x, ()) => f(i, x))
91
92fun app(t, f) = appi(t, f o #2)
93
94fun mapi (T{numItems, mask, equals, buckets}, f) =
95 T {numItems = ref (!numItems),
96 mask = ref (!mask),
97 equals = equals,
98 buckets = ref (Array.map (!buckets, fn r =>
99 List.revMap (r, fn (w, i, x) =>
100 (w, i, f (i, x)))))}
101
102fun map (t, f) = mapi (t, f o #2)
103
104end