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@.)
14 #if defined(COMPILING_GHC)
15 #include "HsVersions.h"
16 #define IF_NOT_GHC(a) {--}
18 #define ASSERT(e) {--}
19 #define IF_NOT_GHC(a) a
23 UniqFM, -- abstract type
24 Uniquable(..), -- class to go with it
34 addListToUFM_Directly,
35 IF_NOT_GHC(addToUFM_C COMMA)
44 IF_NOT_GHC(intersectUFM_C COMMA)
45 IF_NOT_GHC(foldUFM COMMA)
50 lookupUFM, lookupUFM_Directly,
51 lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
56 #if defined(COMPILING_GHC)
60 import Unique ( Unique, u2i, mkUniqueGrimily )
62 import Pretty ( SYN_IE(Pretty), PrettyRep )
63 import PprStyle ( PprStyle )
64 import SrcLoc ( SrcLoc )
66 #if ! OMIT_NATIVE_CODEGEN
69 #define IF_NCG(a) {--}
73 %************************************************************************
75 \subsection{The @UniqFM@ type, and signatures for the functions}
77 %************************************************************************
79 We use @FiniteMaps@, with a (@uniqueOf@-able) @Unique@ as ``key''.
82 emptyUFM :: UniqFM elt
83 isNullUFM :: UniqFM elt -> Bool
84 unitUFM :: Uniquable key => key -> elt -> UniqFM elt
85 unitDirectlyUFM -- got the Unique already
86 :: Unique -> elt -> UniqFM elt
87 listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
89 :: [(Unique, elt)] -> UniqFM elt
91 addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
92 addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
94 :: UniqFM elt -> Unique -> elt -> UniqFM elt
96 addToUFM_C :: Uniquable key => (elt -> elt -> elt)
97 -> UniqFM elt -> key -> elt -> UniqFM elt
98 addListToUFM_C :: Uniquable key => (elt -> elt -> elt)
99 -> UniqFM elt -> [(key,elt)]
102 delFromUFM :: Uniquable key => UniqFM elt -> key -> UniqFM elt
103 delListFromUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
104 delFromUFM_Directly :: UniqFM elt -> Unique -> UniqFM elt
106 plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
108 plusUFM_C :: (elt -> elt -> elt)
109 -> UniqFM elt -> UniqFM elt -> UniqFM elt
111 minusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
113 intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
114 intersectUFM_C :: (elt -> elt -> elt)
115 -> UniqFM elt -> UniqFM elt -> UniqFM elt
116 foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
117 mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
118 filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
120 sizeUFM :: UniqFM elt -> Int
122 lookupUFM :: Uniquable key => UniqFM elt -> key -> Maybe elt
123 lookupUFM_Directly -- when you've got the Unique already
124 :: UniqFM elt -> Unique -> Maybe elt
126 :: Uniquable key => UniqFM elt -> elt -> key -> elt
127 lookupWithDefaultUFM_Directly
128 :: UniqFM elt -> elt -> Unique -> elt
130 eltsUFM :: UniqFM elt -> [elt]
131 ufmToList :: UniqFM elt -> [(Unique, elt)]
134 %************************************************************************
136 \subsection{The @IdFinMap@ and @TyVarFinMap@ specialisations for Ids/TyVars}
138 %************************************************************************
141 #ifdef __GLASGOW_HASKELL__
142 -- I don't think HBC was too happy about this (WDP 94/10)
145 addListToUFM :: UniqFM elt -> [(Name, elt)] -> UniqFM elt
146 , UniqFM elt -> [(RnName, elt)] -> UniqFM elt
149 addListToUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Name, elt)] -> UniqFM elt
150 , (elt -> elt -> elt) -> UniqFM elt -> [(RnName,elt)] -> UniqFM elt
153 addToUFM :: UniqFM elt -> Unique -> elt -> UniqFM elt
156 listToUFM :: [(Unique, elt)] -> UniqFM elt
157 , [(RnName, elt)] -> UniqFM elt
160 lookupUFM :: UniqFM elt -> Name -> Maybe elt
161 , UniqFM elt -> RnName -> Maybe elt
162 , UniqFM elt -> Unique -> Maybe elt
165 lookupWithDefaultUFM :: UniqFM elt -> elt -> RnName -> elt
168 #endif {- __GLASGOW_HASKELL__ -}
171 %************************************************************************
173 \subsection{Andy Gill's underlying @UniqFM@ machinery}
175 %************************************************************************
177 ``Uniq Finite maps'' are the heart and soul of the compiler's
178 lookup-tables/environments. Important stuff! It works well with
179 Dense and Sparse ranges.
180 Both @Uq@ Finite maps and @Hash@ Finite Maps
181 are built ontop of Int Finite Maps.
183 This code is explained in the paper:
185 A Gill, S Peyton Jones, B O'Sullivan, W Partain and Aqua Friends
186 "A Cheap balancing act that grows on a tree"
187 Glasgow FP Workshop, Sep 1994, pp??-??
190 %************************************************************************
192 \subsubsection{The @UniqFM@ type, and signatures for the functions}
194 %************************************************************************
196 @UniqFM a@ is a mapping from Unique to a.
198 First, the DataType itself; which is either a Node, a Leaf, or an Empty.
203 | LeafUFM FAST_INT ele
204 | NodeUFM FAST_INT -- the switching
205 FAST_INT -- the delta
209 class Uniquable a where
210 uniqueOf :: a -> Unique
212 -- for debugging only :-)
214 instance Text (UniqFM a) where
215 showsPrec _ (NodeUFM a b t1 t2) =
216 showString "NodeUFM " . shows (IBOX(a))
217 . showString " " . shows (IBOX(b))
218 . showString " (" . shows t1
219 . showString ") (" . shows t2
221 showsPrec _ (LeafUFM x a) = showString "LeafUFM " . shows (IBOX(x))
222 showsPrec _ (EmptyUFM) = id
226 %************************************************************************
228 \subsubsection{The @UniqFM@ functions}
230 %************************************************************************
232 First the ways of building a UniqFM.
236 unitUFM key elt = mkLeafUFM (u2i (uniqueOf key)) elt
237 unitDirectlyUFM key elt = mkLeafUFM (u2i key) elt
239 listToUFM key_elt_pairs
240 = addListToUFM_C use_snd EmptyUFM key_elt_pairs
242 listToUFM_Directly uniq_elt_pairs
243 = addListToUFM_directly_C use_snd EmptyUFM uniq_elt_pairs
246 Now ways of adding things to UniqFMs.
248 There is an alternative version of @addListToUFM_C@, that uses @plusUFM@,
249 but the semantics of this operation demands a linear insertion;
250 perhaps the version without the combinator function
251 could be optimised using it.
254 addToUFM fm key elt = addToUFM_C use_snd fm key elt
256 addToUFM_Directly fm u elt = insert_ele use_snd fm (u2i u) elt
258 addToUFM_C combiner fm key elt
259 = insert_ele combiner fm (u2i (uniqueOf key)) elt
261 addListToUFM fm key_elt_pairs = addListToUFM_C use_snd fm key_elt_pairs
262 addListToUFM_Directly fm uniq_elt_pairs = addListToUFM_directly_C use_snd fm uniq_elt_pairs
264 addListToUFM_C combiner fm key_elt_pairs
265 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i (uniqueOf k)) e)
268 addListToUFM_directly_C combiner fm uniq_elt_pairs
269 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i k) e)
273 Now ways of removing things from UniqFM.
276 delListFromUFM fm lst = foldl delFromUFM fm lst
278 delFromUFM fm key = delete fm (u2i (uniqueOf key))
279 delFromUFM_Directly fm u = delete fm (u2i u)
281 delete EmptyUFM _ = EmptyUFM
282 delete fm key = del_ele fm
284 del_ele :: UniqFM a -> UniqFM a
286 del_ele lf@(LeafUFM j _)
287 | j _EQ_ key = EmptyUFM
288 | otherwise = lf -- no delete!
290 del_ele nd@(NodeUFM j p t1 t2)
292 = mkSLNodeUFM (NodeUFMData j p) (del_ele t1) t2
294 = mkLSNodeUFM (NodeUFMData j p) t1 (del_ele t2)
296 del_ele _ = panic "Found EmptyUFM FM when rec-deleting"
299 Now ways of adding two UniqFM's together.
302 plusUFM tr1 tr2 = plusUFM_C use_snd tr1 tr2
304 plusUFM_C f EmptyUFM tr = tr
305 plusUFM_C f tr EmptyUFM = tr
306 plusUFM_C f fm1 fm2 = mix_trees fm1 fm2
308 mix_trees (LeafUFM i a) t2 = insert_ele (flip f) t2 i a
309 mix_trees t1 (LeafUFM i a) = insert_ele f t1 i a
311 mix_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
313 (ask_about_common_ancestor
317 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
321 -- t1 t2 t1' t2' j j'
326 mix_branches (NewRoot nd False)
327 = mkLLNodeUFM nd left_t right_t
328 mix_branches (NewRoot nd True)
329 = mkLLNodeUFM nd right_t left_t
335 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
337 mix_branches (SameRoot)
338 = mkSSNodeUFM (NodeUFMData j p)
341 -- Now the 4 different other ways; all like this:
343 -- Given j >^ j' (and, say, j > j')
347 -- t1 t2 t1' t2' t1 t2 + j'
350 mix_branches (LeftRoot Leftt) -- | trace "LL" True
353 (mix_trees t1 right_t)
356 mix_branches (LeftRoot Rightt) -- | trace "LR" True
360 (mix_trees t2 right_t)
362 mix_branches (RightRoot Leftt) -- | trace "RL" True
365 (mix_trees left_t t1')
368 mix_branches (RightRoot Rightt) -- | trace "RR" True
372 (mix_trees left_t t2')
374 mix_trees _ _ = panic "EmptyUFM found when inserting into plusInt"
377 And ways of subtracting them. First the base cases,
378 then the full D&C approach.
381 minusUFM EmptyUFM _ = EmptyUFM
382 minusUFM t1 EmptyUFM = t1
383 minusUFM fm1 fm2 = minus_trees fm1 fm2
386 -- Notice the asymetry of subtraction
388 minus_trees lf@(LeafUFM i a) t2 =
393 minus_trees t1 (LeafUFM i _) = delete t1 i
395 minus_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
397 (ask_about_common_ancestor
401 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
405 -- t1 t2 t1' t2' t1 t2
410 minus_branches (NewRoot nd _) = left_t
416 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
418 minus_branches (SameRoot)
419 = mkSSNodeUFM (NodeUFMData j p)
422 -- Now the 4 different other ways; all like this:
423 -- again, with asymatry
426 -- The left is above the right
428 minus_branches (LeftRoot Leftt)
431 (minus_trees t1 right_t)
433 minus_branches (LeftRoot Rightt)
437 (minus_trees t2 right_t)
440 -- The right is above the left
442 minus_branches (RightRoot Leftt)
443 = minus_trees left_t t1'
444 minus_branches (RightRoot Rightt)
445 = minus_trees left_t t2'
447 minus_trees _ _ = panic "EmptyUFM found when insering into plusInt"
450 And taking the intersection of two UniqFM's.
453 intersectUFM t1 t2 = intersectUFM_C use_snd t1 t2
455 intersectUFM_C f EmptyUFM _ = EmptyUFM
456 intersectUFM_C f _ EmptyUFM = EmptyUFM
457 intersectUFM_C f fm1 fm2 = intersect_trees fm1 fm2
459 intersect_trees (LeafUFM i a) t2 =
462 Just b -> mkLeafUFM i (f a b)
464 intersect_trees t1 (LeafUFM i a) =
467 Just b -> mkLeafUFM i (f b a)
469 intersect_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
471 (ask_about_common_ancestor
475 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
478 -- / \ + / \ ==> EmptyUFM
483 intersect_branches (NewRoot nd _) = EmptyUFM
489 -- t1 t2 t1' t2' t1 x t1' t2 x t2'
491 intersect_branches (SameRoot)
492 = mkSSNodeUFM (NodeUFMData j p)
493 (intersect_trees t1 t1')
494 (intersect_trees t2 t2')
495 -- Now the 4 different other ways; all like this:
497 -- Given j >^ j' (and, say, j > j')
501 -- t1 t2 t1' t2' t1' t2'
503 -- This does cut down the search space quite a bit.
505 intersect_branches (LeftRoot Leftt)
506 = intersect_trees t1 right_t
507 intersect_branches (LeftRoot Rightt)
508 = intersect_trees t2 right_t
509 intersect_branches (RightRoot Leftt)
510 = intersect_trees left_t t1'
511 intersect_branches (RightRoot Rightt)
512 = intersect_trees left_t t2'
514 intersect_trees x y = panic ("EmptyUFM found when intersecting trees")
517 Now the usual set of `collection' operators, like map, fold, etc.
520 foldUFM fn a EmptyUFM = a
521 foldUFM fn a fm = fold_tree fn a fm
523 mapUFM fn EmptyUFM = EmptyUFM
524 mapUFM fn fm = map_tree fn fm
526 filterUFM fn EmptyUFM = EmptyUFM
527 filterUFM fn fm = filter_tree fn fm
530 Note, this takes a long time, O(n), but
531 because we dont want to do this very often, we put up with this.
532 O'rable, but how often do we look at the size of
537 sizeUFM (NodeUFM _ _ t1 t2) = sizeUFM t1 + sizeUFM t2
538 sizeUFM (LeafUFM _ _) = 1
540 isNullUFM EmptyUFM = True
544 looking up in a hurry is the {\em whole point} of this binary tree lark.
545 Lookup up a binary tree is easy (and fast).
548 lookupUFM fm key = lookUp fm (u2i (uniqueOf key))
549 lookupUFM_Directly fm key = lookUp fm (u2i key)
551 lookupWithDefaultUFM fm deflt key
552 = case lookUp fm (u2i (uniqueOf key)) of
556 lookupWithDefaultUFM_Directly fm deflt key
557 = case lookUp fm (u2i key) of
561 lookUp EmptyUFM _ = Nothing
562 lookUp fm i = lookup_tree fm
564 lookup_tree :: UniqFM a -> Maybe a
566 lookup_tree (LeafUFM j b)
568 | otherwise = Nothing
569 lookup_tree (NodeUFM j p t1 t2)
570 | j _GT_ i = lookup_tree t1
571 | otherwise = lookup_tree t2
573 lookup_tree EmptyUFM = panic "lookup Failed"
576 folds are *wonderful* things.
579 eltsUFM EmptyUFM = []
580 eltsUFM fm = fold_tree (:) [] fm
582 ufmToList EmptyUFM = []
584 = fold_tree (\ iu elt rest -> (mkUniqueGrimily iu, elt) : rest) [] fm
586 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
587 fold_tree f a (LeafUFM iu obj) = f iu obj a
589 fold_tree f a EmptyUFM = panic "Should Never fold over an EmptyUFM"
592 %************************************************************************
594 \subsubsection{The @UniqFM@ type, and its functions}
596 %************************************************************************
598 You should always use these to build the tree.
599 There are 4 versions of mkNodeUFM, depending on
600 the strictness of the two sub-tree arguments.
601 The strictness is used *both* to prune out
602 empty trees, *and* to improve performance,
603 stoping needless thunks lying around.
604 The rule of thumb (from experence with these trees)
605 is make thunks strict, but data structures lazy.
606 If in doubt, use mkSSNodeUFM, which has the `strongest'
607 functionality, but may do a few needless evaluations.
610 mkLeafUFM :: FAST_INT -> a -> UniqFM a
611 mkLeafUFM i a = LeafUFM i a
613 -- The *ONLY* ways of building a NodeUFM.
615 mkSSNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
616 mkSSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
617 mkSSNodeUFM (NodeUFMData j p) t1 t2
618 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
621 mkSLNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
622 mkSLNodeUFM (NodeUFMData j p) t1 t2
623 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
626 mkLSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
627 mkLSNodeUFM (NodeUFMData j p) t1 t2
628 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
631 mkLLNodeUFM (NodeUFMData j p) t1 t2
632 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
642 correctNodeUFM j p t1 t2
643 = correct (j-p) (j-1) p t1 && correct j ((j-1)+p) p t2
645 correct low high _ (LeafUFM i _)
646 = low <= IBOX(i) && IBOX(i) <= high
647 correct low high above_p (NodeUFM j p _ _)
648 = low <= IBOX(j) && IBOX(j) <= high && above_p > IBOX(p)
649 correct _ _ _ EmptyUFM = panic "EmptyUFM stored inside a tree"
652 Note: doing SAT on this by hand seems to make it worse. Todo: Investigate,
653 and if necessary do $\lambda$ lifting on our functions that are bound.
663 insert_ele f EmptyUFM i new = mkLeafUFM i new
665 insert_ele f (LeafUFM j old) i new
667 mkLLNodeUFM (getCommonNodeUFMData
672 | j _EQ_ i = mkLeafUFM j (f old new)
674 mkLLNodeUFM (getCommonNodeUFMData
680 insert_ele f n@(NodeUFM j p t1 t2) i a
682 = if (i _GE_ (j _SUB_ p))
683 then mkSLNodeUFM (NodeUFMData j p) (insert_ele f t1 i a) t2
684 else mkLLNodeUFM (getCommonNodeUFMData
690 = if (i _LE_ ((j _SUB_ ILIT(1)) _ADD_ p))
691 then mkLSNodeUFM (NodeUFMData j p) t1 (insert_ele f t2 i a)
692 else mkLLNodeUFM (getCommonNodeUFMData
699 This has got a left to right ordering.
702 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
703 fold_tree f a (LeafUFM _ obj) = f obj a
705 fold_tree f a EmptyUFM = panic "Should Never fold over an EmptyUFM"
709 map_tree f (NodeUFM j p t1 t2)
710 = mkSSNodeUFM (NodeUFMData j p) (map_tree f t1) (map_tree f t2)
711 map_tree f (LeafUFM i obj)
712 = mkLeafUFM i (f obj)
714 map_tree f _ = panic "map_tree failed"
718 filter_tree f nd@(NodeUFM j p t1 t2)
719 = mkSSNodeUFM (NodeUFMData j p) (filter_tree f t1) (filter_tree f t2)
721 filter_tree f lf@(LeafUFM i obj)
723 | otherwise = EmptyUFM
726 %************************************************************************
728 \subsubsection{The @UniqFM@ type, and signatures for the functions}
730 %************************************************************************
734 This is the information that is held inside a NodeUFM, packaged up for
739 = NodeUFMData FAST_INT
743 This is the information used when computing new NodeUFMs.
746 data Side = Leftt | Rightt -- NB: avoid 1.3 names "Left" and "Right"
748 = LeftRoot Side -- which side is the right down ?
749 | RightRoot Side -- which side is the left down ?
750 | SameRoot -- they are the same !
751 | NewRoot NodeUFMData -- here's the new, common, root
752 Bool -- do you need to swap left and right ?
755 This specifies the relationship between NodeUFMData and CalcNodeUFMData.
758 indexToRoot :: FAST_INT -> NodeUFMData
762 l = (ILIT(1) :: FAST_INT)
764 NodeUFMData (((i `shiftR_` l) `shiftL_` l) _ADD_ ILIT(1)) l
766 getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData
768 getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
769 | p _EQ_ p2 = getCommonNodeUFMData_ p j j2
770 | p _LT_ p2 = getCommonNodeUFMData_ p2 (j _QUOT_ (p2 _QUOT_ p)) j2
771 | otherwise = getCommonNodeUFMData_ p j (j2 _QUOT_ (p _QUOT_ p2))
773 l = (ILIT(1) :: FAST_INT)
774 j = i _QUOT_ (p `shiftL_` l)
775 j2 = i2 _QUOT_ (p2 `shiftL_` l)
777 getCommonNodeUFMData_ :: FAST_INT -> FAST_INT -> FAST_INT -> NodeUFMData
779 getCommonNodeUFMData_ p j j_
781 = NodeUFMData (((j `shiftL_` l) _ADD_ l) _MUL_ p) p
783 = getCommonNodeUFMData_ (p `shiftL_` l) (j `shiftR_` l) (j_ `shiftR_` l)
785 ask_about_common_ancestor :: NodeUFMData -> NodeUFMData -> CommonRoot
787 ask_about_common_ancestor x@(NodeUFMData j p) y@(NodeUFMData j2 p2)
788 | j _EQ_ j2 = SameRoot
790 = case getCommonNodeUFMData x y of
791 nd@(NodeUFMData j3 p3)
792 | j3 _EQ_ j -> LeftRoot (decideSide (j _GT_ j2))
793 | j3 _EQ_ j2 -> RightRoot (decideSide (j _LT_ j2))
794 | otherwise -> NewRoot nd (j _GT_ j2)
796 decideSide :: Bool -> Side
797 decideSide True = Leftt
798 decideSide False = Rightt
801 This might be better in Util.lhs ?
804 Now the bit twiddling functions.
806 shiftL_ :: FAST_INT -> FAST_INT -> FAST_INT
807 shiftR_ :: FAST_INT -> FAST_INT -> FAST_INT
809 #if __GLASGOW_HASKELL__
810 {-# INLINE shiftL_ #-}
811 {-# INLINE shiftR_ #-}
812 shiftL_ n p = word2Int#((int2Word# n) `shiftL#` p)
813 shiftR_ n p = word2Int#((int2Word# n) `shiftr` p)
815 shiftr x y = shiftRA# x y
818 shiftL_ n p = n * (2 ^ p)
819 shiftR_ n p = n `quot` (2 ^ p)
824 Andy's extras: ToDo: to Util.
827 use_fst :: a -> b -> a
830 use_snd :: a -> b -> b