PageRenderTime 66ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/utils/UniqFM.lhs

https://bitbucket.org/khibino/ghc-hack
Haskell | 276 lines | 208 code | 46 blank | 22 comment | 1 complexity | ef682227d16a694d2d64e9ac8149e5de MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause, LGPL-3.0
  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 -fno-warn-tabs -XGeneralizedNewtypeDeriving #-}
  18. -- The above warning supression flag is a temporary kludge.
  19. -- While working on this module you are encouraged to remove it and
  20. -- detab the module (please do the detabbing in a separate patch). See
  21. -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces
  22. -- for details
  23. {-# OPTIONS -Wall #-}
  24. module UniqFM (
  25. -- * Unique-keyed mappings
  26. UniqFM, -- abstract type
  27. -- ** Manipulating those mappings
  28. emptyUFM,
  29. unitUFM,
  30. unitDirectlyUFM,
  31. listToUFM,
  32. listToUFM_Directly,
  33. listToUFM_C,
  34. addToUFM,addToUFM_C,addToUFM_Acc,
  35. addListToUFM,addListToUFM_C,
  36. addToUFM_Directly,
  37. addListToUFM_Directly,
  38. adjustUFM, alterUFM,
  39. adjustUFM_Directly,
  40. delFromUFM,
  41. delFromUFM_Directly,
  42. delListFromUFM,
  43. plusUFM,
  44. plusUFM_C,
  45. minusUFM,
  46. intersectUFM,
  47. intersectUFM_C,
  48. foldUFM, foldUFM_Directly,
  49. mapUFM, mapUFM_Directly,
  50. elemUFM, elemUFM_Directly,
  51. filterUFM, filterUFM_Directly,
  52. sizeUFM,
  53. isNullUFM,
  54. lookupUFM, lookupUFM_Directly,
  55. lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
  56. eltsUFM, keysUFM, splitUFM,
  57. ufmToList,
  58. joinUFM
  59. ) where
  60. import Unique ( Uniquable(..), Unique, getKey )
  61. import Outputable
  62. import Compiler.Hoopl hiding (Unique)
  63. import Data.Function (on)
  64. import qualified Data.IntMap as M
  65. import qualified Data.Foldable as Foldable
  66. import qualified Data.Traversable as Traversable
  67. import Data.Typeable
  68. import Data.Data
  69. \end{code}
  70. %************************************************************************
  71. %* *
  72. \subsection{The signature of the module}
  73. %* *
  74. %************************************************************************
  75. \begin{code}
  76. emptyUFM :: UniqFM elt
  77. isNullUFM :: UniqFM elt -> Bool
  78. unitUFM :: Uniquable key => key -> elt -> UniqFM elt
  79. unitDirectlyUFM -- got the Unique already
  80. :: Unique -> elt -> UniqFM elt
  81. listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
  82. listToUFM_Directly
  83. :: [(Unique, elt)] -> UniqFM elt
  84. listToUFM_C :: Uniquable key => (elt -> elt -> elt)
  85. -> [(key, elt)]
  86. -> UniqFM elt
  87. addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
  88. addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
  89. addListToUFM_Directly :: UniqFM elt -> [(Unique,elt)] -> UniqFM elt
  90. addToUFM_Directly
  91. :: UniqFM elt -> Unique -> elt -> UniqFM elt
  92. addToUFM_C :: Uniquable key => (elt -> elt -> elt) -- old -> new -> result
  93. -> UniqFM elt -- old
  94. -> key -> elt -- new
  95. -> UniqFM elt -- result
  96. addToUFM_Acc :: Uniquable key =>
  97. (elt -> elts -> elts) -- Add to existing
  98. -> (elt -> elts) -- New element
  99. -> UniqFM elts -- old
  100. -> key -> elt -- new
  101. -> UniqFM elts -- result
  102. alterUFM :: Uniquable key =>
  103. (Maybe elt -> Maybe elt) -- How to adjust
  104. -> UniqFM elt -- old
  105. -> key -- new
  106. -> UniqFM elt -- result
  107. addListToUFM_C :: Uniquable key => (elt -> elt -> elt)
  108. -> UniqFM elt -> [(key,elt)]
  109. -> UniqFM elt
  110. adjustUFM :: Uniquable key => (elt -> elt) -> UniqFM elt -> key -> UniqFM elt
  111. adjustUFM_Directly :: (elt -> elt) -> UniqFM elt -> Unique -> UniqFM elt
  112. delFromUFM :: Uniquable key => UniqFM elt -> key -> UniqFM elt
  113. delListFromUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
  114. delFromUFM_Directly :: UniqFM elt -> Unique -> UniqFM elt
  115. -- Bindings in right argument shadow those in the left
  116. plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
  117. plusUFM_C :: (elt -> elt -> elt)
  118. -> UniqFM elt -> UniqFM elt -> UniqFM elt
  119. minusUFM :: UniqFM elt1 -> UniqFM elt2 -> UniqFM elt1
  120. intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
  121. intersectUFM_C :: (elt1 -> elt2 -> elt3)
  122. -> UniqFM elt1 -> UniqFM elt2 -> UniqFM elt3
  123. foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
  124. foldUFM_Directly:: (Unique -> elt -> a -> a) -> a -> UniqFM elt -> a
  125. mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
  126. mapUFM_Directly :: (Unique -> elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
  127. filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
  128. filterUFM_Directly :: (Unique -> elt -> Bool) -> UniqFM elt -> UniqFM elt
  129. sizeUFM :: UniqFM elt -> Int
  130. --hashUFM :: UniqFM elt -> Int
  131. elemUFM :: Uniquable key => key -> UniqFM elt -> Bool
  132. elemUFM_Directly:: Unique -> UniqFM elt -> Bool
  133. splitUFM :: Uniquable key => UniqFM elt -> key -> (UniqFM elt, Maybe elt, UniqFM elt)
  134. -- Splits a UFM into things less than, equal to, and greater than the key
  135. lookupUFM :: Uniquable key => UniqFM elt -> key -> Maybe elt
  136. lookupUFM_Directly -- when you've got the Unique already
  137. :: UniqFM elt -> Unique -> Maybe elt
  138. lookupWithDefaultUFM
  139. :: Uniquable key => UniqFM elt -> elt -> key -> elt
  140. lookupWithDefaultUFM_Directly
  141. :: UniqFM elt -> elt -> Unique -> elt
  142. keysUFM :: UniqFM elt -> [Unique] -- Get the keys
  143. eltsUFM :: UniqFM elt -> [elt]
  144. ufmToList :: UniqFM elt -> [(Unique, elt)]
  145. \end{code}
  146. %************************************************************************
  147. %* *
  148. \subsection{Implementation using ``Data.IntMap''}
  149. %* *
  150. %************************************************************************
  151. \begin{code}
  152. newtype UniqFM ele = UFM { unUFM :: M.IntMap ele }
  153. deriving (Typeable,Data, Traversable.Traversable, Functor)
  154. instance Eq ele => Eq (UniqFM ele) where
  155. (==) = (==) `on` unUFM
  156. {-
  157. instance Functor UniqFM where
  158. fmap f = fmap f . unUFM
  159. instance Traversable.Traversable UniqFM where
  160. traverse f = Traversable.traverse f . unUFM
  161. -}
  162. instance Foldable.Foldable UniqFM where
  163. foldMap f = Foldable.foldMap f . unUFM
  164. emptyUFM = UFM M.empty
  165. isNullUFM (UFM m) = M.null m
  166. unitUFM k v = UFM (M.singleton (getKey $ getUnique k) v)
  167. unitDirectlyUFM u v = UFM (M.singleton (getKey u) v)
  168. listToUFM = foldl (\m (k, v) -> addToUFM m k v) emptyUFM
  169. listToUFM_Directly = foldl (\m (u, v) -> addToUFM_Directly m u v) emptyUFM
  170. listToUFM_C f = foldl (\m (k, v) -> addToUFM_C f m k v) emptyUFM
  171. alterUFM f (UFM m) k = UFM (M.alter f (getKey $ getUnique k) m)
  172. addToUFM (UFM m) k v = UFM (M.insert (getKey $ getUnique k) v m)
  173. addListToUFM = foldl (\m (k, v) -> addToUFM m k v)
  174. addListToUFM_Directly = foldl (\m (k, v) -> addToUFM_Directly m k v)
  175. addToUFM_Directly (UFM m) u v = UFM (M.insert (getKey u) v m)
  176. -- Arguments of combining function of M.insertWith and addToUFM_C are flipped.
  177. addToUFM_C f (UFM m) k v =
  178. UFM (M.insertWith (flip f) (getKey $ getUnique k) v m)
  179. addToUFM_Acc exi new (UFM m) k v =
  180. UFM (M.insertWith (\_new old -> exi v old) (getKey $ getUnique k) (new v) m)
  181. addListToUFM_C f = foldl (\m (k, v) -> addToUFM_C f m k v)
  182. adjustUFM f (UFM m) k = UFM (M.adjust f (getKey $ getUnique k) m)
  183. adjustUFM_Directly f (UFM m) u = UFM (M.adjust f (getKey u) m)
  184. delFromUFM (UFM m) k = UFM (M.delete (getKey $ getUnique k) m)
  185. delListFromUFM = foldl delFromUFM
  186. delFromUFM_Directly (UFM m) u = UFM (M.delete (getKey u) m)
  187. -- M.union is left-biased, plusUFM should be right-biased.
  188. plusUFM (UFM x) (UFM y) = UFM (M.union y x)
  189. plusUFM_C f (UFM x) (UFM y) = UFM (M.unionWith f x y)
  190. minusUFM (UFM x) (UFM y) = UFM (M.difference x y)
  191. intersectUFM (UFM x) (UFM y) = UFM (M.intersection x y)
  192. intersectUFM_C f (UFM x) (UFM y) = UFM (M.intersectionWith f x y)
  193. foldUFM k z (UFM m) = M.fold k z m
  194. foldUFM_Directly k z (UFM m) = M.foldWithKey (k . getUnique) z m
  195. mapUFM f (UFM m) = UFM (M.map f m)
  196. mapUFM_Directly f (UFM m) = UFM (M.mapWithKey (f . getUnique) m)
  197. filterUFM p (UFM m) = UFM (M.filter p m)
  198. filterUFM_Directly p (UFM m) = UFM (M.filterWithKey (p . getUnique) m)
  199. sizeUFM (UFM m) = M.size m
  200. elemUFM k (UFM m) = M.member (getKey $ getUnique k) m
  201. elemUFM_Directly u (UFM m) = M.member (getKey u) m
  202. splitUFM (UFM m) k = case M.splitLookup (getKey $ getUnique k) m of
  203. (less, equal, greater) -> (UFM less, equal, UFM greater)
  204. lookupUFM (UFM m) k = M.lookup (getKey $ getUnique k) m
  205. lookupUFM_Directly (UFM m) u = M.lookup (getKey u) m
  206. lookupWithDefaultUFM (UFM m) v k = M.findWithDefault v (getKey $ getUnique k) m
  207. lookupWithDefaultUFM_Directly (UFM m) v u = M.findWithDefault v (getKey u) m
  208. keysUFM (UFM m) = map getUnique $ M.keys m
  209. eltsUFM (UFM m) = M.elems m
  210. ufmToList (UFM m) = map (\(k, v) -> (getUnique k, v)) $ M.toList m
  211. -- Hoopl
  212. joinUFM :: JoinFun v -> JoinFun (UniqFM v)
  213. joinUFM eltJoin l (OldFact old) (NewFact new) = foldUFM_Directly add (NoChange, old) new
  214. where add k new_v (ch, joinmap) =
  215. case lookupUFM_Directly joinmap k of
  216. Nothing -> (SomeChange, addToUFM_Directly joinmap k new_v)
  217. Just old_v -> case eltJoin l (OldFact old_v) (NewFact new_v) of
  218. (SomeChange, v') -> (SomeChange, addToUFM_Directly joinmap k v')
  219. (NoChange, _) -> (ch, joinmap)
  220. \end{code}
  221. %************************************************************************
  222. %* *
  223. \subsection{Output-ery}
  224. %* *
  225. %************************************************************************
  226. \begin{code}
  227. instance Outputable a => Outputable (UniqFM a) where
  228. ppr ufm = ppr (ufmToList ufm)
  229. \end{code}