PageRenderTime 40ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/utils/UniqFM.hs

http://github.com/ghc/ghc
Haskell | 378 lines | 225 code | 68 blank | 85 comment | 1 complexity | 933e7c62f4a108b1d48b04aef4b4d293 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, GPL-3.0
  1. {-
  2. (c) The University of Glasgow 2006
  3. (c) The AQUA Project, Glasgow University, 1994-1998
  4. UniqFM: Specialised finite maps, for things with @Uniques@.
  5. Basically, the things need to be in class @Uniquable@, and we use the
  6. @getUnique@ method to grab their @Uniques@.
  7. (A similar thing to @UniqSet@, as opposed to @Set@.)
  8. The interface is based on @FiniteMap@s, but the implementation uses
  9. @Data.IntMap@, which is both maintained and faster than the past
  10. implementation (see commit log).
  11. The @UniqFM@ interface maps directly to Data.IntMap, only
  12. ``Data.IntMap.union'' is left-biased and ``plusUFM'' right-biased
  13. and ``addToUFM\_C'' and ``Data.IntMap.insertWith'' differ in the order
  14. of arguments of combining function.
  15. -}
  16. {-# LANGUAGE CPP #-}
  17. {-# LANGUAGE DeriveDataTypeable #-}
  18. {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  19. {-# OPTIONS_GHC -Wall #-}
  20. module UniqFM (
  21. -- * Unique-keyed mappings
  22. UniqFM, -- abstract type
  23. -- ** Manipulating those mappings
  24. emptyUFM,
  25. unitUFM,
  26. unitDirectlyUFM,
  27. listToUFM,
  28. listToUFM_Directly,
  29. listToUFM_C,
  30. addToUFM,addToUFM_C,addToUFM_Acc,
  31. addListToUFM,addListToUFM_C,
  32. addToUFM_Directly,
  33. addListToUFM_Directly,
  34. adjustUFM, alterUFM,
  35. adjustUFM_Directly,
  36. delFromUFM,
  37. delFromUFM_Directly,
  38. delListFromUFM,
  39. delListFromUFM_Directly,
  40. plusUFM,
  41. plusUFM_C,
  42. plusUFM_CD,
  43. minusUFM,
  44. intersectUFM,
  45. intersectUFM_C,
  46. disjointUFM,
  47. nonDetFoldUFM, foldUFM, nonDetFoldUFM_Directly,
  48. anyUFM, allUFM, seqEltsUFM,
  49. mapUFM, mapUFM_Directly,
  50. elemUFM, elemUFM_Directly,
  51. filterUFM, filterUFM_Directly, partitionUFM,
  52. sizeUFM,
  53. isNullUFM,
  54. lookupUFM, lookupUFM_Directly,
  55. lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
  56. nonDetEltsUFM, eltsUFM, nonDetKeysUFM,
  57. ufmToSet_Directly,
  58. nonDetUFMToList, ufmToIntMap,
  59. pprUniqFM, pprUFM, pprUFMWithKeys, pluralUFM
  60. ) where
  61. import Unique ( Uniquable(..), Unique, getKey )
  62. import Outputable
  63. import qualified Data.IntMap as M
  64. import qualified Data.IntSet as S
  65. import Data.Typeable
  66. import Data.Data
  67. #if __GLASGOW_HASKELL__ > 710
  68. import Data.Semigroup ( Semigroup )
  69. import qualified Data.Semigroup as Semigroup
  70. #endif
  71. newtype UniqFM ele = UFM (M.IntMap ele)
  72. deriving (Data, Eq, Functor, Typeable)
  73. -- We used to derive Traversable and Foldable, but they were nondeterministic
  74. -- and not obvious at the call site. You can use explicit nonDetEltsUFM
  75. -- and fold a list if needed.
  76. -- See Note [Deterministic UniqFM] in UniqDFM to learn about determinism.
  77. emptyUFM :: UniqFM elt
  78. emptyUFM = UFM M.empty
  79. isNullUFM :: UniqFM elt -> Bool
  80. isNullUFM (UFM m) = M.null m
  81. unitUFM :: Uniquable key => key -> elt -> UniqFM elt
  82. unitUFM k v = UFM (M.singleton (getKey $ getUnique k) v)
  83. -- when you've got the Unique already
  84. unitDirectlyUFM :: Unique -> elt -> UniqFM elt
  85. unitDirectlyUFM u v = UFM (M.singleton (getKey u) v)
  86. listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
  87. listToUFM = foldl (\m (k, v) -> addToUFM m k v) emptyUFM
  88. listToUFM_Directly :: [(Unique, elt)] -> UniqFM elt
  89. listToUFM_Directly = foldl (\m (u, v) -> addToUFM_Directly m u v) emptyUFM
  90. listToUFM_C
  91. :: Uniquable key
  92. => (elt -> elt -> elt)
  93. -> [(key, elt)]
  94. -> UniqFM elt
  95. listToUFM_C f = foldl (\m (k, v) -> addToUFM_C f m k v) emptyUFM
  96. addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
  97. addToUFM (UFM m) k v = UFM (M.insert (getKey $ getUnique k) v m)
  98. addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
  99. addListToUFM = foldl (\m (k, v) -> addToUFM m k v)
  100. addListToUFM_Directly :: UniqFM elt -> [(Unique,elt)] -> UniqFM elt
  101. addListToUFM_Directly = foldl (\m (k, v) -> addToUFM_Directly m k v)
  102. addToUFM_Directly :: UniqFM elt -> Unique -> elt -> UniqFM elt
  103. addToUFM_Directly (UFM m) u v = UFM (M.insert (getKey u) v m)
  104. addToUFM_C
  105. :: Uniquable key
  106. => (elt -> elt -> elt) -- old -> new -> result
  107. -> UniqFM elt -- old
  108. -> key -> elt -- new
  109. -> UniqFM elt -- result
  110. -- Arguments of combining function of M.insertWith and addToUFM_C are flipped.
  111. addToUFM_C f (UFM m) k v =
  112. UFM (M.insertWith (flip f) (getKey $ getUnique k) v m)
  113. addToUFM_Acc
  114. :: Uniquable key
  115. => (elt -> elts -> elts) -- Add to existing
  116. -> (elt -> elts) -- New element
  117. -> UniqFM elts -- old
  118. -> key -> elt -- new
  119. -> UniqFM elts -- result
  120. addToUFM_Acc exi new (UFM m) k v =
  121. UFM (M.insertWith (\_new old -> exi v old) (getKey $ getUnique k) (new v) m)
  122. alterUFM
  123. :: Uniquable key
  124. => (Maybe elt -> Maybe elt) -- How to adjust
  125. -> UniqFM elt -- old
  126. -> key -- new
  127. -> UniqFM elt -- result
  128. alterUFM f (UFM m) k = UFM (M.alter f (getKey $ getUnique k) m)
  129. addListToUFM_C
  130. :: Uniquable key
  131. => (elt -> elt -> elt)
  132. -> UniqFM elt -> [(key,elt)]
  133. -> UniqFM elt
  134. addListToUFM_C f = foldl (\m (k, v) -> addToUFM_C f m k v)
  135. adjustUFM :: Uniquable key => (elt -> elt) -> UniqFM elt -> key -> UniqFM elt
  136. adjustUFM f (UFM m) k = UFM (M.adjust f (getKey $ getUnique k) m)
  137. adjustUFM_Directly :: (elt -> elt) -> UniqFM elt -> Unique -> UniqFM elt
  138. adjustUFM_Directly f (UFM m) u = UFM (M.adjust f (getKey u) m)
  139. delFromUFM :: Uniquable key => UniqFM elt -> key -> UniqFM elt
  140. delFromUFM (UFM m) k = UFM (M.delete (getKey $ getUnique k) m)
  141. delListFromUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
  142. delListFromUFM = foldl delFromUFM
  143. delListFromUFM_Directly :: UniqFM elt -> [Unique] -> UniqFM elt
  144. delListFromUFM_Directly = foldl delFromUFM_Directly
  145. delFromUFM_Directly :: UniqFM elt -> Unique -> UniqFM elt
  146. delFromUFM_Directly (UFM m) u = UFM (M.delete (getKey u) m)
  147. -- Bindings in right argument shadow those in the left
  148. plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
  149. -- M.union is left-biased, plusUFM should be right-biased.
  150. plusUFM (UFM x) (UFM y) = UFM (M.union y x)
  151. -- Note (M.union y x), with arguments flipped
  152. -- M.union is left-biased, plusUFM should be right-biased.
  153. plusUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> UniqFM elt -> UniqFM elt
  154. plusUFM_C f (UFM x) (UFM y) = UFM (M.unionWith f x y)
  155. -- | `plusUFM_CD f m1 d1 m2 d2` merges the maps using `f` as the
  156. -- combinding function and `d1` resp. `d2` as the default value if
  157. -- there is no entry in `m1` reps. `m2`. The domain is the union of
  158. -- the domains of `m1` and `m2`.
  159. --
  160. -- Representative example:
  161. --
  162. -- @
  163. -- plusUFM_CD f {A: 1, B: 2} 23 {B: 3, C: 4} 42
  164. -- == {A: f 1 42, B: f 2 3, C: f 23 4 }
  165. -- @
  166. plusUFM_CD
  167. :: (elt -> elt -> elt)
  168. -> UniqFM elt -- map X
  169. -> elt -- default for X
  170. -> UniqFM elt -- map Y
  171. -> elt -- default for Y
  172. -> UniqFM elt
  173. plusUFM_CD f (UFM xm) dx (UFM ym) dy
  174. = UFM $ M.mergeWithKey
  175. (\_ x y -> Just (x `f` y))
  176. (M.map (\x -> x `f` dy))
  177. (M.map (\y -> dx `f` y))
  178. xm ym
  179. minusUFM :: UniqFM elt1 -> UniqFM elt2 -> UniqFM elt1
  180. minusUFM (UFM x) (UFM y) = UFM (M.difference x y)
  181. intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
  182. intersectUFM (UFM x) (UFM y) = UFM (M.intersection x y)
  183. intersectUFM_C
  184. :: (elt1 -> elt2 -> elt3)
  185. -> UniqFM elt1
  186. -> UniqFM elt2
  187. -> UniqFM elt3
  188. intersectUFM_C f (UFM x) (UFM y) = UFM (M.intersectionWith f x y)
  189. disjointUFM :: UniqFM elt1 -> UniqFM elt2 -> Bool
  190. disjointUFM (UFM x) (UFM y) = M.null (M.intersection x y)
  191. foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
  192. foldUFM k z (UFM m) = M.fold k z m
  193. mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
  194. mapUFM f (UFM m) = UFM (M.map f m)
  195. mapUFM_Directly :: (Unique -> elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
  196. mapUFM_Directly f (UFM m) = UFM (M.mapWithKey (f . getUnique) m)
  197. filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
  198. filterUFM p (UFM m) = UFM (M.filter p m)
  199. filterUFM_Directly :: (Unique -> elt -> Bool) -> UniqFM elt -> UniqFM elt
  200. filterUFM_Directly p (UFM m) = UFM (M.filterWithKey (p . getUnique) m)
  201. partitionUFM :: (elt -> Bool) -> UniqFM elt -> (UniqFM elt, UniqFM elt)
  202. partitionUFM p (UFM m) =
  203. case M.partition p m of
  204. (left, right) -> (UFM left, UFM right)
  205. sizeUFM :: UniqFM elt -> Int
  206. sizeUFM (UFM m) = M.size m
  207. elemUFM :: Uniquable key => key -> UniqFM elt -> Bool
  208. elemUFM k (UFM m) = M.member (getKey $ getUnique k) m
  209. elemUFM_Directly :: Unique -> UniqFM elt -> Bool
  210. elemUFM_Directly u (UFM m) = M.member (getKey u) m
  211. lookupUFM :: Uniquable key => UniqFM elt -> key -> Maybe elt
  212. lookupUFM (UFM m) k = M.lookup (getKey $ getUnique k) m
  213. -- when you've got the Unique already
  214. lookupUFM_Directly :: UniqFM elt -> Unique -> Maybe elt
  215. lookupUFM_Directly (UFM m) u = M.lookup (getKey u) m
  216. lookupWithDefaultUFM :: Uniquable key => UniqFM elt -> elt -> key -> elt
  217. lookupWithDefaultUFM (UFM m) v k = M.findWithDefault v (getKey $ getUnique k) m
  218. lookupWithDefaultUFM_Directly :: UniqFM elt -> elt -> Unique -> elt
  219. lookupWithDefaultUFM_Directly (UFM m) v u = M.findWithDefault v (getKey u) m
  220. eltsUFM :: UniqFM elt -> [elt]
  221. eltsUFM (UFM m) = M.elems m
  222. ufmToSet_Directly :: UniqFM elt -> S.IntSet
  223. ufmToSet_Directly (UFM m) = M.keysSet m
  224. anyUFM :: (elt -> Bool) -> UniqFM elt -> Bool
  225. anyUFM p (UFM m) = M.fold ((||) . p) False m
  226. allUFM :: (elt -> Bool) -> UniqFM elt -> Bool
  227. allUFM p (UFM m) = M.fold ((&&) . p) True m
  228. seqEltsUFM :: ([elt] -> ()) -> UniqFM elt -> ()
  229. seqEltsUFM seqList = seqList . nonDetEltsUFM
  230. -- It's OK to use nonDetEltsUFM here because the type guarantees that
  231. -- the only interesting thing this function can do is to force the
  232. -- elements.
  233. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  234. -- If you use this please provide a justification why it doesn't introduce
  235. -- nondeterminism.
  236. nonDetEltsUFM :: UniqFM elt -> [elt]
  237. nonDetEltsUFM (UFM m) = M.elems m
  238. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  239. -- If you use this please provide a justification why it doesn't introduce
  240. -- nondeterminism.
  241. nonDetKeysUFM :: UniqFM elt -> [Unique]
  242. nonDetKeysUFM (UFM m) = map getUnique $ M.keys m
  243. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  244. -- If you use this please provide a justification why it doesn't introduce
  245. -- nondeterminism.
  246. nonDetFoldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
  247. nonDetFoldUFM k z (UFM m) = M.fold k z m
  248. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  249. -- If you use this please provide a justification why it doesn't introduce
  250. -- nondeterminism.
  251. nonDetFoldUFM_Directly:: (Unique -> elt -> a -> a) -> a -> UniqFM elt -> a
  252. nonDetFoldUFM_Directly k z (UFM m) = M.foldWithKey (k . getUnique) z m
  253. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  254. -- If you use this please provide a justification why it doesn't introduce
  255. -- nondeterminism.
  256. nonDetUFMToList :: UniqFM elt -> [(Unique, elt)]
  257. nonDetUFMToList (UFM m) = map (\(k, v) -> (getUnique k, v)) $ M.toList m
  258. ufmToIntMap :: UniqFM elt -> M.IntMap elt
  259. ufmToIntMap (UFM m) = m
  260. -- Instances
  261. #if __GLASGOW_HASKELL__ > 710
  262. instance Semigroup (UniqFM a) where
  263. (<>) = plusUFM
  264. #endif
  265. instance Monoid (UniqFM a) where
  266. mempty = emptyUFM
  267. mappend = plusUFM
  268. -- Output-ery
  269. instance Outputable a => Outputable (UniqFM a) where
  270. ppr ufm = pprUniqFM ppr ufm
  271. pprUniqFM :: (a -> SDoc) -> UniqFM a -> SDoc
  272. pprUniqFM ppr_elt ufm
  273. = brackets $ fsep $ punctuate comma $
  274. [ ppr uq <+> text ":->" <+> ppr_elt elt
  275. | (uq, elt) <- nonDetUFMToList ufm ]
  276. -- It's OK to use nonDetUFMToList here because we only use it for
  277. -- pretty-printing.
  278. -- | Pretty-print a non-deterministic set.
  279. -- The order of variables is non-deterministic and for pretty-printing that
  280. -- shouldn't be a problem.
  281. -- Having this function helps contain the non-determinism created with
  282. -- nonDetEltsUFM.
  283. pprUFM :: UniqFM a -- ^ The things to be pretty printed
  284. -> ([a] -> SDoc) -- ^ The pretty printing function to use on the elements
  285. -> SDoc -- ^ 'SDoc' where the things have been pretty
  286. -- printed
  287. pprUFM ufm pp = pp (nonDetEltsUFM ufm)
  288. -- | Pretty-print a non-deterministic set.
  289. -- The order of variables is non-deterministic and for pretty-printing that
  290. -- shouldn't be a problem.
  291. -- Having this function helps contain the non-determinism created with
  292. -- nonDetUFMToList.
  293. pprUFMWithKeys
  294. :: UniqFM a -- ^ The things to be pretty printed
  295. -> ([(Unique, a)] -> SDoc) -- ^ The pretty printing function to use on the elements
  296. -> SDoc -- ^ 'SDoc' where the things have been pretty
  297. -- printed
  298. pprUFMWithKeys ufm pp = pp (nonDetUFMToList ufm)
  299. -- | Determines the pluralisation suffix appropriate for the length of a set
  300. -- in the same way that plural from Outputable does for lists.
  301. pluralUFM :: UniqFM a -> SDoc
  302. pluralUFM ufm
  303. | sizeUFM ufm == 1 = empty
  304. | otherwise = char 's'