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