[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / compiler / utils / FiniteMap.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1994-1998
3 %
4 \section[FiniteMap]{An implementation of finite maps}
5
6 ``Finite maps'' are the heart of the compiler's
7 lookup-tables/environments and its implementation of sets.  Important
8 stuff!
9
10 This code is derived from that in the paper:
11 \begin{display}
12         S Adams
13         "Efficient sets: a balancing act"
14         Journal of functional programming 3(4) Oct 1993, pp553-562
15 \end{display}
16
17 The code is SPECIALIZEd to various highly-desirable types (e.g., Id)
18 near the end.
19
20 \begin{code}
21
22 module FiniteMap (
23         FiniteMap,              -- abstract type
24
25         emptyFM, unitFM, listToFM,
26
27         addToFM,
28         addToFM_C,
29         addListToFM,
30         addListToFM_C,
31         delFromFM,
32         delListFromFM,
33
34         plusFM,
35         plusFM_C,
36         minusFM,
37         foldFM,
38
39         intersectFM,
40         intersectFM_C,
41         mapFM, filterFM, 
42
43         sizeFM, isEmptyFM, elemFM, lookupFM, lookupWithDefaultFM,
44
45         fmToList, keysFM, eltsFM
46
47         , bagToFM
48         , FiniteSet, emptySet, mkSet, isEmptySet
49         , elementOf, setToList, union, minusSet
50
51     ) where
52
53 #include "HsVersions.h"
54 #define IF_NOT_GHC(a) {--}
55
56 #if defined(DEBUG_FINITEMAPS)/* NB NB NB */
57 #define OUTPUTABLE_key , Outputable key
58 #else
59 #define OUTPUTABLE_key {--}
60 #endif
61
62 import {-# SOURCE #-} Name ( Name )
63 import GlaExts
64 import FastString
65 import Maybes
66 import Bag        ( Bag, foldrBag )
67 import Outputable
68
69 #if ! OMIT_NATIVE_CODEGEN
70 #  define IF_NCG(a) a
71 #else
72 #  define IF_NCG(a) {--}
73 #endif
74
75
76 -- SIGH: but we use unboxed "sizes"...
77 #if __GLASGOW_HASKELL__
78 #define IF_GHC(a,b) a
79 #else /* not GHC */
80 #define IF_GHC(a,b) b
81 #endif /* not GHC */
82 \end{code}
83
84
85 %************************************************************************
86 %*                                                                      *
87 \subsection{The signature of the module}
88 %*                                                                      *
89 %************************************************************************
90
91 \begin{code}
92 --      BUILDING
93 emptyFM         :: FiniteMap key elt
94 unitFM          :: key -> elt -> FiniteMap key elt
95 listToFM        :: (Ord key OUTPUTABLE_key) => [(key,elt)] -> FiniteMap key elt
96                         -- In the case of duplicates, the last is taken
97 bagToFM         :: (Ord key OUTPUTABLE_key) => Bag (key,elt) -> FiniteMap key elt
98                         -- In the case of duplicates, who knows which is taken
99
100 --      ADDING AND DELETING
101                    -- Throws away any previous binding
102                    -- In the list case, the items are added starting with the
103                    -- first one in the list
104 addToFM         :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> key -> elt  -> FiniteMap key elt
105 addListToFM     :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> [(key,elt)] -> FiniteMap key elt
106
107                    -- Combines with previous binding
108 addToFM_C       :: (Ord key OUTPUTABLE_key) => (elt -> elt -> elt)
109                            -> FiniteMap key elt -> key -> elt
110                            -> FiniteMap key elt
111 addListToFM_C   :: (Ord key OUTPUTABLE_key) => (elt -> elt -> elt)
112                            -> FiniteMap key elt -> [(key,elt)]
113                            -> FiniteMap key elt
114
115                    -- Deletion doesn't complain if you try to delete something
116                    -- which isn't there
117 delFromFM       :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> key   -> FiniteMap key elt
118 delListFromFM   :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> [key] -> FiniteMap key elt
119
120 --      COMBINING
121                    -- Bindings in right argument shadow those in the left
122 plusFM          :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> FiniteMap key elt
123                            -> FiniteMap key elt
124
125                    -- Combines bindings for the same thing with the given function
126 plusFM_C        :: (Ord key OUTPUTABLE_key) => (elt -> elt -> elt)
127                            -> FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt
128
129 minusFM         :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt
130                    -- (minusFM a1 a2) deletes from a1 any bindings which are bound in a2
131
132 intersectFM     :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt
133 intersectFM_C   :: (Ord key OUTPUTABLE_key) => (elt -> elt -> elt2)
134                            -> FiniteMap key elt -> FiniteMap key elt -> FiniteMap key elt2
135
136 --      MAPPING, FOLDING, FILTERING
137 foldFM          :: (key -> elt -> a -> a) -> a -> FiniteMap key elt -> a
138 mapFM           :: (key -> elt1 -> elt2) -> FiniteMap key elt1 -> FiniteMap key elt2
139 filterFM        :: (Ord key OUTPUTABLE_key) => (key -> elt -> Bool)
140                            -> FiniteMap key elt -> FiniteMap key elt
141
142
143 --      INTERROGATING
144 sizeFM          :: FiniteMap key elt -> Int
145 isEmptyFM       :: FiniteMap key elt -> Bool
146
147 elemFM          :: (Ord key OUTPUTABLE_key) => key -> FiniteMap key elt -> Bool
148 lookupFM        :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> key -> Maybe elt
149 lookupWithDefaultFM
150                 :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> elt -> key -> elt
151                 -- lookupWithDefaultFM supplies a "default" elt
152                 -- to return for an unmapped key
153
154 --      LISTIFYING
155 fmToList        :: FiniteMap key elt -> [(key,elt)]
156 keysFM          :: FiniteMap key elt -> [key]
157 eltsFM          :: FiniteMap key elt -> [elt]
158 \end{code}
159
160 %************************************************************************
161 %*                                                                      *
162 \subsection{The @FiniteMap@ data type, and building of same}
163 %*                                                                      *
164 %************************************************************************
165
166 Invariants about @FiniteMap@:
167 \begin{enumerate}
168 \item
169 all keys in a FiniteMap are distinct
170 \item
171 all keys in left  subtree are $<$ key in Branch and
172 all keys in right subtree are $>$ key in Branch
173 \item
174 size field of a Branch gives number of Branch nodes in the tree
175 \item
176 size of left subtree is differs from size of right subtree by a
177 factor of at most \tr{sIZE_RATIO}
178 \end{enumerate}
179
180 \begin{code}
181 data FiniteMap key elt
182   = EmptyFM
183   | Branch key elt              -- Key and elt stored here
184     IF_GHC(Int#,Int{-STRICT-})  -- Size >= 1
185     (FiniteMap key elt)         -- Children
186     (FiniteMap key elt)
187 \end{code}
188
189 \begin{code}
190 emptyFM = EmptyFM
191 {-
192 emptyFM
193   = Branch bottom bottom IF_GHC(0#,0) bottom bottom
194   where
195     bottom = panic "emptyFM"
196 -}
197
198 -- #define EmptyFM (Branch _ _ IF_GHC(0#,0) _ _)
199
200 unitFM key elt = Branch key elt IF_GHC(1#,1) emptyFM emptyFM
201
202 listToFM = addListToFM emptyFM
203
204 bagToFM = foldrBag (\(k,v) fm -> addToFM fm k v) emptyFM
205 \end{code}
206
207 %************************************************************************
208 %*                                                                      *
209 \subsection{Adding to and deleting from @FiniteMaps@}
210 %*                                                                      *
211 %************************************************************************
212
213 \begin{code}
214 addToFM fm key elt = addToFM_C (\ old new -> new) fm key elt
215
216 addToFM_C combiner EmptyFM key elt = unitFM key elt
217 addToFM_C combiner (Branch key elt size fm_l fm_r) new_key new_elt
218   = case compare new_key key of
219         LT -> mkBalBranch key elt (addToFM_C combiner fm_l new_key new_elt) fm_r
220         GT -> mkBalBranch key elt fm_l (addToFM_C combiner fm_r new_key new_elt)
221         EQ -> Branch new_key (combiner elt new_elt) size fm_l fm_r
222
223 addListToFM fm key_elt_pairs = addListToFM_C (\ old new -> new) fm key_elt_pairs
224
225 addListToFM_C combiner fm key_elt_pairs
226   = foldl add fm key_elt_pairs  -- foldl adds from the left
227   where
228     add fmap (key,elt) = addToFM_C combiner fmap key elt
229 \end{code}
230
231 \begin{code}
232 delFromFM EmptyFM del_key = emptyFM
233 delFromFM (Branch key elt size fm_l fm_r) del_key
234   = case compare del_key key of
235         GT -> mkBalBranch key elt fm_l (delFromFM fm_r del_key)
236         LT -> mkBalBranch key elt (delFromFM fm_l del_key) fm_r
237         EQ -> glueBal fm_l fm_r
238
239 delListFromFM fm keys = foldl delFromFM fm keys
240 \end{code}
241
242 %************************************************************************
243 %*                                                                      *
244 \subsection{Combining @FiniteMaps@}
245 %*                                                                      *
246 %************************************************************************
247
248 \begin{code}
249 plusFM_C combiner EmptyFM fm2 = fm2
250 plusFM_C combiner fm1 EmptyFM = fm1
251 plusFM_C combiner fm1 (Branch split_key elt2 _ left right)
252   = mkVBalBranch split_key new_elt
253                  (plusFM_C combiner lts left)
254                  (plusFM_C combiner gts right)
255   where
256     lts     = splitLT fm1 split_key
257     gts     = splitGT fm1 split_key
258     new_elt = case lookupFM fm1 split_key of
259                 Nothing   -> elt2
260                 Just elt1 -> combiner elt1 elt2
261
262 -- It's worth doing plusFM specially, because we don't need
263 -- to do the lookup in fm1.
264 -- FM2 over-rides FM1.
265
266 plusFM EmptyFM fm2 = fm2
267 plusFM fm1 EmptyFM = fm1
268 plusFM fm1 (Branch split_key elt1 _ left right)
269   = mkVBalBranch split_key elt1 (plusFM lts left) (plusFM gts right)
270   where
271     lts     = splitLT fm1 split_key
272     gts     = splitGT fm1 split_key
273
274 minusFM EmptyFM fm2 = emptyFM
275 minusFM fm1 EmptyFM = fm1
276 minusFM fm1 (Branch split_key elt _ left right)
277   = glueVBal (minusFM lts left) (minusFM gts right)
278         -- The two can be way different, so we need glueVBal
279   where
280     lts = splitLT fm1 split_key         -- NB gt and lt, so the equal ones
281     gts = splitGT fm1 split_key         -- are not in either.
282
283 intersectFM fm1 fm2 = intersectFM_C (\ left right -> right) fm1 fm2
284
285 intersectFM_C combiner fm1 EmptyFM = emptyFM
286 intersectFM_C combiner EmptyFM fm2 = emptyFM
287 intersectFM_C combiner fm1 (Branch split_key elt2 _ left right)
288
289   | maybeToBool maybe_elt1      -- split_elt *is* in intersection
290   = mkVBalBranch split_key (combiner elt1 elt2) (intersectFM_C combiner lts left)
291                                                 (intersectFM_C combiner gts right)
292
293   | otherwise                   -- split_elt is *not* in intersection
294   = glueVBal (intersectFM_C combiner lts left) (intersectFM_C combiner gts right)
295
296   where
297     lts = splitLT fm1 split_key         -- NB gt and lt, so the equal ones
298     gts = splitGT fm1 split_key         -- are not in either.
299
300     maybe_elt1 = lookupFM fm1 split_key
301     Just elt1  = maybe_elt1
302 \end{code}
303
304 %************************************************************************
305 %*                                                                      *
306 \subsection{Mapping, folding, and filtering with @FiniteMaps@}
307 %*                                                                      *
308 %************************************************************************
309
310 \begin{code}
311 foldFM k z EmptyFM = z
312 foldFM k z (Branch key elt _ fm_l fm_r)
313   = foldFM k (k key elt (foldFM k z fm_r)) fm_l
314
315 mapFM f EmptyFM = emptyFM
316 mapFM f (Branch key elt size fm_l fm_r)
317   = Branch key (f key elt) size (mapFM f fm_l) (mapFM f fm_r)
318
319 filterFM p EmptyFM = emptyFM
320 filterFM p (Branch key elt _ fm_l fm_r)
321   | p key elt           -- Keep the item
322   = mkVBalBranch key elt (filterFM p fm_l) (filterFM p fm_r)
323
324   | otherwise           -- Drop the item
325   = glueVBal (filterFM p fm_l) (filterFM p fm_r)
326 \end{code}
327
328 %************************************************************************
329 %*                                                                      *
330 \subsection{Interrogating @FiniteMaps@}
331 %*                                                                      *
332 %************************************************************************
333
334 \begin{code}
335 --{-# INLINE sizeFM #-}
336 sizeFM EmptyFM               = 0
337 sizeFM (Branch _ _ size _ _) = IF_GHC(I# size, size)
338
339 isEmptyFM fm = sizeFM fm == 0
340
341 lookupFM EmptyFM key = Nothing
342 lookupFM (Branch key elt _ fm_l fm_r) key_to_find
343   = case compare key_to_find key of
344         LT -> lookupFM fm_l key_to_find
345         GT -> lookupFM fm_r key_to_find
346         EQ -> Just elt
347
348 key `elemFM` fm
349   = case (lookupFM fm key) of { Nothing -> False; Just elt -> True }
350
351 lookupWithDefaultFM fm deflt key
352   = case (lookupFM fm key) of { Nothing -> deflt; Just elt -> elt }
353 \end{code}
354
355 %************************************************************************
356 %*                                                                      *
357 \subsection{Listifying @FiniteMaps@}
358 %*                                                                      *
359 %************************************************************************
360
361 \begin{code}
362 fmToList fm = foldFM (\ key elt rest -> (key,elt) : rest) [] fm
363 keysFM fm   = foldFM (\ key elt rest -> key : rest)       [] fm
364 eltsFM fm   = foldFM (\ key elt rest -> elt : rest)       [] fm
365 \end{code}
366
367
368 %************************************************************************
369 %*                                                                      *
370 \subsection{The implementation of balancing}
371 %*                                                                      *
372 %************************************************************************
373
374 %************************************************************************
375 %*                                                                      *
376 \subsubsection{Basic construction of a @FiniteMap@}
377 %*                                                                      *
378 %************************************************************************
379
380 @mkBranch@ simply gets the size component right.  This is the ONLY
381 (non-trivial) place the Branch object is built, so the ASSERTion
382 recursively checks consistency.  (The trivial use of Branch is in
383 @unitFM@.)
384
385 \begin{code}
386 sIZE_RATIO :: Int
387 sIZE_RATIO = 5
388
389 mkBranch :: (Ord key OUTPUTABLE_key)            -- Used for the assertion checking only
390          => Int
391          -> key -> elt
392          -> FiniteMap key elt -> FiniteMap key elt
393          -> FiniteMap key elt
394
395 mkBranch which key elt fm_l fm_r
396   = --ASSERT( left_ok && right_ok && balance_ok )
397 #if defined(DEBUG_FINITEMAPS)
398     if not ( left_ok && right_ok && balance_ok ) then
399         pprPanic ("mkBranch:"++show which) (vcat [ppr [left_ok, right_ok, balance_ok],
400                                        ppr key,
401                                        ppr fm_l,
402                                        ppr fm_r])
403     else
404 #endif
405     let
406         result = Branch key elt (unbox (1 + left_size + right_size)) fm_l fm_r
407     in
408 --    if sizeFM result <= 8 then
409         result
410 --    else
411 --      pprTrace ("mkBranch:"++(show which)) (ppr result) (
412 --      result
413 --      )
414   where
415     left_ok  = case fm_l of
416                 EmptyFM                  -> True
417                 Branch left_key _ _ _ _  -> let
418                                                 biggest_left_key = fst (findMax fm_l)
419                                             in
420                                             biggest_left_key < key
421     right_ok = case fm_r of
422                 EmptyFM                  -> True
423                 Branch right_key _ _ _ _ -> let
424                                                 smallest_right_key = fst (findMin fm_r)
425                                             in
426                                             key < smallest_right_key
427     balance_ok = True -- sigh
428 {- LATER:
429     balance_ok
430       = -- Both subtrees have one or no elements...
431         (left_size + right_size <= 1)
432 -- NO         || left_size == 0  -- ???
433 -- NO         || right_size == 0 -- ???
434         -- ... or the number of elements in a subtree does not exceed
435         -- sIZE_RATIO times the number of elements in the other subtree
436       || (left_size  * sIZE_RATIO >= right_size &&
437           right_size * sIZE_RATIO >= left_size)
438 -}
439
440     left_size  = sizeFM fm_l
441     right_size = sizeFM fm_r
442
443 #ifdef __GLASGOW_HASKELL__
444     unbox :: Int -> Int#
445     unbox (I# size) = size
446 #else
447     unbox :: Int -> Int
448     unbox x = x
449 #endif
450 \end{code}
451
452 %************************************************************************
453 %*                                                                      *
454 \subsubsection{{\em Balanced} construction of a @FiniteMap@}
455 %*                                                                      *
456 %************************************************************************
457
458 @mkBalBranch@ rebalances, assuming that the subtrees aren't too far
459 out of whack.
460
461 \begin{code}
462 mkBalBranch :: (Ord key OUTPUTABLE_key)
463             => key -> elt
464             -> FiniteMap key elt -> FiniteMap key elt
465             -> FiniteMap key elt
466
467 mkBalBranch key elt fm_L fm_R
468
469   | size_l + size_r < 2
470   = mkBranch 1{-which-} key elt fm_L fm_R
471
472   | size_r > sIZE_RATIO * size_l        -- Right tree too big
473   = case fm_R of
474         Branch _ _ _ fm_rl fm_rr
475                 | sizeFM fm_rl < 2 * sizeFM fm_rr -> single_L fm_L fm_R
476                 | otherwise                       -> double_L fm_L fm_R
477         -- Other case impossible
478
479   | size_l > sIZE_RATIO * size_r        -- Left tree too big
480   = case fm_L of
481         Branch _ _ _ fm_ll fm_lr
482                 | sizeFM fm_lr < 2 * sizeFM fm_ll -> single_R fm_L fm_R
483                 | otherwise                       -> double_R fm_L fm_R
484         -- Other case impossible
485
486   | otherwise                           -- No imbalance
487   = mkBranch 2{-which-} key elt fm_L fm_R
488
489   where
490     size_l   = sizeFM fm_L
491     size_r   = sizeFM fm_R
492
493     single_L fm_l (Branch key_r elt_r _ fm_rl fm_rr)
494         = mkBranch 3{-which-} key_r elt_r (mkBranch 4{-which-} key elt fm_l fm_rl) fm_rr
495
496     double_L fm_l (Branch key_r elt_r _ (Branch key_rl elt_rl _ fm_rll fm_rlr) fm_rr)
497         = mkBranch 5{-which-} key_rl elt_rl (mkBranch 6{-which-} key   elt   fm_l   fm_rll)
498                                  (mkBranch 7{-which-} key_r elt_r fm_rlr fm_rr)
499
500     single_R (Branch key_l elt_l _ fm_ll fm_lr) fm_r
501         = mkBranch 8{-which-} key_l elt_l fm_ll (mkBranch 9{-which-} key elt fm_lr fm_r)
502
503     double_R (Branch key_l elt_l _ fm_ll (Branch key_lr elt_lr _ fm_lrl fm_lrr)) fm_r
504         = mkBranch 10{-which-} key_lr elt_lr (mkBranch 11{-which-} key_l elt_l fm_ll  fm_lrl)
505                                  (mkBranch 12{-which-} key   elt   fm_lrr fm_r)
506 \end{code}
507
508
509 \begin{code}
510 mkVBalBranch :: (Ord key OUTPUTABLE_key)
511              => key -> elt
512              -> FiniteMap key elt -> FiniteMap key elt
513              -> FiniteMap key elt
514
515 -- Assert: in any call to (mkVBalBranch_C comb key elt l r),
516 --         (a) all keys in l are < all keys in r
517 --         (b) all keys in l are < key
518 --         (c) all keys in r are > key
519
520 mkVBalBranch key elt EmptyFM fm_r = addToFM fm_r key elt
521 mkVBalBranch key elt fm_l EmptyFM = addToFM fm_l key elt
522
523 mkVBalBranch key elt fm_l@(Branch key_l elt_l _ fm_ll fm_lr)
524                      fm_r@(Branch key_r elt_r _ fm_rl fm_rr)
525   | sIZE_RATIO * size_l < size_r
526   = mkBalBranch key_r elt_r (mkVBalBranch key elt fm_l fm_rl) fm_rr
527
528   | sIZE_RATIO * size_r < size_l
529   = mkBalBranch key_l elt_l fm_ll (mkVBalBranch key elt fm_lr fm_r)
530
531   | otherwise
532   = mkBranch 13{-which-} key elt fm_l fm_r
533
534   where
535     size_l = sizeFM fm_l
536     size_r = sizeFM fm_r
537 \end{code}
538
539 %************************************************************************
540 %*                                                                      *
541 \subsubsection{Gluing two trees together}
542 %*                                                                      *
543 %************************************************************************
544
545 @glueBal@ assumes its two arguments aren't too far out of whack, just
546 like @mkBalBranch@.  But: all keys in first arg are $<$ all keys in
547 second.
548
549 \begin{code}
550 glueBal :: (Ord key OUTPUTABLE_key)
551         => FiniteMap key elt -> FiniteMap key elt
552         -> FiniteMap key elt
553
554 glueBal EmptyFM fm2 = fm2
555 glueBal fm1 EmptyFM = fm1
556 glueBal fm1 fm2
557         -- The case analysis here (absent in Adams' program) is really to deal
558         -- with the case where fm2 is a singleton. Then deleting the minimum means
559         -- we pass an empty tree to mkBalBranch, which breaks its invariant.
560   | sizeFM fm2 > sizeFM fm1
561   = mkBalBranch mid_key2 mid_elt2 fm1 (deleteMin fm2)
562
563   | otherwise
564   = mkBalBranch mid_key1 mid_elt1 (deleteMax fm1) fm2
565   where
566     (mid_key1, mid_elt1) = findMax fm1
567     (mid_key2, mid_elt2) = findMin fm2
568 \end{code}
569
570 @glueVBal@ copes with arguments which can be of any size.
571 But: all keys in first arg are $<$ all keys in second.
572
573 \begin{code}
574 glueVBal :: (Ord key OUTPUTABLE_key)
575          => FiniteMap key elt -> FiniteMap key elt
576          -> FiniteMap key elt
577
578 glueVBal EmptyFM fm2 = fm2
579 glueVBal fm1 EmptyFM = fm1
580 glueVBal fm_l@(Branch key_l elt_l _ fm_ll fm_lr)
581          fm_r@(Branch key_r elt_r _ fm_rl fm_rr)
582   | sIZE_RATIO * size_l < size_r
583   = mkBalBranch key_r elt_r (glueVBal fm_l fm_rl) fm_rr
584
585   | sIZE_RATIO * size_r < size_l
586   = mkBalBranch key_l elt_l fm_ll (glueVBal fm_lr fm_r)
587
588   | otherwise           -- We now need the same two cases as in glueBal above.
589   = glueBal fm_l fm_r
590   where
591     (mid_key_l,mid_elt_l) = findMax fm_l
592     (mid_key_r,mid_elt_r) = findMin fm_r
593     size_l = sizeFM fm_l
594     size_r = sizeFM fm_r
595 \end{code}
596
597 %************************************************************************
598 %*                                                                      *
599 \subsection{Local utilities}
600 %*                                                                      *
601 %************************************************************************
602
603 \begin{code}
604 splitLT, splitGT :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> key -> FiniteMap key elt
605
606 -- splitLT fm split_key  =  fm restricted to keys <  split_key
607 -- splitGT fm split_key  =  fm restricted to keys >  split_key
608
609 splitLT EmptyFM split_key = emptyFM
610 splitLT (Branch key elt _ fm_l fm_r) split_key
611   = case compare split_key key of
612         LT -> splitLT fm_l split_key
613         GT -> mkVBalBranch key elt fm_l (splitLT fm_r split_key)
614         EQ -> fm_l
615
616 splitGT EmptyFM split_key = emptyFM
617 splitGT (Branch key elt _ fm_l fm_r) split_key
618   = case compare split_key key of
619         GT -> splitGT fm_r split_key
620         LT -> mkVBalBranch key elt (splitGT fm_l split_key) fm_r
621         EQ -> fm_r
622
623 findMin :: FiniteMap key elt -> (key,elt)
624 findMin (Branch key elt _ EmptyFM _) = (key,elt)
625 findMin (Branch key elt _ fm_l    _) = findMin fm_l
626
627 deleteMin :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> FiniteMap key elt
628 deleteMin (Branch key elt _ EmptyFM fm_r) = fm_r
629 deleteMin (Branch key elt _ fm_l    fm_r) = mkBalBranch key elt (deleteMin fm_l) fm_r
630
631 findMax :: FiniteMap key elt -> (key,elt)
632 findMax (Branch key elt _ _ EmptyFM) = (key,elt)
633 findMax (Branch key elt _ _    fm_r) = findMax fm_r
634
635 deleteMax :: (Ord key OUTPUTABLE_key) => FiniteMap key elt -> FiniteMap key elt
636 deleteMax (Branch key elt _ fm_l EmptyFM) = fm_l
637 deleteMax (Branch key elt _ fm_l    fm_r) = mkBalBranch key elt fm_l (deleteMax fm_r)
638 \end{code}
639
640 %************************************************************************
641 %*                                                                      *
642 \subsection{Output-ery}
643 %*                                                                      *
644 %************************************************************************
645
646 \begin{code}
647 #if defined(DEBUG_FINITEMAPS)
648
649 instance (Outputable key) => Outputable (FiniteMap key elt) where
650     ppr fm = pprX fm
651
652 pprX EmptyFM = char '!'
653 pprX (Branch key elt sz fm_l fm_r)
654  = parens (hcat [pprX fm_l, space,
655                       ppr key, space, int (IF_GHC(I# sz, sz)), space,
656                       pprX fm_r])
657 #endif
658
659 #if 0
660 instance (Eq key, Eq elt) => Eq (FiniteMap key elt) where
661   fm_1 == fm_2 = (sizeFM   fm_1 == sizeFM   fm_2) &&   -- quick test
662                  (fmToList fm_1 == fmToList fm_2)
663
664 {- NO: not clear what The Right Thing to do is:
665 instance (Ord key, Ord elt) => Ord (FiniteMap key elt) where
666   fm_1 <= fm_2 = (sizeFM   fm_1 <= sizeFM   fm_2) &&   -- quick test
667                  (fmToList fm_1 <= fmToList fm_2)
668 -}
669 #endif
670 \end{code}
671
672 %************************************************************************
673 %*                                                                      *
674 \subsection{FiniteSets---a thin veneer}
675 %*                                                                      *
676 %************************************************************************
677
678 \begin{code}
679 type FiniteSet key = FiniteMap key ()
680 emptySet        :: FiniteSet key
681 mkSet           :: (Ord key OUTPUTABLE_key) => [key] -> FiniteSet key
682 isEmptySet      :: FiniteSet key -> Bool
683 elementOf       :: (Ord key OUTPUTABLE_key) => key -> FiniteSet key -> Bool
684 minusSet        :: (Ord key OUTPUTABLE_key) => FiniteSet key -> FiniteSet key -> FiniteSet key
685 setToList       :: FiniteSet key -> [key]
686 union           :: (Ord key OUTPUTABLE_key) => FiniteSet key -> FiniteSet key -> FiniteSet key
687
688 emptySet = emptyFM
689 mkSet xs = listToFM [ (x, ()) | x <- xs]
690 isEmptySet = isEmptyFM
691 elementOf = elemFM
692 minusSet  = minusFM
693 setToList = keysFM
694 union = plusFM
695
696 \end{code}
697
698 %************************************************************************
699 %*                                                                      *
700 \subsection{Efficiency pragmas for GHC}
701 %*                                                                      *
702 %************************************************************************
703
704 When the FiniteMap module is used in GHC, we specialise it for
705 \tr{Uniques}, for dastardly efficiency reasons.
706
707 \begin{code}
708 #if __GLASGOW_HASKELL__ && !defined(REALLY_HASKELL_1_3)
709
710 {-# SPECIALIZE addListToFM
711                 :: FiniteMap (FAST_STRING, FAST_STRING) elt -> [((FAST_STRING, FAST_STRING),elt)] -> FiniteMap (FAST_STRING, FAST_STRING) elt
712                  , FiniteMap RdrName elt -> [(RdrName,elt)] -> FiniteMap RdrName elt
713     IF_NCG(COMMA   FiniteMap Reg elt -> [(Reg COMMA elt)] -> FiniteMap Reg elt)
714     #-}
715 {-# SPECIALIZE addListToFM_C
716                 :: (elt -> elt -> elt) -> FiniteMap TyCon elt -> [(TyCon,elt)] -> FiniteMap TyCon elt
717                  , (elt -> elt -> elt) -> FiniteMap FAST_STRING elt -> [(FAST_STRING,elt)] -> FiniteMap FAST_STRING elt
718     IF_NCG(COMMA   (elt -> elt -> elt) -> FiniteMap Reg elt -> [(Reg COMMA elt)] -> FiniteMap Reg elt)
719     #-}
720 {-# SPECIALIZE addToFM
721                 :: FiniteMap CLabel elt -> CLabel -> elt  -> FiniteMap CLabel elt
722                  , FiniteMap FAST_STRING elt -> FAST_STRING -> elt  -> FiniteMap FAST_STRING elt
723                  , FiniteMap (FAST_STRING, FAST_STRING) elt -> (FAST_STRING, FAST_STRING) -> elt  -> FiniteMap (FAST_STRING, FAST_STRING) elt
724                  , FiniteMap RdrName elt -> RdrName -> elt  -> FiniteMap RdrName elt
725     IF_NCG(COMMA   FiniteMap Reg elt -> Reg -> elt  -> FiniteMap Reg elt)
726     #-}
727 {-# SPECIALIZE addToFM_C
728                 :: (elt -> elt -> elt) -> FiniteMap (RdrName, RdrName) elt -> (RdrName, RdrName) -> elt -> FiniteMap (RdrName, RdrName) elt
729                  , (elt -> elt -> elt) -> FiniteMap FAST_STRING elt -> FAST_STRING -> elt -> FiniteMap FAST_STRING elt
730     IF_NCG(COMMA   (elt -> elt -> elt) -> FiniteMap Reg elt -> Reg -> elt -> FiniteMap Reg elt)
731     #-}
732 {-# SPECIALIZE bagToFM
733                 :: Bag (FAST_STRING,elt) -> FiniteMap FAST_STRING elt
734     #-}
735 {-# SPECIALIZE delListFromFM
736                 :: FiniteMap RdrName elt -> [RdrName]   -> FiniteMap RdrName elt
737                  , FiniteMap FAST_STRING elt -> [FAST_STRING]   -> FiniteMap FAST_STRING elt
738     IF_NCG(COMMA   FiniteMap Reg elt -> [Reg]   -> FiniteMap Reg elt)
739     #-}
740 {-# SPECIALIZE listToFM
741                 :: [([Char],elt)] -> FiniteMap [Char] elt
742                  , [(FAST_STRING,elt)] -> FiniteMap FAST_STRING elt
743                  , [((FAST_STRING,FAST_STRING),elt)] -> FiniteMap (FAST_STRING, FAST_STRING) elt
744     IF_NCG(COMMA   [(Reg COMMA elt)] -> FiniteMap Reg elt)
745     #-}
746 {-# SPECIALIZE lookupFM
747                 :: FiniteMap CLabel elt -> CLabel -> Maybe elt
748                  , FiniteMap [Char] elt -> [Char] -> Maybe elt
749                  , FiniteMap FAST_STRING elt -> FAST_STRING -> Maybe elt
750                  , FiniteMap (FAST_STRING,FAST_STRING) elt -> (FAST_STRING,FAST_STRING) -> Maybe elt
751                  , FiniteMap RdrName elt -> RdrName -> Maybe elt
752                  , FiniteMap (RdrName,RdrName) elt -> (RdrName,RdrName) -> Maybe elt
753     IF_NCG(COMMA   FiniteMap Reg elt -> Reg -> Maybe elt)
754     #-}
755 {-# SPECIALIZE lookupWithDefaultFM
756                 :: FiniteMap FAST_STRING elt -> elt -> FAST_STRING -> elt
757     IF_NCG(COMMA   FiniteMap Reg elt -> elt -> Reg -> elt)
758     #-}
759 {-# SPECIALIZE plusFM
760                 :: FiniteMap RdrName elt -> FiniteMap RdrName elt -> FiniteMap RdrName elt
761                  , FiniteMap FAST_STRING elt -> FiniteMap FAST_STRING elt -> FiniteMap FAST_STRING elt
762     IF_NCG(COMMA   FiniteMap Reg elt -> FiniteMap Reg elt -> FiniteMap Reg elt)
763     #-}
764 {-# SPECIALIZE plusFM_C
765                 :: (elt -> elt -> elt) -> FiniteMap FAST_STRING elt -> FiniteMap FAST_STRING elt -> FiniteMap FAST_STRING elt
766     IF_NCG(COMMA   (elt -> elt -> elt) -> FiniteMap Reg elt -> FiniteMap Reg elt -> FiniteMap Reg elt)
767     #-}
768
769 #endif {- compiling with ghc and have specialiser -}
770 \end{code}