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,
40 lookupUFM, lookupUFM_Directly,
41 lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
47 #include "HsVersions.h"
49 import {-# SOURCE #-} Name ( Name )
51 import Unique ( Uniquable(..), Unique, u2i, mkUniqueGrimily )
53 import GlaExts -- Lots of Int# operations
55 #if ! OMIT_NATIVE_CODEGEN
58 #define IF_NCG(a) {--}
62 %************************************************************************
64 \subsection{The @UniqFM@ type, and signatures for the functions}
66 %************************************************************************
68 We use @FiniteMaps@, with a (@uniqueOf@-able) @Unique@ as ``key''.
71 emptyUFM :: UniqFM elt
72 isNullUFM :: UniqFM elt -> Bool
73 unitUFM :: Uniquable key => key -> elt -> UniqFM elt
74 unitDirectlyUFM -- got the Unique already
75 :: Unique -> elt -> UniqFM elt
76 listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
78 :: [(Unique, elt)] -> UniqFM elt
80 addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
81 addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
83 :: UniqFM elt -> Unique -> elt -> UniqFM elt
85 addToUFM_C :: Uniquable key => (elt -> elt -> elt)
86 -> UniqFM elt -> key -> elt -> UniqFM elt
87 addListToUFM_C :: Uniquable key => (elt -> elt -> elt)
88 -> UniqFM elt -> [(key,elt)]
91 delFromUFM :: Uniquable key => UniqFM elt -> key -> UniqFM elt
92 delListFromUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
93 delFromUFM_Directly :: UniqFM elt -> Unique -> UniqFM elt
95 plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
97 plusUFM_C :: (elt -> elt -> elt)
98 -> UniqFM elt -> UniqFM elt -> UniqFM elt
100 minusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
102 intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
103 intersectUFM_C :: (elt -> elt -> elt)
104 -> UniqFM elt -> UniqFM elt -> UniqFM elt
105 foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
106 mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
107 filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
109 sizeUFM :: UniqFM elt -> Int
110 elemUFM :: Uniquable key => key -> UniqFM elt -> Bool
112 lookupUFM :: Uniquable key => UniqFM elt -> key -> Maybe elt
113 lookupUFM_Directly -- when you've got the Unique already
114 :: UniqFM elt -> Unique -> Maybe elt
116 :: Uniquable key => UniqFM elt -> elt -> key -> elt
117 lookupWithDefaultUFM_Directly
118 :: UniqFM elt -> elt -> Unique -> elt
120 keysUFM :: UniqFM elt -> [Int] -- Get the keys
121 eltsUFM :: UniqFM elt -> [elt]
122 ufmToList :: UniqFM elt -> [(Unique, elt)]
125 %************************************************************************
127 \subsection{The @IdFinMap@ and @TyVarFinMap@ specialisations for Ids/TyVars}
129 %************************************************************************
132 #ifdef __GLASGOW_HASKELL__
133 -- I don't think HBC was too happy about this (WDP 94/10)
136 addListToUFM :: UniqFM elt -> [(Name, elt)] -> UniqFM elt
139 addListToUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Name, elt)] -> UniqFM elt
142 addToUFM :: UniqFM elt -> Unique -> elt -> UniqFM elt
145 listToUFM :: [(Unique, elt)] -> UniqFM elt
148 lookupUFM :: UniqFM elt -> Name -> Maybe elt
149 , UniqFM elt -> Unique -> Maybe elt
152 #endif {- __GLASGOW_HASKELL__ -}
155 %************************************************************************
157 \subsection{Andy Gill's underlying @UniqFM@ machinery}
159 %************************************************************************
161 ``Uniq Finite maps'' are the heart and soul of the compiler's
162 lookup-tables/environments. Important stuff! It works well with
163 Dense and Sparse ranges.
164 Both @Uq@ Finite maps and @Hash@ Finite Maps
165 are built ontop of Int Finite Maps.
167 This code is explained in the paper:
169 A Gill, S Peyton Jones, B O'Sullivan, W Partain and Aqua Friends
170 "A Cheap balancing act that grows on a tree"
171 Glasgow FP Workshop, Sep 1994, pp??-??
174 %************************************************************************
176 \subsubsection{The @UniqFM@ type, and signatures for the functions}
178 %************************************************************************
180 @UniqFM a@ is a mapping from Unique to a.
182 First, the DataType itself; which is either a Node, a Leaf, or an Empty.
187 | LeafUFM FAST_INT ele
188 | NodeUFM FAST_INT -- the switching
189 FAST_INT -- the delta
193 -- for debugging only :-)
195 instance Text (UniqFM a) where
196 showsPrec _ (NodeUFM a b t1 t2) =
197 showString "NodeUFM " . shows (IBOX(a))
198 . showString " " . shows (IBOX(b))
199 . showString " (" . shows t1
200 . showString ") (" . shows t2
202 showsPrec _ (LeafUFM x a) = showString "LeafUFM " . shows (IBOX(x))
203 showsPrec _ (EmptyUFM) = id
207 %************************************************************************
209 \subsubsection{The @UniqFM@ functions}
211 %************************************************************************
213 First the ways of building a UniqFM.
217 unitUFM key elt = mkLeafUFM (u2i (uniqueOf key)) elt
218 unitDirectlyUFM key elt = mkLeafUFM (u2i key) elt
220 listToUFM key_elt_pairs
221 = addListToUFM_C use_snd EmptyUFM key_elt_pairs
223 listToUFM_Directly uniq_elt_pairs
224 = addListToUFM_directly_C use_snd EmptyUFM uniq_elt_pairs
227 Now ways of adding things to UniqFMs.
229 There is an alternative version of @addListToUFM_C@, that uses @plusUFM@,
230 but the semantics of this operation demands a linear insertion;
231 perhaps the version without the combinator function
232 could be optimised using it.
235 addToUFM fm key elt = addToUFM_C use_snd fm key elt
237 addToUFM_Directly fm u elt = insert_ele use_snd fm (u2i u) elt
239 addToUFM_C combiner fm key elt
240 = insert_ele combiner fm (u2i (uniqueOf key)) elt
242 addListToUFM fm key_elt_pairs = addListToUFM_C use_snd fm key_elt_pairs
243 addListToUFM_Directly fm uniq_elt_pairs = addListToUFM_directly_C use_snd fm uniq_elt_pairs
245 addListToUFM_C combiner fm key_elt_pairs
246 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i (uniqueOf k)) e)
249 addListToUFM_directly_C combiner fm uniq_elt_pairs
250 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i k) e)
254 Now ways of removing things from UniqFM.
257 delListFromUFM fm lst = foldl delFromUFM fm lst
259 delFromUFM fm key = delete fm (u2i (uniqueOf key))
260 delFromUFM_Directly fm u = delete fm (u2i u)
262 delete EmptyUFM _ = EmptyUFM
263 delete fm key = del_ele fm
265 del_ele :: UniqFM a -> UniqFM a
267 del_ele lf@(LeafUFM j _)
268 | j _EQ_ key = EmptyUFM
269 | otherwise = lf -- no delete!
271 del_ele nd@(NodeUFM j p t1 t2)
273 = mkSLNodeUFM (NodeUFMData j p) (del_ele t1) t2
275 = mkLSNodeUFM (NodeUFMData j p) t1 (del_ele t2)
277 del_ele _ = panic "Found EmptyUFM FM when rec-deleting"
280 Now ways of adding two UniqFM's together.
283 plusUFM tr1 tr2 = plusUFM_C use_snd tr1 tr2
285 plusUFM_C f EmptyUFM tr = tr
286 plusUFM_C f tr EmptyUFM = tr
287 plusUFM_C f fm1 fm2 = mix_trees fm1 fm2
289 mix_trees (LeafUFM i a) t2 = insert_ele (flip f) t2 i a
290 mix_trees t1 (LeafUFM i a) = insert_ele f t1 i a
292 mix_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
294 (ask_about_common_ancestor
298 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
302 -- t1 t2 t1' t2' j j'
307 mix_branches (NewRoot nd False)
308 = mkLLNodeUFM nd left_t right_t
309 mix_branches (NewRoot nd True)
310 = mkLLNodeUFM nd right_t left_t
316 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
318 mix_branches (SameRoot)
319 = mkSSNodeUFM (NodeUFMData j p)
322 -- Now the 4 different other ways; all like this:
324 -- Given j >^ j' (and, say, j > j')
328 -- t1 t2 t1' t2' t1 t2 + j'
331 mix_branches (LeftRoot Leftt) -- | trace "LL" True
334 (mix_trees t1 right_t)
337 mix_branches (LeftRoot Rightt) -- | trace "LR" True
341 (mix_trees t2 right_t)
343 mix_branches (RightRoot Leftt) -- | trace "RL" True
346 (mix_trees left_t t1')
349 mix_branches (RightRoot Rightt) -- | trace "RR" True
353 (mix_trees left_t t2')
355 mix_trees _ _ = panic "EmptyUFM found when inserting into plusInt"
358 And ways of subtracting them. First the base cases,
359 then the full D&C approach.
362 minusUFM EmptyUFM _ = EmptyUFM
363 minusUFM t1 EmptyUFM = t1
364 minusUFM fm1 fm2 = minus_trees fm1 fm2
367 -- Notice the asymetry of subtraction
369 minus_trees lf@(LeafUFM i a) t2 =
374 minus_trees t1 (LeafUFM i _) = delete t1 i
376 minus_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
378 (ask_about_common_ancestor
382 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
386 -- t1 t2 t1' t2' t1 t2
391 minus_branches (NewRoot nd _) = left_t
397 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
399 minus_branches (SameRoot)
400 = mkSSNodeUFM (NodeUFMData j p)
403 -- Now the 4 different other ways; all like this:
404 -- again, with asymatry
407 -- The left is above the right
409 minus_branches (LeftRoot Leftt)
412 (minus_trees t1 right_t)
414 minus_branches (LeftRoot Rightt)
418 (minus_trees t2 right_t)
421 -- The right is above the left
423 minus_branches (RightRoot Leftt)
424 = minus_trees left_t t1'
425 minus_branches (RightRoot Rightt)
426 = minus_trees left_t t2'
428 minus_trees _ _ = panic "EmptyUFM found when insering into plusInt"
431 And taking the intersection of two UniqFM's.
434 intersectUFM t1 t2 = intersectUFM_C use_snd t1 t2
436 intersectUFM_C f EmptyUFM _ = EmptyUFM
437 intersectUFM_C f _ EmptyUFM = EmptyUFM
438 intersectUFM_C f fm1 fm2 = intersect_trees fm1 fm2
440 intersect_trees (LeafUFM i a) t2 =
443 Just b -> mkLeafUFM i (f a b)
445 intersect_trees t1 (LeafUFM i a) =
448 Just b -> mkLeafUFM i (f b a)
450 intersect_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
452 (ask_about_common_ancestor
456 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
459 -- / \ + / \ ==> EmptyUFM
464 intersect_branches (NewRoot nd _) = EmptyUFM
470 -- t1 t2 t1' t2' t1 x t1' t2 x t2'
472 intersect_branches (SameRoot)
473 = mkSSNodeUFM (NodeUFMData j p)
474 (intersect_trees t1 t1')
475 (intersect_trees t2 t2')
476 -- Now the 4 different other ways; all like this:
478 -- Given j >^ j' (and, say, j > j')
482 -- t1 t2 t1' t2' t1' t2'
484 -- This does cut down the search space quite a bit.
486 intersect_branches (LeftRoot Leftt)
487 = intersect_trees t1 right_t
488 intersect_branches (LeftRoot Rightt)
489 = intersect_trees t2 right_t
490 intersect_branches (RightRoot Leftt)
491 = intersect_trees left_t t1'
492 intersect_branches (RightRoot Rightt)
493 = intersect_trees left_t t2'
495 intersect_trees x y = panic ("EmptyUFM found when intersecting trees")
498 Now the usual set of `collection' operators, like map, fold, etc.
501 foldUFM f a (NodeUFM _ _ t1 t2) = foldUFM f (foldUFM f a t2) t1
502 foldUFM f a (LeafUFM _ obj) = f obj a
503 foldUFM f a EmptyUFM = a
507 mapUFM fn EmptyUFM = EmptyUFM
508 mapUFM fn fm = map_tree fn fm
510 filterUFM fn EmptyUFM = EmptyUFM
511 filterUFM fn fm = filter_tree fn fm
514 Note, this takes a long time, O(n), but
515 because we dont want to do this very often, we put up with this.
516 O'rable, but how often do we look at the size of
521 sizeUFM (NodeUFM _ _ t1 t2) = sizeUFM t1 + sizeUFM t2
522 sizeUFM (LeafUFM _ _) = 1
524 isNullUFM EmptyUFM = True
528 looking up in a hurry is the {\em whole point} of this binary tree lark.
529 Lookup up a binary tree is easy (and fast).
532 elemUFM key fm = case lookUp fm (u2i (uniqueOf key)) of
536 lookupUFM fm key = lookUp fm (u2i (uniqueOf key))
537 lookupUFM_Directly fm key = lookUp fm (u2i key)
539 lookupWithDefaultUFM fm deflt key
540 = case lookUp fm (u2i (uniqueOf key)) of
544 lookupWithDefaultUFM_Directly fm deflt key
545 = case lookUp fm (u2i key) of
549 lookUp EmptyUFM _ = Nothing
550 lookUp fm i = lookup_tree fm
552 lookup_tree :: UniqFM a -> Maybe a
554 lookup_tree (LeafUFM j b)
556 | otherwise = Nothing
557 lookup_tree (NodeUFM j p t1 t2)
558 | j _GT_ i = lookup_tree t1
559 | otherwise = lookup_tree t2
561 lookup_tree EmptyUFM = panic "lookup Failed"
564 folds are *wonderful* things.
567 eltsUFM fm = foldUFM (:) [] fm
569 ufmToList fm = fold_tree (\ iu elt rest -> (mkUniqueGrimily iu, elt) : rest) [] fm
571 keysUFM fm = fold_tree (\ iu elt rest -> IBOX(iu) : rest) [] fm
573 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
574 fold_tree f a (LeafUFM iu obj) = f iu obj a
575 fold_tree f a EmptyUFM = a
578 %************************************************************************
580 \subsubsection{The @UniqFM@ type, and its functions}
582 %************************************************************************
584 You should always use these to build the tree.
585 There are 4 versions of mkNodeUFM, depending on
586 the strictness of the two sub-tree arguments.
587 The strictness is used *both* to prune out
588 empty trees, *and* to improve performance,
589 stoping needless thunks lying around.
590 The rule of thumb (from experence with these trees)
591 is make thunks strict, but data structures lazy.
592 If in doubt, use mkSSNodeUFM, which has the `strongest'
593 functionality, but may do a few needless evaluations.
596 mkLeafUFM :: FAST_INT -> a -> UniqFM a
597 mkLeafUFM i a = LeafUFM i a
599 -- The *ONLY* ways of building a NodeUFM.
601 mkSSNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
602 mkSSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
603 mkSSNodeUFM (NodeUFMData j p) t1 t2
604 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
607 mkSLNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
608 mkSLNodeUFM (NodeUFMData j p) t1 t2
609 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
612 mkLSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
613 mkLSNodeUFM (NodeUFMData j p) t1 t2
614 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
617 mkLLNodeUFM (NodeUFMData j p) t1 t2
618 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
628 correctNodeUFM j p t1 t2
629 = correct (j-p) (j-1) p t1 && correct j ((j-1)+p) p t2
631 correct low high _ (LeafUFM i _)
632 = low <= IBOX(i) && IBOX(i) <= high
633 correct low high above_p (NodeUFM j p _ _)
634 = low <= IBOX(j) && IBOX(j) <= high && above_p > IBOX(p)
635 correct _ _ _ EmptyUFM = panic "EmptyUFM stored inside a tree"
638 Note: doing SAT on this by hand seems to make it worse. Todo: Investigate,
639 and if necessary do $\lambda$ lifting on our functions that are bound.
649 insert_ele f EmptyUFM i new = mkLeafUFM i new
651 insert_ele f (LeafUFM j old) i new
653 mkLLNodeUFM (getCommonNodeUFMData
658 | j _EQ_ i = mkLeafUFM j (f old new)
660 mkLLNodeUFM (getCommonNodeUFMData
666 insert_ele f n@(NodeUFM j p t1 t2) i a
668 = if (i _GE_ (j _SUB_ p))
669 then mkSLNodeUFM (NodeUFMData j p) (insert_ele f t1 i a) t2
670 else mkLLNodeUFM (getCommonNodeUFMData
676 = if (i _LE_ ((j _SUB_ ILIT(1)) _ADD_ p))
677 then mkLSNodeUFM (NodeUFMData j p) t1 (insert_ele f t2 i a)
678 else mkLLNodeUFM (getCommonNodeUFMData
688 map_tree f (NodeUFM j p t1 t2)
689 = mkSSNodeUFM (NodeUFMData j p) (map_tree f t1) (map_tree f t2)
690 map_tree f (LeafUFM i obj)
691 = mkLeafUFM i (f obj)
693 map_tree f _ = panic "map_tree failed"
697 filter_tree f nd@(NodeUFM j p t1 t2)
698 = mkSSNodeUFM (NodeUFMData j p) (filter_tree f t1) (filter_tree f t2)
700 filter_tree f lf@(LeafUFM i obj)
702 | otherwise = EmptyUFM
703 filter_tree f _ = panic "filter_tree failed"
706 %************************************************************************
708 \subsubsection{The @UniqFM@ type, and signatures for the functions}
710 %************************************************************************
714 This is the information that is held inside a NodeUFM, packaged up for
719 = NodeUFMData FAST_INT
723 This is the information used when computing new NodeUFMs.
726 data Side = Leftt | Rightt -- NB: avoid 1.3 names "Left" and "Right"
728 = LeftRoot Side -- which side is the right down ?
729 | RightRoot Side -- which side is the left down ?
730 | SameRoot -- they are the same !
731 | NewRoot NodeUFMData -- here's the new, common, root
732 Bool -- do you need to swap left and right ?
735 This specifies the relationship between NodeUFMData and CalcNodeUFMData.
738 indexToRoot :: FAST_INT -> NodeUFMData
742 l = (ILIT(1) :: FAST_INT)
744 NodeUFMData (((i `shiftR_` l) `shiftL_` l) _ADD_ ILIT(1)) l
746 getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData
748 getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
749 | p _EQ_ p2 = getCommonNodeUFMData_ p j j2
750 | p _LT_ p2 = getCommonNodeUFMData_ p2 (j _QUOT_ (p2 _QUOT_ p)) j2
751 | otherwise = getCommonNodeUFMData_ p j (j2 _QUOT_ (p _QUOT_ p2))
753 l = (ILIT(1) :: FAST_INT)
754 j = i _QUOT_ (p `shiftL_` l)
755 j2 = i2 _QUOT_ (p2 `shiftL_` l)
757 getCommonNodeUFMData_ :: FAST_INT -> FAST_INT -> FAST_INT -> NodeUFMData
759 getCommonNodeUFMData_ p j j_
761 = NodeUFMData (((j `shiftL_` l) _ADD_ l) _MUL_ p) p
763 = getCommonNodeUFMData_ (p `shiftL_` l) (j `shiftR_` l) (j_ `shiftR_` l)
765 ask_about_common_ancestor :: NodeUFMData -> NodeUFMData -> CommonRoot
767 ask_about_common_ancestor x@(NodeUFMData j p) y@(NodeUFMData j2 p2)
768 | j _EQ_ j2 = SameRoot
770 = case getCommonNodeUFMData x y of
771 nd@(NodeUFMData j3 p3)
772 | j3 _EQ_ j -> LeftRoot (decideSide (j _GT_ j2))
773 | j3 _EQ_ j2 -> RightRoot (decideSide (j _LT_ j2))
774 | otherwise -> NewRoot nd (j _GT_ j2)
776 decideSide :: Bool -> Side
777 decideSide True = Leftt
778 decideSide False = Rightt
781 This might be better in Util.lhs ?
784 Now the bit twiddling functions.
786 shiftL_ :: FAST_INT -> FAST_INT -> FAST_INT
787 shiftR_ :: FAST_INT -> FAST_INT -> FAST_INT
789 #if __GLASGOW_HASKELL__
790 {-# INLINE shiftL_ #-}
791 {-# INLINE shiftR_ #-}
792 shiftL_ n p = word2Int#((int2Word# n) `shiftL#` p)
793 shiftR_ n p = word2Int#((int2Word# n) `shiftr` p)
795 shiftr x y = shiftRA# x y
798 shiftL_ n p = n * (2 ^ p)
799 shiftR_ n p = n `quot` (2 ^ p)
805 use_snd :: a -> b -> b