PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/ghc-7.0.4/compiler/utils/UniqFM.lhs

http://picorec.googlecode.com/
Haskell | 232 lines | 185 code | 37 blank | 10 comment | 1 complexity | b1acbaf89199ecb4a93187be46a2fb9d MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause
  1. %
  2. % (c) The University of Glasgow 2006
  3. % (c) The AQUA Project, Glasgow University, 1994-1998
  4. %
  5. UniqFM: Specialised finite maps, for things with @Uniques@.
  6. Basically, the things need to be in class @Uniquable@, and we use the
  7. @getUnique@ method to grab their @Uniques@.
  8. (A similar thing to @UniqSet@, as opposed to @Set@.)
  9. The interface is based on @FiniteMap@s, but the implementation uses
  10. @Data.IntMap@, which is both maitained and faster than the past
  11. implementation (see commit log).
  12. The @UniqFM@ interface maps directly to Data.IntMap, only
  13. ``Data.IntMap.union'' is left-biased and ``plusUFM'' right-biased
  14. and ``addToUFM\_C'' and ``Data.IntMap.insertWith'' differ in the order
  15. of arguments of combining function.
  16. \begin{code}
  17. {-# OPTIONS -Wall #-}
  18. module UniqFM (
  19. -- * Unique-keyed mappings
  20. UniqFM, -- abstract type
  21. -- ** Manipulating those mappings
  22. emptyUFM,
  23. unitUFM,
  24. unitDirectlyUFM,
  25. listToUFM,
  26. listToUFM_Directly,
  27. listToUFM_C,
  28. addToUFM,addToUFM_C,addToUFM_Acc,
  29. addListToUFM,addListToUFM_C,
  30. addToUFM_Directly,
  31. addListToUFM_Directly,
  32. delFromUFM,
  33. delFromUFM_Directly,
  34. delListFromUFM,
  35. plusUFM,
  36. plusUFM_C,
  37. minusUFM,
  38. intersectUFM,
  39. intersectUFM_C,
  40. foldUFM, foldUFM_Directly,
  41. mapUFM,
  42. elemUFM, elemUFM_Directly,
  43. filterUFM, filterUFM_Directly,
  44. sizeUFM,
  45. isNullUFM,
  46. lookupUFM, lookupUFM_Directly,
  47. lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
  48. eltsUFM, keysUFM, splitUFM,
  49. ufmToList
  50. ) where
  51. import Unique ( Uniquable(..), Unique, getKey )
  52. import Outputable
  53. import qualified Data.IntMap as M
  54. \end{code}
  55. %************************************************************************
  56. %* *
  57. \subsection{The signature of the module}
  58. %* *
  59. %************************************************************************
  60. \begin{code}
  61. emptyUFM :: UniqFM elt
  62. isNullUFM :: UniqFM elt -> Bool
  63. unitUFM :: Uniquable key => key -> elt -> UniqFM elt
  64. unitDirectlyUFM -- got the Unique already
  65. :: Unique -> elt -> UniqFM elt
  66. listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
  67. listToUFM_Directly
  68. :: [(Unique, elt)] -> UniqFM elt
  69. listToUFM_C :: Uniquable key => (elt -> elt -> elt)
  70. -> [(key, elt)]
  71. -> UniqFM elt
  72. addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
  73. addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
  74. addListToUFM_Directly :: UniqFM elt -> [(Unique,elt)] -> UniqFM elt
  75. addToUFM_Directly
  76. :: UniqFM elt -> Unique -> elt -> UniqFM elt
  77. addToUFM_C :: Uniquable key => (elt -> elt -> elt) -- old -> new -> result
  78. -> UniqFM elt -- old
  79. -> key -> elt -- new
  80. -> UniqFM elt -- result
  81. addToUFM_Acc :: Uniquable key =>
  82. (elt -> elts -> elts) -- Add to existing
  83. -> (elt -> elts) -- New element
  84. -> UniqFM elts -- old
  85. -> key -> elt -- new
  86. -> UniqFM elts -- result
  87. addListToUFM_C :: Uniquable key => (elt -> elt -> elt)
  88. -> UniqFM elt -> [(key,elt)]
  89. -> UniqFM 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
  93. -- Bindings in right argument shadow those in the left
  94. plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
  95. plusUFM_C :: (elt -> elt -> elt)
  96. -> UniqFM elt -> UniqFM elt -> UniqFM elt
  97. minusUFM :: UniqFM elt1 -> UniqFM elt2 -> UniqFM elt1
  98. intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
  99. intersectUFM_C :: (elt1 -> elt2 -> elt3)
  100. -> UniqFM elt1 -> UniqFM elt2 -> UniqFM elt3
  101. foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
  102. foldUFM_Directly:: (Unique -> elt -> a -> a) -> a -> UniqFM elt -> a
  103. mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
  104. filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
  105. filterUFM_Directly :: (Unique -> elt -> Bool) -> UniqFM elt -> UniqFM elt
  106. sizeUFM :: UniqFM elt -> Int
  107. --hashUFM :: UniqFM elt -> Int
  108. elemUFM :: Uniquable key => key -> UniqFM elt -> Bool
  109. elemUFM_Directly:: Unique -> UniqFM elt -> Bool
  110. splitUFM :: Uniquable key => UniqFM elt -> key -> (UniqFM elt, Maybe elt, UniqFM elt)
  111. -- Splits a UFM into things less than, equal to, and greater than the key
  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
  115. lookupWithDefaultUFM
  116. :: Uniquable key => UniqFM elt -> elt -> key -> elt
  117. lookupWithDefaultUFM_Directly
  118. :: UniqFM elt -> elt -> Unique -> elt
  119. keysUFM :: UniqFM elt -> [Unique] -- Get the keys
  120. eltsUFM :: UniqFM elt -> [elt]
  121. ufmToList :: UniqFM elt -> [(Unique, elt)]
  122. \end{code}
  123. %************************************************************************
  124. %* *
  125. \subsection{Implementation using ``Data.IntMap''}
  126. %* *
  127. %************************************************************************
  128. \begin{code}
  129. newtype UniqFM ele = UFM (M.IntMap ele)
  130. emptyUFM = UFM M.empty
  131. isNullUFM (UFM m) = M.null m
  132. unitUFM k v = UFM (M.singleton (getKey $ getUnique k) v)
  133. unitDirectlyUFM u v = UFM (M.singleton (getKey u) v)
  134. listToUFM = foldl (\m (k, v) -> addToUFM m k v) emptyUFM
  135. listToUFM_Directly = foldl (\m (u, v) -> addToUFM_Directly m u v) emptyUFM
  136. listToUFM_C f = foldl (\m (k, v) -> addToUFM_C f m k v) emptyUFM
  137. addToUFM (UFM m) k v = UFM (M.insert (getKey $ getUnique k) v m)
  138. addListToUFM = foldl (\m (k, v) -> addToUFM m k v)
  139. addListToUFM_Directly = foldl (\m (k, v) -> addToUFM_Directly m k v)
  140. addToUFM_Directly (UFM m) u v = UFM (M.insert (getKey u) v m)
  141. -- Arguments of combining function of M.insertWith and addToUFM_C are flipped.
  142. addToUFM_C f (UFM m) k v =
  143. UFM (M.insertWith (flip f) (getKey $ getUnique k) v m)
  144. addToUFM_Acc exi new (UFM m) k v =
  145. UFM (M.insertWith (\_new old -> exi v old) (getKey $ getUnique k) (new v) m)
  146. addListToUFM_C f = foldl (\m (k, v) -> addToUFM_C f m k v)
  147. delFromUFM (UFM m) k = UFM (M.delete (getKey $ getUnique k) m)
  148. delListFromUFM = foldl delFromUFM
  149. delFromUFM_Directly (UFM m) u = UFM (M.delete (getKey u) m)
  150. -- M.union is left-biased, plusUFM should be right-biased.
  151. plusUFM (UFM x) (UFM y) = UFM (M.union y x)
  152. plusUFM_C f (UFM x) (UFM y) = UFM (M.unionWith f x y)
  153. minusUFM (UFM x) (UFM y) = UFM (M.difference x y)
  154. intersectUFM (UFM x) (UFM y) = UFM (M.intersection x y)
  155. #if __GLASGOW_HASKELL__ >= 611
  156. intersectUFM_C f (UFM x) (UFM y) = UFM (M.intersectionWith f x y)
  157. #else
  158. -- In GHC 6.10, intersectionWith is (a -> b -> a) instead of (a -> b -> c),
  159. -- so we need to jump through some hoops to get the more general type.
  160. intersectUFM_C f (UFM x) (UFM y) = UFM z
  161. where z = let x' = M.map Left x
  162. f' (Left a) b = Right (f a b)
  163. f' (Right _) _ = panic "intersectUFM_C: f': Right"
  164. z' = M.intersectionWith f' x' y
  165. fromRight (Right a) = a
  166. fromRight _ = panic "intersectUFM_C: Left"
  167. in M.map fromRight z'
  168. #endif
  169. foldUFM k z (UFM m) = M.fold k z m
  170. foldUFM_Directly k z (UFM m) = M.foldWithKey (k . getUnique) z m
  171. mapUFM f (UFM m) = UFM (M.map f m)
  172. filterUFM p (UFM m) = UFM (M.filter p m)
  173. filterUFM_Directly p (UFM m) = UFM (M.filterWithKey (p . getUnique) m)
  174. sizeUFM (UFM m) = M.size m
  175. elemUFM k (UFM m) = M.member (getKey $ getUnique k) m
  176. elemUFM_Directly u (UFM m) = M.member (getKey u) m
  177. splitUFM (UFM m) k = case M.splitLookup (getKey $ getUnique k) m of
  178. (less, equal, greater) -> (UFM less, equal, UFM greater)
  179. lookupUFM (UFM m) k = M.lookup (getKey $ getUnique k) m
  180. lookupUFM_Directly (UFM m) u = M.lookup (getKey u) m
  181. lookupWithDefaultUFM (UFM m) v k = M.findWithDefault v (getKey $ getUnique k) m
  182. lookupWithDefaultUFM_Directly (UFM m) v u = M.findWithDefault v (getKey u) m
  183. keysUFM (UFM m) = map getUnique $ M.keys m
  184. eltsUFM (UFM m) = M.elems m
  185. ufmToList (UFM m) = map (\(k, v) -> (getUnique k, v)) $ M.toList m
  186. \end{code}
  187. %************************************************************************
  188. %* *
  189. \subsection{Output-ery}
  190. %* *
  191. %************************************************************************
  192. \begin{code}
  193. instance Outputable a => Outputable (UniqFM a) where
  194. ppr ufm = ppr (ufmToList ufm)
  195. \end{code}