| 1 | {-# LANGUAGE BangPatterns, CPP #-} |
|---|
| 2 | module Data.HashMap |
|---|
| 3 | ( |
|---|
| 4 | HashMap |
|---|
| 5 | , lookup |
|---|
| 6 | ) where |
|---|
| 7 | |
|---|
| 8 | import Data.Bits ((.&.)) |
|---|
| 9 | import Data.Hashable (Hashable(hash)) |
|---|
| 10 | import qualified Data.FullList as FL |
|---|
| 11 | import Data.Word (Word) |
|---|
| 12 | import Prelude hiding (lookup) |
|---|
| 13 | |
|---|
| 14 | data HashMap k v |
|---|
| 15 | = Nil |
|---|
| 16 | | Tip {-# UNPACK #-} !Hash |
|---|
| 17 | {-# UNPACK #-} !(FL.FullList k v) |
|---|
| 18 | | Bin {-# UNPACK #-} !Prefix |
|---|
| 19 | {-# UNPACK #-} !Mask |
|---|
| 20 | !(HashMap k v) |
|---|
| 21 | !(HashMap k v) |
|---|
| 22 | |
|---|
| 23 | type Prefix = Int |
|---|
| 24 | type Mask = Int |
|---|
| 25 | type Hash = Int |
|---|
| 26 | |
|---|
| 27 | lookup :: (Eq k, Hashable k) => k -> HashMap k v -> Maybe v |
|---|
| 28 | lookup k0 t = go h0 k0 t |
|---|
| 29 | where |
|---|
| 30 | h0 = hash k0 |
|---|
| 31 | go !h !k (Bin _ m l r) |
|---|
| 32 | | zero h m = go h k l |
|---|
| 33 | | otherwise = go h k r |
|---|
| 34 | go h k (Tip h' l) |
|---|
| 35 | | h == h' = FL.lookup k l |
|---|
| 36 | | otherwise = Nothing |
|---|
| 37 | go _ _ Nil = Nothing |
|---|
| 38 | #if __GLASGOW_HASKELL__ >= 700 |
|---|
| 39 | {-# INLINABLE lookup #-} |
|---|
| 40 | #endif |
|---|
| 41 | |
|---|
| 42 | zero :: Hash -> Mask -> Bool |
|---|
| 43 | zero i m = (fromIntegral i :: Word) .&. (fromIntegral m :: Word) == 0 |
|---|
| 44 | {-# INLINE zero #-} |
|---|