summaryrefslogtreecommitdiff
path: root/hashtable.sml
diff options
context:
space:
mode:
Diffstat (limited to 'hashtable.sml')
-rw-r--r--hashtable.sml54
1 files changed, 30 insertions, 24 deletions
diff --git a/hashtable.sml b/hashtable.sml
index 822d1fd..286d241 100644
--- a/hashtable.sml
+++ b/hashtable.sml
@@ -3,10 +3,11 @@ structure Hashtable: HASHTABLE = struct
open Word
(* buf * taken * mask *)
- type 'a t = (string * 'a) option array * int * word
+ type 'a t = ((string * 'a) option array * int * word) ref
+
val ` = Word.fromInt
- val ! = Word.toInt
+ val ~> = Word.toInt
infixr 4 <<
infix 5 andb
@@ -18,10 +19,10 @@ structure Hashtable: HASHTABLE = struct
val size = `1 << `log
val mask = size - `1
in
- (array (Word.toInt size, NONE), 0, mask)
+ ref (array (Word.toInt size, NONE), 0, mask)
end
- exception Full and Exists
+ exception Full
fun hash key =
List.foldl (fn (c, s) => s * `31 + `(ord c)) (`17) (explode key)
@@ -39,37 +40,42 @@ structure Hashtable: HASHTABLE = struct
fun next idx mask = (idx + `1) andb mask
- fun lookup2 (array, _, mask) key f g =
+ fun insertIfNew H key v =
let
+ val (array, _, mask) = !H
+
+ fun inc H =
+ let
+ open Int
+ val (array, taken, mask) = !H
+ in
+ H := (array, taken + 1, mask)
+ end
+
+ val () = checkFreeSpace $ !H
fun find idx =
- case sub (array, !idx) of
- NONE => g ()
- | SOME (key', v) =>
+ case sub (array, ~> idx) of
+ NONE => (update (array, ~> idx, SOME (key, v)); inc H; NONE)
+ | SOME (key', v') =>
if key' = key then
- case f v of
- (NONE, res) => res
- | (SOME v, res) =>
- (update (array, !idx, SOME (key, v)); res)
+ (SOME v')
else
find (next idx mask)
in
find (hash key andb mask)
end
- fun lookup H key = lookup2 H key (fn v => (NONE, SOME v)) (fn () => NONE)
+ fun taken H =
+ let
+ val (_, taken, _) = !H
+ in
+ taken
+ end
- fun insert (H as (array, _, mask)) key v =
+ fun size H =
let
- val () = checkFreeSpace H;
- fun find idx =
- case sub (array, !idx) of
- NONE => update (array, !idx, SOME (key, v))
- | SOME (key', _) =>
- if key' = key then
- raise Exists
- else
- find (next idx mask)
+ val (array, _, _) = !H
in
- find (hash key andb mask)
+ length array
end
end