2 % (c) The AQUA Project, Glasgow University, 1994-1996
4 \section[UniqFM]{Specialised finite maps, for things with @Uniques@}
6 Based on @FiniteMaps@ (as you would expect).
8 Basically, the things need to be in class @Uniquable@, and we use the
9 @uniqueOf@ method to grab their @Uniques@.
11 (A similar thing to @UniqSet@, as opposed to @Set@.)
15 UniqFM, -- abstract type
23 addListToUFM,addListToUFM_C,
25 addListToUFM_Directly,
39 lookupUFM, lookupUFM_Directly,
40 lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
46 #include "HsVersions.h"
48 import {-# SOURCE #-} Name ( Name )
50 import Unique ( Uniquable(..), Unique, u2i, mkUniqueGrimily )
52 import GlaExts -- Lots of Int# operations
54 #if ! OMIT_NATIVE_CODEGEN
57 #define IF_NCG(a) {--}
61 %************************************************************************
63 \subsection{The @UniqFM@ type, and signatures for the functions}
65 %************************************************************************
67 We use @FiniteMaps@, with a (@uniqueOf@-able) @Unique@ as ``key''.
70 emptyUFM :: UniqFM elt
71 isNullUFM :: UniqFM elt -> Bool
72 unitUFM :: Uniquable key => key -> elt -> UniqFM elt
73 unitDirectlyUFM -- got the Unique already
74 :: Unique -> elt -> UniqFM elt
75 listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
77 :: [(Unique, elt)] -> UniqFM elt
79 addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
80 addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
82 :: UniqFM elt -> Unique -> elt -> UniqFM elt
84 addToUFM_C :: Uniquable key => (elt -> elt -> elt)
85 -> UniqFM elt -> key -> elt -> UniqFM elt
86 addListToUFM_C :: Uniquable key => (elt -> elt -> elt)
87 -> UniqFM elt -> [(key,elt)]
90 delFromUFM :: Uniquable key => UniqFM elt -> key -> UniqFM elt
91 delListFromUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
92 delFromUFM_Directly :: UniqFM elt -> Unique -> UniqFM elt
94 plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
96 plusUFM_C :: (elt -> elt -> elt)
97 -> UniqFM elt -> UniqFM elt -> UniqFM elt
99 minusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
101 intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
102 intersectUFM_C :: (elt -> elt -> elt)
103 -> UniqFM elt -> UniqFM elt -> UniqFM elt
104 foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
105 mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
106 filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
108 sizeUFM :: UniqFM elt -> Int
110 lookupUFM :: Uniquable key => UniqFM elt -> key -> Maybe elt
111 lookupUFM_Directly -- when you've got the Unique already
112 :: UniqFM elt -> Unique -> Maybe elt
114 :: Uniquable key => UniqFM elt -> elt -> key -> elt
115 lookupWithDefaultUFM_Directly
116 :: UniqFM elt -> elt -> Unique -> elt
118 keysUFM :: UniqFM elt -> [Int] -- Get the keys
119 eltsUFM :: UniqFM elt -> [elt]
120 ufmToList :: UniqFM elt -> [(Unique, elt)]
123 %************************************************************************
125 \subsection{The @IdFinMap@ and @TyVarFinMap@ specialisations for Ids/TyVars}
127 %************************************************************************
130 #ifdef __GLASGOW_HASKELL__
131 -- I don't think HBC was too happy about this (WDP 94/10)
134 addListToUFM :: UniqFM elt -> [(Name, elt)] -> UniqFM elt
137 addListToUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Name, elt)] -> UniqFM elt
140 addToUFM :: UniqFM elt -> Unique -> elt -> UniqFM elt
143 listToUFM :: [(Unique, elt)] -> UniqFM elt
146 lookupUFM :: UniqFM elt -> Name -> Maybe elt
147 , UniqFM elt -> Unique -> Maybe elt
150 #endif {- __GLASGOW_HASKELL__ -}
153 %************************************************************************
155 \subsection{Andy Gill's underlying @UniqFM@ machinery}
157 %************************************************************************
159 ``Uniq Finite maps'' are the heart and soul of the compiler's
160 lookup-tables/environments. Important stuff! It works well with
161 Dense and Sparse ranges.
162 Both @Uq@ Finite maps and @Hash@ Finite Maps
163 are built ontop of Int Finite Maps.
165 This code is explained in the paper:
167 A Gill, S Peyton Jones, B O'Sullivan, W Partain and Aqua Friends
168 "A Cheap balancing act that grows on a tree"
169 Glasgow FP Workshop, Sep 1994, pp??-??
172 %************************************************************************
174 \subsubsection{The @UniqFM@ type, and signatures for the functions}
176 %************************************************************************
178 @UniqFM a@ is a mapping from Unique to a.
180 First, the DataType itself; which is either a Node, a Leaf, or an Empty.
185 | LeafUFM FAST_INT ele
186 | NodeUFM FAST_INT -- the switching
187 FAST_INT -- the delta
191 -- for debugging only :-)
193 instance Text (UniqFM a) where
194 showsPrec _ (NodeUFM a b t1 t2) =
195 showString "NodeUFM " . shows (IBOX(a))
196 . showString " " . shows (IBOX(b))
197 . showString " (" . shows t1
198 . showString ") (" . shows t2
200 showsPrec _ (LeafUFM x a) = showString "LeafUFM " . shows (IBOX(x))
201 showsPrec _ (EmptyUFM) = id
205 %************************************************************************
207 \subsubsection{The @UniqFM@ functions}
209 %************************************************************************
211 First the ways of building a UniqFM.
215 unitUFM key elt = mkLeafUFM (u2i (uniqueOf key)) elt
216 unitDirectlyUFM key elt = mkLeafUFM (u2i key) elt
218 listToUFM key_elt_pairs
219 = addListToUFM_C use_snd EmptyUFM key_elt_pairs
221 listToUFM_Directly uniq_elt_pairs
222 = addListToUFM_directly_C use_snd EmptyUFM uniq_elt_pairs
225 Now ways of adding things to UniqFMs.
227 There is an alternative version of @addListToUFM_C@, that uses @plusUFM@,
228 but the semantics of this operation demands a linear insertion;
229 perhaps the version without the combinator function
230 could be optimised using it.
233 addToUFM fm key elt = addToUFM_C use_snd fm key elt
235 addToUFM_Directly fm u elt = insert_ele use_snd fm (u2i u) elt
237 addToUFM_C combiner fm key elt
238 = insert_ele combiner fm (u2i (uniqueOf key)) elt
240 addListToUFM fm key_elt_pairs = addListToUFM_C use_snd fm key_elt_pairs
241 addListToUFM_Directly fm uniq_elt_pairs = addListToUFM_directly_C use_snd fm uniq_elt_pairs
243 addListToUFM_C combiner fm key_elt_pairs
244 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i (uniqueOf k)) e)
247 addListToUFM_directly_C combiner fm uniq_elt_pairs
248 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i k) e)
252 Now ways of removing things from UniqFM.
255 delListFromUFM fm lst = foldl delFromUFM fm lst
257 delFromUFM fm key = delete fm (u2i (uniqueOf key))
258 delFromUFM_Directly fm u = delete fm (u2i u)
260 delete EmptyUFM _ = EmptyUFM
261 delete fm key = del_ele fm
263 del_ele :: UniqFM a -> UniqFM a
265 del_ele lf@(LeafUFM j _)
266 | j _EQ_ key = EmptyUFM
267 | otherwise = lf -- no delete!
269 del_ele nd@(NodeUFM j p t1 t2)
271 = mkSLNodeUFM (NodeUFMData j p) (del_ele t1) t2
273 = mkLSNodeUFM (NodeUFMData j p) t1 (del_ele t2)
275 del_ele _ = panic "Found EmptyUFM FM when rec-deleting"
278 Now ways of adding two UniqFM's together.
281 plusUFM tr1 tr2 = plusUFM_C use_snd tr1 tr2
283 plusUFM_C f EmptyUFM tr = tr
284 plusUFM_C f tr EmptyUFM = tr
285 plusUFM_C f fm1 fm2 = mix_trees fm1 fm2
287 mix_trees (LeafUFM i a) t2 = insert_ele (flip f) t2 i a
288 mix_trees t1 (LeafUFM i a) = insert_ele f t1 i a
290 mix_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
292 (ask_about_common_ancestor
296 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
300 -- t1 t2 t1' t2' j j'
305 mix_branches (NewRoot nd False)
306 = mkLLNodeUFM nd left_t right_t
307 mix_branches (NewRoot nd True)
308 = mkLLNodeUFM nd right_t left_t
314 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
316 mix_branches (SameRoot)
317 = mkSSNodeUFM (NodeUFMData j p)
320 -- Now the 4 different other ways; all like this:
322 -- Given j >^ j' (and, say, j > j')
326 -- t1 t2 t1' t2' t1 t2 + j'
329 mix_branches (LeftRoot Leftt) -- | trace "LL" True
332 (mix_trees t1 right_t)
335 mix_branches (LeftRoot Rightt) -- | trace "LR" True
339 (mix_trees t2 right_t)
341 mix_branches (RightRoot Leftt) -- | trace "RL" True
344 (mix_trees left_t t1')
347 mix_branches (RightRoot Rightt) -- | trace "RR" True
351 (mix_trees left_t t2')
353 mix_trees _ _ = panic "EmptyUFM found when inserting into plusInt"
356 And ways of subtracting them. First the base cases,
357 then the full D&C approach.
360 minusUFM EmptyUFM _ = EmptyUFM
361 minusUFM t1 EmptyUFM = t1
362 minusUFM fm1 fm2 = minus_trees fm1 fm2
365 -- Notice the asymetry of subtraction
367 minus_trees lf@(LeafUFM i a) t2 =
372 minus_trees t1 (LeafUFM i _) = delete t1 i
374 minus_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
376 (ask_about_common_ancestor
380 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
384 -- t1 t2 t1' t2' t1 t2
389 minus_branches (NewRoot nd _) = left_t
395 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
397 minus_branches (SameRoot)
398 = mkSSNodeUFM (NodeUFMData j p)
401 -- Now the 4 different other ways; all like this:
402 -- again, with asymatry
405 -- The left is above the right
407 minus_branches (LeftRoot Leftt)
410 (minus_trees t1 right_t)
412 minus_branches (LeftRoot Rightt)
416 (minus_trees t2 right_t)
419 -- The right is above the left
421 minus_branches (RightRoot Leftt)
422 = minus_trees left_t t1'
423 minus_branches (RightRoot Rightt)
424 = minus_trees left_t t2'
426 minus_trees _ _ = panic "EmptyUFM found when insering into plusInt"
429 And taking the intersection of two UniqFM's.
432 intersectUFM t1 t2 = intersectUFM_C use_snd t1 t2
434 intersectUFM_C f EmptyUFM _ = EmptyUFM
435 intersectUFM_C f _ EmptyUFM = EmptyUFM
436 intersectUFM_C f fm1 fm2 = intersect_trees fm1 fm2
438 intersect_trees (LeafUFM i a) t2 =
441 Just b -> mkLeafUFM i (f a b)
443 intersect_trees t1 (LeafUFM i a) =
446 Just b -> mkLeafUFM i (f b a)
448 intersect_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
450 (ask_about_common_ancestor
454 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
457 -- / \ + / \ ==> EmptyUFM
462 intersect_branches (NewRoot nd _) = EmptyUFM
468 -- t1 t2 t1' t2' t1 x t1' t2 x t2'
470 intersect_branches (SameRoot)
471 = mkSSNodeUFM (NodeUFMData j p)
472 (intersect_trees t1 t1')
473 (intersect_trees t2 t2')
474 -- Now the 4 different other ways; all like this:
476 -- Given j >^ j' (and, say, j > j')
480 -- t1 t2 t1' t2' t1' t2'
482 -- This does cut down the search space quite a bit.
484 intersect_branches (LeftRoot Leftt)
485 = intersect_trees t1 right_t
486 intersect_branches (LeftRoot Rightt)
487 = intersect_trees t2 right_t
488 intersect_branches (RightRoot Leftt)
489 = intersect_trees left_t t1'
490 intersect_branches (RightRoot Rightt)
491 = intersect_trees left_t t2'
493 intersect_trees x y = panic ("EmptyUFM found when intersecting trees")
496 Now the usual set of `collection' operators, like map, fold, etc.
499 foldUFM f a (NodeUFM _ _ t1 t2) = foldUFM f (foldUFM f a t2) t1
500 foldUFM f a (LeafUFM _ obj) = f obj a
501 foldUFM f a EmptyUFM = a
505 mapUFM fn EmptyUFM = EmptyUFM
506 mapUFM fn fm = map_tree fn fm
508 filterUFM fn EmptyUFM = EmptyUFM
509 filterUFM fn fm = filter_tree fn fm
512 Note, this takes a long time, O(n), but
513 because we dont want to do this very often, we put up with this.
514 O'rable, but how often do we look at the size of
519 sizeUFM (NodeUFM _ _ t1 t2) = sizeUFM t1 + sizeUFM t2
520 sizeUFM (LeafUFM _ _) = 1
522 isNullUFM EmptyUFM = True
526 looking up in a hurry is the {\em whole point} of this binary tree lark.
527 Lookup up a binary tree is easy (and fast).
530 lookupUFM fm key = lookUp fm (u2i (uniqueOf key))
531 lookupUFM_Directly fm key = lookUp fm (u2i key)
533 lookupWithDefaultUFM fm deflt key
534 = case lookUp fm (u2i (uniqueOf key)) of
538 lookupWithDefaultUFM_Directly fm deflt key
539 = case lookUp fm (u2i key) of
543 lookUp EmptyUFM _ = Nothing
544 lookUp fm i = lookup_tree fm
546 lookup_tree :: UniqFM a -> Maybe a
548 lookup_tree (LeafUFM j b)
550 | otherwise = Nothing
551 lookup_tree (NodeUFM j p t1 t2)
552 | j _GT_ i = lookup_tree t1
553 | otherwise = lookup_tree t2
555 lookup_tree EmptyUFM = panic "lookup Failed"
558 folds are *wonderful* things.
561 eltsUFM fm = foldUFM (:) [] fm
563 ufmToList fm = fold_tree (\ iu elt rest -> (mkUniqueGrimily iu, elt) : rest) [] fm
565 keysUFM fm = fold_tree (\ iu elt rest -> IBOX(iu) : rest) [] fm
567 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
568 fold_tree f a (LeafUFM iu obj) = f iu obj a
569 fold_tree f a EmptyUFM = a
572 %************************************************************************
574 \subsubsection{The @UniqFM@ type, and its functions}
576 %************************************************************************
578 You should always use these to build the tree.
579 There are 4 versions of mkNodeUFM, depending on
580 the strictness of the two sub-tree arguments.
581 The strictness is used *both* to prune out
582 empty trees, *and* to improve performance,
583 stoping needless thunks lying around.
584 The rule of thumb (from experence with these trees)
585 is make thunks strict, but data structures lazy.
586 If in doubt, use mkSSNodeUFM, which has the `strongest'
587 functionality, but may do a few needless evaluations.
590 mkLeafUFM :: FAST_INT -> a -> UniqFM a
591 mkLeafUFM i a = LeafUFM i a
593 -- The *ONLY* ways of building a NodeUFM.
595 mkSSNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
596 mkSSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
597 mkSSNodeUFM (NodeUFMData j p) t1 t2
598 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
601 mkSLNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
602 mkSLNodeUFM (NodeUFMData j p) t1 t2
603 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
606 mkLSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
607 mkLSNodeUFM (NodeUFMData j p) t1 t2
608 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
611 mkLLNodeUFM (NodeUFMData j p) t1 t2
612 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
622 correctNodeUFM j p t1 t2
623 = correct (j-p) (j-1) p t1 && correct j ((j-1)+p) p t2
625 correct low high _ (LeafUFM i _)
626 = low <= IBOX(i) && IBOX(i) <= high
627 correct low high above_p (NodeUFM j p _ _)
628 = low <= IBOX(j) && IBOX(j) <= high && above_p > IBOX(p)
629 correct _ _ _ EmptyUFM = panic "EmptyUFM stored inside a tree"
632 Note: doing SAT on this by hand seems to make it worse. Todo: Investigate,
633 and if necessary do $\lambda$ lifting on our functions that are bound.
643 insert_ele f EmptyUFM i new = mkLeafUFM i new
645 insert_ele f (LeafUFM j old) i new
647 mkLLNodeUFM (getCommonNodeUFMData
652 | j _EQ_ i = mkLeafUFM j (f old new)
654 mkLLNodeUFM (getCommonNodeUFMData
660 insert_ele f n@(NodeUFM j p t1 t2) i a
662 = if (i _GE_ (j _SUB_ p))
663 then mkSLNodeUFM (NodeUFMData j p) (insert_ele f t1 i a) t2
664 else mkLLNodeUFM (getCommonNodeUFMData
670 = if (i _LE_ ((j _SUB_ ILIT(1)) _ADD_ p))
671 then mkLSNodeUFM (NodeUFMData j p) t1 (insert_ele f t2 i a)
672 else mkLLNodeUFM (getCommonNodeUFMData
682 map_tree f (NodeUFM j p t1 t2)
683 = mkSSNodeUFM (NodeUFMData j p) (map_tree f t1) (map_tree f t2)
684 map_tree f (LeafUFM i obj)
685 = mkLeafUFM i (f obj)
687 map_tree f _ = panic "map_tree failed"
691 filter_tree f nd@(NodeUFM j p t1 t2)
692 = mkSSNodeUFM (NodeUFMData j p) (filter_tree f t1) (filter_tree f t2)
694 filter_tree f lf@(LeafUFM i obj)
696 | otherwise = EmptyUFM
697 filter_tree f _ = panic "filter_tree failed"
700 %************************************************************************
702 \subsubsection{The @UniqFM@ type, and signatures for the functions}
704 %************************************************************************
708 This is the information that is held inside a NodeUFM, packaged up for
713 = NodeUFMData FAST_INT
717 This is the information used when computing new NodeUFMs.
720 data Side = Leftt | Rightt -- NB: avoid 1.3 names "Left" and "Right"
722 = LeftRoot Side -- which side is the right down ?
723 | RightRoot Side -- which side is the left down ?
724 | SameRoot -- they are the same !
725 | NewRoot NodeUFMData -- here's the new, common, root
726 Bool -- do you need to swap left and right ?
729 This specifies the relationship between NodeUFMData and CalcNodeUFMData.
732 indexToRoot :: FAST_INT -> NodeUFMData
736 l = (ILIT(1) :: FAST_INT)
738 NodeUFMData (((i `shiftR_` l) `shiftL_` l) _ADD_ ILIT(1)) l
740 getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData
742 getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
743 | p _EQ_ p2 = getCommonNodeUFMData_ p j j2
744 | p _LT_ p2 = getCommonNodeUFMData_ p2 (j _QUOT_ (p2 _QUOT_ p)) j2
745 | otherwise = getCommonNodeUFMData_ p j (j2 _QUOT_ (p _QUOT_ p2))
747 l = (ILIT(1) :: FAST_INT)
748 j = i _QUOT_ (p `shiftL_` l)
749 j2 = i2 _QUOT_ (p2 `shiftL_` l)
751 getCommonNodeUFMData_ :: FAST_INT -> FAST_INT -> FAST_INT -> NodeUFMData
753 getCommonNodeUFMData_ p j j_
755 = NodeUFMData (((j `shiftL_` l) _ADD_ l) _MUL_ p) p
757 = getCommonNodeUFMData_ (p `shiftL_` l) (j `shiftR_` l) (j_ `shiftR_` l)
759 ask_about_common_ancestor :: NodeUFMData -> NodeUFMData -> CommonRoot
761 ask_about_common_ancestor x@(NodeUFMData j p) y@(NodeUFMData j2 p2)
762 | j _EQ_ j2 = SameRoot
764 = case getCommonNodeUFMData x y of
765 nd@(NodeUFMData j3 p3)
766 | j3 _EQ_ j -> LeftRoot (decideSide (j _GT_ j2))
767 | j3 _EQ_ j2 -> RightRoot (decideSide (j _LT_ j2))
768 | otherwise -> NewRoot nd (j _GT_ j2)
770 decideSide :: Bool -> Side
771 decideSide True = Leftt
772 decideSide False = Rightt
775 This might be better in Util.lhs ?
778 Now the bit twiddling functions.
780 shiftL_ :: FAST_INT -> FAST_INT -> FAST_INT
781 shiftR_ :: FAST_INT -> FAST_INT -> FAST_INT
783 #if __GLASGOW_HASKELL__
784 {-# INLINE shiftL_ #-}
785 {-# INLINE shiftR_ #-}
786 shiftL_ n p = word2Int#((int2Word# n) `shiftL#` p)
787 shiftR_ n p = word2Int#((int2Word# n) `shiftr` p)
789 shiftr x y = shiftRA# x y
792 shiftL_ n p = n * (2 ^ p)
793 shiftR_ n p = n `quot` (2 ^ p)
799 use_snd :: a -> b -> b