/compiler/GHC/Types/Unique/Set.hs

https://github.com/bgamari/ghc · Haskell · 198 lines · 116 code · 43 blank · 39 comment · 1 complexity · 3f1f4a598c6e6407164fdb3c3565d491 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 DeriveDataTypeable #-}
  10. module GHC.Types.Unique.Set (
  11. -- * Unique set type
  12. UniqSet, -- type synonym for UniqFM a
  13. getUniqSet,
  14. pprUniqSet,
  15. -- ** Manipulating these sets
  16. emptyUniqSet,
  17. unitUniqSet,
  18. mkUniqSet,
  19. addOneToUniqSet, addListToUniqSet,
  20. delOneFromUniqSet, delOneFromUniqSet_Directly, delListFromUniqSet,
  21. delListFromUniqSet_Directly,
  22. unionUniqSets, unionManyUniqSets,
  23. minusUniqSet, uniqSetMinusUFM, uniqSetMinusUDFM,
  24. intersectUniqSets,
  25. disjointUniqSets,
  26. restrictUniqSetToUFM,
  27. uniqSetAny, uniqSetAll,
  28. elementOfUniqSet,
  29. elemUniqSet_Directly,
  30. filterUniqSet,
  31. filterUniqSet_Directly,
  32. sizeUniqSet,
  33. isEmptyUniqSet,
  34. lookupUniqSet,
  35. lookupUniqSet_Directly,
  36. partitionUniqSet,
  37. mapUniqSet,
  38. unsafeUFMToUniqSet,
  39. nonDetEltsUniqSet,
  40. nonDetKeysUniqSet,
  41. nonDetStrictFoldUniqSet,
  42. ) where
  43. import GHC.Prelude
  44. import GHC.Types.Unique.DFM
  45. import GHC.Types.Unique.FM
  46. import GHC.Types.Unique
  47. import Data.Coerce
  48. import GHC.Utils.Outputable
  49. import Data.Data
  50. import qualified Data.Semigroup as Semi
  51. -- Note [UniqSet invariant]
  52. -- ~~~~~~~~~~~~~~~~~~~~~~~~~
  53. -- UniqSet has the following invariant:
  54. -- The keys in the map are the uniques of the values
  55. -- It means that to implement mapUniqSet you have to update
  56. -- both the keys and the values.
  57. newtype UniqSet a = UniqSet {getUniqSet' :: UniqFM a a}
  58. deriving (Data, Semi.Semigroup, Monoid)
  59. emptyUniqSet :: UniqSet a
  60. emptyUniqSet = UniqSet emptyUFM
  61. unitUniqSet :: Uniquable a => a -> UniqSet a
  62. unitUniqSet x = UniqSet $ unitUFM x x
  63. mkUniqSet :: Uniquable a => [a] -> UniqSet a
  64. mkUniqSet = foldl' addOneToUniqSet emptyUniqSet
  65. addOneToUniqSet :: Uniquable a => UniqSet a -> a -> UniqSet a
  66. addOneToUniqSet (UniqSet set) x = UniqSet (addToUFM set x x)
  67. addListToUniqSet :: Uniquable a => UniqSet a -> [a] -> UniqSet a
  68. addListToUniqSet = foldl' addOneToUniqSet
  69. delOneFromUniqSet :: Uniquable a => UniqSet a -> a -> UniqSet a
  70. delOneFromUniqSet (UniqSet s) a = UniqSet (delFromUFM s a)
  71. delOneFromUniqSet_Directly :: UniqSet a -> Unique -> UniqSet a
  72. delOneFromUniqSet_Directly (UniqSet s) u = UniqSet (delFromUFM_Directly s u)
  73. delListFromUniqSet :: Uniquable a => UniqSet a -> [a] -> UniqSet a
  74. delListFromUniqSet (UniqSet s) l = UniqSet (delListFromUFM s l)
  75. delListFromUniqSet_Directly :: UniqSet a -> [Unique] -> UniqSet a
  76. delListFromUniqSet_Directly (UniqSet s) l =
  77. UniqSet (delListFromUFM_Directly s l)
  78. unionUniqSets :: UniqSet a -> UniqSet a -> UniqSet a
  79. unionUniqSets (UniqSet s) (UniqSet t) = UniqSet (plusUFM s t)
  80. unionManyUniqSets :: [UniqSet a] -> UniqSet a
  81. unionManyUniqSets = foldl' (flip unionUniqSets) emptyUniqSet
  82. minusUniqSet :: UniqSet a -> UniqSet a -> UniqSet a
  83. minusUniqSet (UniqSet s) (UniqSet t) = UniqSet (minusUFM s t)
  84. intersectUniqSets :: UniqSet a -> UniqSet a -> UniqSet a
  85. intersectUniqSets (UniqSet s) (UniqSet t) = UniqSet (intersectUFM s t)
  86. disjointUniqSets :: UniqSet a -> UniqSet a -> Bool
  87. disjointUniqSets (UniqSet s) (UniqSet t) = disjointUFM s t
  88. restrictUniqSetToUFM :: UniqSet key -> UniqFM key b -> UniqSet key
  89. restrictUniqSetToUFM (UniqSet s) m = UniqSet (intersectUFM s m)
  90. uniqSetMinusUFM :: UniqSet key -> UniqFM key b -> UniqSet key
  91. uniqSetMinusUFM (UniqSet s) t = UniqSet (minusUFM s t)
  92. uniqSetMinusUDFM :: UniqSet key -> UniqDFM key b -> UniqSet key
  93. uniqSetMinusUDFM (UniqSet s) t = UniqSet (ufmMinusUDFM s t)
  94. elementOfUniqSet :: Uniquable a => a -> UniqSet a -> Bool
  95. elementOfUniqSet a (UniqSet s) = elemUFM a s
  96. elemUniqSet_Directly :: Unique -> UniqSet a -> Bool
  97. elemUniqSet_Directly a (UniqSet s) = elemUFM_Directly a s
  98. filterUniqSet :: (a -> Bool) -> UniqSet a -> UniqSet a
  99. filterUniqSet p (UniqSet s) = UniqSet (filterUFM p s)
  100. filterUniqSet_Directly :: (Unique -> elt -> Bool) -> UniqSet elt -> UniqSet elt
  101. filterUniqSet_Directly f (UniqSet s) = UniqSet (filterUFM_Directly f s)
  102. partitionUniqSet :: (a -> Bool) -> UniqSet a -> (UniqSet a, UniqSet a)
  103. partitionUniqSet p (UniqSet s) = coerce (partitionUFM p s)
  104. uniqSetAny :: (a -> Bool) -> UniqSet a -> Bool
  105. uniqSetAny p (UniqSet s) = anyUFM p s
  106. uniqSetAll :: (a -> Bool) -> UniqSet a -> Bool
  107. uniqSetAll p (UniqSet s) = allUFM p s
  108. sizeUniqSet :: UniqSet a -> Int
  109. sizeUniqSet (UniqSet s) = sizeUFM s
  110. isEmptyUniqSet :: UniqSet a -> Bool
  111. isEmptyUniqSet (UniqSet s) = isNullUFM s
  112. -- | What's the point you might ask? We might have changed an object
  113. -- without it's key changing. In which case this lookup makes sense.
  114. lookupUniqSet :: Uniquable key => UniqSet key -> key -> Maybe key
  115. lookupUniqSet (UniqSet s) k = lookupUFM s k
  116. lookupUniqSet_Directly :: UniqSet a -> Unique -> Maybe a
  117. lookupUniqSet_Directly (UniqSet s) k = lookupUFM_Directly s k
  118. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  119. -- If you use this please provide a justification why it doesn't introduce
  120. -- nondeterminism.
  121. nonDetEltsUniqSet :: UniqSet elt -> [elt]
  122. nonDetEltsUniqSet = nonDetEltsUFM . getUniqSet'
  123. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  124. -- If you use this please provide a justification why it doesn't introduce
  125. -- nondeterminism.
  126. nonDetKeysUniqSet :: UniqSet elt -> [Unique]
  127. nonDetKeysUniqSet = nonDetKeysUFM . getUniqSet'
  128. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  129. -- If you use this please provide a justification why it doesn't introduce
  130. -- nondeterminism.
  131. nonDetStrictFoldUniqSet :: (elt -> a -> a) -> a -> UniqSet elt -> a
  132. nonDetStrictFoldUniqSet c n (UniqSet s) = nonDetStrictFoldUFM c n s
  133. -- See Note [UniqSet invariant]
  134. mapUniqSet :: Uniquable b => (a -> b) -> UniqSet a -> UniqSet b
  135. mapUniqSet f = mkUniqSet . map f . nonDetEltsUniqSet
  136. -- Two 'UniqSet's are considered equal if they contain the same
  137. -- uniques.
  138. instance Eq (UniqSet a) where
  139. UniqSet a == UniqSet b = equalKeysUFM a b
  140. getUniqSet :: UniqSet a -> UniqFM a a
  141. getUniqSet = getUniqSet'
  142. -- | 'unsafeUFMToUniqSet' converts a @'UniqFM' a@ into a @'UniqSet' a@
  143. -- assuming, without checking, that it maps each 'Unique' to a value
  144. -- that has that 'Unique'. See Note [UniqSet invariant].
  145. unsafeUFMToUniqSet :: UniqFM a a -> UniqSet a
  146. unsafeUFMToUniqSet = UniqSet
  147. instance Outputable a => Outputable (UniqSet a) where
  148. ppr = pprUniqSet ppr
  149. pprUniqSet :: (a -> SDoc) -> UniqSet a -> SDoc
  150. -- It's OK to use nonDetUFMToList here because we only use it for
  151. -- pretty-printing.
  152. pprUniqSet f = braces . pprWithCommas f . nonDetEltsUniqSet