ec3d1d998090e823b40a637f78caaa392106a693
[ghc-hetmet.git] / compiler / utils / UniqSet.lhs
1 %
2 % (c) The University of Glasgow 2006
3 % (c) The AQUA Project, Glasgow University, 1994-1998
4 %
5 \section[UniqSet]{Specialised sets, for things with @Uniques@}
6
7 Based on @UniqFMs@ (as you would expect).
8
9 Basically, the things need to be in class @Uniquable@.
10
11 \begin{code}
12 module UniqSet (
13         UniqSet,    -- abstract type: NOT
14
15         mkUniqSet, uniqSetToList, emptyUniqSet, unitUniqSet,
16         addOneToUniqSet, addListToUniqSet, delOneFromUniqSet, delListFromUniqSet,
17         unionUniqSets, unionManyUniqSets, minusUniqSet,
18         elementOfUniqSet, mapUniqSet, intersectUniqSets,
19         isEmptyUniqSet, filterUniqSet, sizeUniqSet, foldUniqSet,
20         elemUniqSet_Directly, lookupUniqSet, hashUniqSet
21     ) where
22
23 #include "HsVersions.h"
24
25 import Maybes           ( maybeToBool )
26 import UniqFM
27 import Unique           ( Unique, Uniquable(..) )
28
29 #if ! OMIT_NATIVE_CODEGEN
30 #define IF_NCG(a) a
31 #else
32 #define IF_NCG(a) {--}
33 #endif
34 \end{code}
35
36 %************************************************************************
37 %*                                                                      *
38 \subsection{The @UniqSet@ type}
39 %*                                                                      *
40 %************************************************************************
41
42 We use @UniqFM@, with a (@getUnique@-able) @Unique@ as ``key''
43 and the thing itself as the ``value'' (for later retrieval).
44
45 \begin{code}
46 --data UniqSet a = MkUniqSet (FiniteMap Unique a) : NOT
47
48 type UniqSet a = UniqFM a
49 #define MkUniqSet {--}
50
51 emptyUniqSet :: UniqSet a
52 emptyUniqSet = MkUniqSet emptyUFM
53
54 unitUniqSet :: Uniquable a => a -> UniqSet a
55 unitUniqSet x = MkUniqSet (unitUFM x x)
56
57 uniqSetToList :: UniqSet a -> [a]
58 uniqSetToList (MkUniqSet set) = eltsUFM set
59
60 foldUniqSet :: (a -> b -> b) -> b -> UniqSet a -> b
61 foldUniqSet k z (MkUniqSet set) = foldUFM k z set 
62
63 mkUniqSet :: Uniquable a => [a]  -> UniqSet a
64 mkUniqSet xs = MkUniqSet (listToUFM [ (x, x) | x <- xs])
65
66 addOneToUniqSet :: Uniquable a => UniqSet a -> a -> UniqSet a
67 addOneToUniqSet (MkUniqSet set) x = MkUniqSet (addToUFM set x x)
68
69 delOneFromUniqSet :: Uniquable a => UniqSet a -> a -> UniqSet a
70 delOneFromUniqSet (MkUniqSet set) x = MkUniqSet (delFromUFM set x)
71
72 delListFromUniqSet :: Uniquable a => UniqSet a -> [a] -> UniqSet a
73 delListFromUniqSet (MkUniqSet set) xs = MkUniqSet (delListFromUFM set xs)
74
75 addListToUniqSet :: Uniquable a => UniqSet a -> [a] -> UniqSet a
76 addListToUniqSet (MkUniqSet set) xs = MkUniqSet (addListToUFM set [(x,x) | x<-xs])
77
78 unionUniqSets :: UniqSet a -> UniqSet a -> UniqSet a
79 unionUniqSets (MkUniqSet set1) (MkUniqSet set2) = MkUniqSet (plusUFM set1 set2)
80
81 unionManyUniqSets :: [UniqSet a] -> UniqSet a
82         -- = foldr unionUniqSets emptyUniqSet ss
83 unionManyUniqSets []     = emptyUniqSet
84 unionManyUniqSets [s]    = s
85 unionManyUniqSets (s:ss) = s `unionUniqSets` unionManyUniqSets ss
86
87 minusUniqSet  :: UniqSet a -> UniqSet a -> UniqSet a
88 minusUniqSet (MkUniqSet set1) (MkUniqSet set2) = MkUniqSet (minusUFM set1 set2)
89
90 filterUniqSet :: (a -> Bool) -> UniqSet a -> UniqSet a
91 filterUniqSet pred (MkUniqSet set) = MkUniqSet (filterUFM pred set)
92
93 intersectUniqSets :: UniqSet a -> UniqSet a -> UniqSet a
94 intersectUniqSets (MkUniqSet set1) (MkUniqSet set2) = MkUniqSet (intersectUFM set1 set2)
95
96 elementOfUniqSet :: Uniquable a => a -> UniqSet a -> Bool
97 elementOfUniqSet x (MkUniqSet set) = maybeToBool (lookupUFM set x)
98
99 lookupUniqSet :: Uniquable a => UniqSet a -> a -> Maybe a
100 lookupUniqSet (MkUniqSet set) x = lookupUFM set x
101
102 elemUniqSet_Directly :: Unique -> UniqSet a -> Bool
103 elemUniqSet_Directly x (MkUniqSet set) = maybeToBool (lookupUFM_Directly set x)
104
105 sizeUniqSet :: UniqSet a -> Int
106 sizeUniqSet (MkUniqSet set) = sizeUFM set
107
108 hashUniqSet :: UniqSet a -> Int
109 hashUniqSet (MkUniqSet set) = hashUFM set
110
111 isEmptyUniqSet :: UniqSet a -> Bool
112 isEmptyUniqSet (MkUniqSet set) = isNullUFM set {-SLOW: sizeUFM set == 0-}
113
114 mapUniqSet :: (a -> a) -> UniqSet a -> UniqSet a
115   -- VERY IMPORTANT: *assumes* that the function doesn't change the unique
116 mapUniqSet f (MkUniqSet set) = MkUniqSet (mapUFM f set)
117 \end{code}
118
119 \begin{code}
120 #if __GLASGOW_HASKELL__
121 {-# SPECIALIZE
122     addOneToUniqSet :: UniqSet Unique -> Unique -> UniqSet Unique
123     #-}
124
125 -- These next three specialisations disabled as importing Name creates a
126 -- loop, and getting the Uniquable Name instance in particular is tricky.
127
128 {- SPECIALIZE
129     elementOfUniqSet :: Name -> UniqSet Name -> Bool
130                       , Unique -> UniqSet Unique -> Bool
131     -}
132 {- SPECIALIZE
133     mkUniqSet :: [Name] -> UniqSet Name
134     -}
135
136 {- SPECIALIZE
137     unitUniqSet :: Name -> UniqSet Name
138                  , Unique -> UniqSet Unique
139     -}
140 #endif
141 \end{code}