/compiler/Eta/Utils/UniqSet.hs

https://github.com/typelead/eta · Haskell · 210 lines · 129 code · 35 blank · 46 comment · 0 complexity · 269640d75b453772fd0bd392dac3ab88 MD5 · raw file

  1. {-
  2. (c) The University of Glasgow 2006
  3. (c) The AQUA Project, Glasgow University, 1994-1998
  4. \section[UniqSet]{Specialised sets, for things with @Uniques@}
  5. Based on @UniqFMs@ (as you would expect).
  6. Basically, the things need to be in class @Uniquable@.
  7. -}
  8. {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  9. {-# LANGUAGE CPP #-}
  10. {-# LANGUAGE DeriveDataTypeable #-}
  11. module Eta.Utils.UniqSet (
  12. -- * Unique set type
  13. UniqSet, -- type synonym for UniqFM a
  14. getUniqSet,
  15. pprUniqSet,
  16. -- ** Manipulating these sets
  17. emptyUniqSet,
  18. unitUniqSet,
  19. mkUniqSet,
  20. addOneToUniqSet,
  21. addOneToUniqSet_C, -- TODO: Remove
  22. addListToUniqSet,
  23. delOneFromUniqSet, delOneFromUniqSet_Directly, delListFromUniqSet,
  24. delListFromUniqSet_Directly,
  25. unionUniqSets, unionManyUniqSets,
  26. minusUniqSet, uniqSetMinusUFM,
  27. intersectUniqSets,
  28. foldUniqSet, -- TODO: Remove
  29. restrictUniqSetToUFM,
  30. uniqSetAny, uniqSetAll,
  31. elementOfUniqSet,
  32. elemUniqSet_Directly,
  33. filterUniqSet,
  34. filterUniqSet_Directly,
  35. sizeUniqSet,
  36. isEmptyUniqSet,
  37. lookupUniqSet,
  38. uniqSetToList, -- TODO: Remove
  39. lookupUniqSet_Directly,
  40. partitionUniqSet,
  41. mapUniqSet,
  42. unsafeUFMToUniqSet,
  43. nonDetEltsUniqSet,
  44. nonDetKeysUniqSet,
  45. nonDetFoldUniqSet,
  46. nonDetFoldUniqSet_Directly
  47. ) where
  48. import Eta.Utils.UniqFM
  49. import Eta.BasicTypes.Unique
  50. import Data.Coerce
  51. import Eta.Utils.Outputable
  52. import Data.Foldable (foldl')
  53. import Data.Data
  54. #if __GLASGOW_HASKELL__ >= 801
  55. import qualified Data.Semigroup
  56. #endif
  57. {-
  58. ************************************************************************
  59. * *
  60. \subsection{The signature of the module}
  61. * *
  62. ************************************************************************
  63. -}
  64. emptyUniqSet :: UniqSet a
  65. unitUniqSet :: Uniquable a => a -> UniqSet a
  66. mkUniqSet :: Uniquable a => [a] -> UniqSet a
  67. addOneToUniqSet :: Uniquable a => UniqSet a -> a -> UniqSet a
  68. addOneToUniqSet_C :: Uniquable a => (a -> a -> a) -> UniqSet a -> a -> UniqSet a
  69. addListToUniqSet :: Uniquable a => UniqSet a -> [a] -> UniqSet a
  70. delOneFromUniqSet :: Uniquable a => UniqSet a -> a -> UniqSet a
  71. delOneFromUniqSet_Directly :: UniqSet a -> Unique -> UniqSet a
  72. delListFromUniqSet :: Uniquable a => UniqSet a -> [a] -> UniqSet a
  73. delListFromUniqSet_Directly :: UniqSet a -> [Unique] -> UniqSet a
  74. unionUniqSets :: UniqSet a -> UniqSet a -> UniqSet a
  75. unionManyUniqSets :: [UniqSet a] -> UniqSet a
  76. minusUniqSet :: UniqSet a -> UniqSet a -> UniqSet a
  77. intersectUniqSets :: UniqSet a -> UniqSet a -> UniqSet a
  78. restrictUniqSetToUFM :: UniqSet a -> UniqFM b -> UniqSet a
  79. uniqSetMinusUFM :: UniqSet a -> UniqFM b -> UniqSet a
  80. foldUniqSet :: (a -> b -> b) -> b -> UniqSet a -> b
  81. elementOfUniqSet :: Uniquable a => a -> UniqSet a -> Bool
  82. elemUniqSet_Directly :: Unique -> UniqSet a -> Bool
  83. filterUniqSet :: (a -> Bool) -> UniqSet a -> UniqSet a
  84. filterUniqSet_Directly :: (Unique -> elt -> Bool) -> UniqSet elt -> UniqSet elt
  85. partitionUniqSet :: (a -> Bool) -> UniqSet a -> (UniqSet a, UniqSet a)
  86. sizeUniqSet :: UniqSet a -> Int
  87. isEmptyUniqSet :: UniqSet a -> Bool
  88. lookupUniqSet :: Uniquable a => UniqSet b -> a -> Maybe b
  89. lookupUniqSet_Directly :: UniqSet a -> Unique -> Maybe a
  90. uniqSetToList :: UniqSet a -> [a]
  91. nonDetEltsUniqSet :: UniqSet elt -> [elt]
  92. nonDetKeysUniqSet :: UniqSet elt -> [Unique]
  93. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  94. -- If you use this please provide a justification why it doesn't introduce
  95. -- nondeterminism.
  96. nonDetFoldUniqSet :: (elt -> a -> a) -> a -> UniqSet elt -> a
  97. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  98. -- If you use this please provide a justification why it doesn't introduce
  99. -- nondeterminism.
  100. nonDetFoldUniqSet_Directly:: (Unique -> elt -> a -> a) -> a -> UniqSet elt -> a
  101. mapUniqSet :: Uniquable b => (a -> b) -> UniqSet a -> UniqSet b
  102. {-
  103. ************************************************************************
  104. * *
  105. \subsection{Implementation using ``UniqFM''}
  106. * *
  107. ************************************************************************
  108. -}
  109. -- Note [Unsound mapUniqSet]
  110. -- ~~~~~~~~~~~~~~~~~~~~~~~~~
  111. -- UniqSet has the following invariant:
  112. -- The keys in the map are the uniques of the values
  113. -- It means that to implement mapUniqSet you'd have to update
  114. -- both the keys and the values. There used to be an implementation
  115. -- that only updated the values and it's been removed, because it broke
  116. -- the invariant.
  117. newtype UniqSet a = UniqSet {getUniqSet' :: UniqFM a} deriving Data
  118. getUniqSet :: UniqSet a -> UniqFM a
  119. getUniqSet = getUniqSet'
  120. -- | 'unsafeUFMToUniqSet' converts a @'UniqFM' a@ into a @'UniqSet' a@
  121. -- assuming, without checking, that it maps each 'Unique' to a value
  122. -- that has that 'Unique'. See Note [Unsound mapUniqSet].
  123. unsafeUFMToUniqSet :: UniqFM a -> UniqSet a
  124. unsafeUFMToUniqSet = UniqSet
  125. instance Outputable a => Outputable (UniqSet a) where
  126. ppr = pprUniqSet ppr
  127. #if __GLASGOW_HASKELL__ >= 801
  128. instance Data.Semigroup.Semigroup (UniqSet a) where
  129. (<>) = mappend
  130. #endif
  131. instance Monoid (UniqSet a) where
  132. mempty = UniqSet mempty
  133. UniqSet s `mappend` UniqSet t = UniqSet (s `mappend` t)
  134. pprUniqSet :: (a -> SDoc) -> UniqSet a -> SDoc
  135. pprUniqSet f (UniqSet s) = pprUniqFM f s
  136. emptyUniqSet = UniqSet emptyUFM
  137. unitUniqSet x = UniqSet $ unitUFM x x
  138. mkUniqSet = foldl' addOneToUniqSet emptyUniqSet
  139. addOneToUniqSet (UniqSet set) x = UniqSet (addToUFM set x x)
  140. addOneToUniqSet_C f (UniqSet set) x = UniqSet (addToUFM_C f set x x)
  141. addListToUniqSet = foldl' addOneToUniqSet
  142. delOneFromUniqSet (UniqSet s) a = UniqSet (delFromUFM s a)
  143. delOneFromUniqSet_Directly (UniqSet s) u = UniqSet (delFromUFM_Directly s u)
  144. delListFromUniqSet (UniqSet s) l = UniqSet (delListFromUFM s l)
  145. delListFromUniqSet_Directly (UniqSet s) l =
  146. UniqSet (delListFromUFM_Directly s l)
  147. unionUniqSets (UniqSet s) (UniqSet t) = UniqSet (plusUFM s t)
  148. unionManyUniqSets = foldl' (flip unionUniqSets) emptyUniqSet
  149. minusUniqSet (UniqSet s) (UniqSet t) = UniqSet (minusUFM s t)
  150. uniqSetMinusUFM (UniqSet s) t = UniqSet (minusUFM s t)
  151. intersectUniqSets (UniqSet s) (UniqSet t) = UniqSet (intersectUFM s t)
  152. restrictUniqSetToUFM (UniqSet s) m = UniqSet (intersectUFM s m)
  153. foldUniqSet f x (UniqSet s) = foldUFM f x s
  154. elementOfUniqSet a (UniqSet s) = elemUFM a s
  155. elemUniqSet_Directly a (UniqSet s) = elemUFM_Directly a s
  156. filterUniqSet p (UniqSet s) = UniqSet (filterUFM p s)
  157. filterUniqSet_Directly f (UniqSet s) = UniqSet (filterUFM_Directly f s)
  158. partitionUniqSet p (UniqSet s) = coerce (partitionUFM p s)
  159. sizeUniqSet (UniqSet s) = sizeUFM s
  160. isEmptyUniqSet (UniqSet s) = isNullUFM s
  161. lookupUniqSet (UniqSet s) k = lookupUFM s k
  162. lookupUniqSet_Directly (UniqSet s) k = lookupUFM_Directly s k
  163. uniqSetToList (UniqSet s) = eltsUFM s
  164. uniqSetAny :: (a -> Bool) -> UniqSet a -> Bool
  165. uniqSetAny p (UniqSet s) = anyUFM p s
  166. uniqSetAll :: (a -> Bool) -> UniqSet a -> Bool
  167. uniqSetAll p (UniqSet s) = allUFM p s
  168. nonDetFoldUniqSet c n (UniqSet s) = nonDetFoldUFM c n s
  169. nonDetFoldUniqSet_Directly f n (UniqSet s) = nonDetFoldUFM_Directly f n s
  170. nonDetEltsUniqSet = nonDetEltsUFM . getUniqSet'
  171. nonDetKeysUniqSet = nonDetKeysUFM . getUniqSet'
  172. mapUniqSet f = mkUniqSet . map f . nonDetEltsUniqSet