Commit | Line | Data |
---|---|---|
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 *) | |
9 | structure HashTable: HASH_TABLE = | |
10 | struct | |
11 | ||
12 | structure Set = HashSet | |
13 | ||
14 | type ('a, 'b) t = ('a * 'b) Set.t | |
15 | ||
16 | fun ('a, 'b) new {equals, hash}: ('a, 'b) t = | |
17 | Set.new {equals = fn ((a, _), (a', _)) => equals (a, a') | |
18 | hash = hash o #1} | |
19 | ||
20 | local | |
21 | open Set | |
22 | in | |
23 | val size = size | |
24 | val stats = stats | |
25 | end | |
26 | ||
27 | fun update (t, a, b) = Set.update (t, (a, b)) | |
28 | ||
29 | fun peek (t, a) = | |
30 | Option.map (Set.peek (t, Set.hash (t, | |
31 | ||
32 | fun 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 | ||
46 | fun peek(t, w, i) = peekGen(t, w, i, fn _ => NONE, SOME) | |
47 | ||
48 | fun 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 | ||
60 | fun lookupOrInsert (table, w, i, x) = | |
61 | lookupGen (table, w, i, x, fn x => x) | |
62 | ||
63 | fun insertIfNew (table, w, i, x, yes) = | |
64 | lookupGen (table, w, i, fn () => x, fn _ => yes ()) | |
65 | ||
66 | fun 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 | ||
70 | fun listItemsi t = foldi(t, [], fn (i, x, l) => (i, x) :: l) | |
71 | ||
72 | fun layout lay t = List.layout lay (listItemsi t) | |
73 | ||
74 | fun fold(t, b, f) = foldi(t, b, fn (_, x, b) => f(x, b)) | |
75 | ||
76 | fun foreachi(t, f) = foldi(t, (), fn (i, x, ()) => f(i, x)) | |
77 | ||
78 | fun foreach(t, f) = foreachi(t, f o #2) | |
79 | ||
80 | fun foralli(t, f) = | |
81 | DynamicWind.withEscape | |
82 | (fn escape => | |
83 | (foreachi(t, fn z => if f z then () else escape false) | |
84 | ; true)) | |
85 | ||
86 | fun forall(t, f) = foralli(t, f o #2) | |
87 | ||
88 | fun listItems t = fold(t, [], op ::) | |
89 | ||
90 | fun appi(t, f) = foldi(t, (), fn (i, x, ()) => f(i, x)) | |
91 | ||
92 | fun app(t, f) = appi(t, f o #2) | |
93 | ||
94 | fun 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 | ||
102 | fun map (t, f) = mapi (t, f o #2) | |
103 | ||
104 | end |