PageRenderTime 55ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/GHC/Types/Var/Set.hs

https://github.com/ghc/ghc
Haskell | 360 lines | 208 code | 68 blank | 84 comment | 0 complexity | 42d23ef0660ebf90f31616c108ee94c7 MD5 | raw file
  1. {-
  2. (c) The University of Glasgow 2006
  3. (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
  4. -}
  5. module GHC.Types.Var.Set (
  6. -- * Var, Id and TyVar set types
  7. VarSet, IdSet, TyVarSet, CoVarSet, TyCoVarSet,
  8. -- ** Manipulating these sets
  9. emptyVarSet, unitVarSet, mkVarSet,
  10. extendVarSet, extendVarSetList,
  11. elemVarSet, subVarSet,
  12. unionVarSet, unionVarSets, mapUnionVarSet,
  13. intersectVarSet, intersectsVarSet, disjointVarSet,
  14. isEmptyVarSet, delVarSet, delVarSetList, delVarSetByKey,
  15. minusVarSet, filterVarSet, mapVarSet,
  16. anyVarSet, allVarSet,
  17. transCloVarSet, fixVarSet,
  18. lookupVarSet_Directly, lookupVarSet, lookupVarSetByName,
  19. sizeVarSet, seqVarSet,
  20. elemVarSetByKey, partitionVarSet,
  21. pluralVarSet, pprVarSet,
  22. nonDetStrictFoldVarSet,
  23. -- * Deterministic Var set types
  24. DVarSet, DIdSet, DTyVarSet, DTyCoVarSet,
  25. -- ** Manipulating these sets
  26. emptyDVarSet, unitDVarSet, mkDVarSet,
  27. extendDVarSet, extendDVarSetList,
  28. elemDVarSet, dVarSetElems, subDVarSet,
  29. unionDVarSet, unionDVarSets, mapUnionDVarSet,
  30. intersectDVarSet, dVarSetIntersectVarSet,
  31. intersectsDVarSet, disjointDVarSet,
  32. isEmptyDVarSet, delDVarSet, delDVarSetList,
  33. minusDVarSet,
  34. nonDetStrictFoldDVarSet,
  35. filterDVarSet, mapDVarSet,
  36. dVarSetMinusVarSet, anyDVarSet, allDVarSet,
  37. transCloDVarSet,
  38. sizeDVarSet, seqDVarSet,
  39. partitionDVarSet,
  40. dVarSetToVarSet,
  41. ) where
  42. import GHC.Prelude
  43. import GHC.Types.Var ( Var, TyVar, CoVar, TyCoVar, Id )
  44. import GHC.Types.Unique
  45. import GHC.Types.Name ( Name )
  46. import GHC.Types.Unique.Set
  47. import GHC.Types.Unique.DSet
  48. import GHC.Types.Unique.FM( disjointUFM, pluralUFM, pprUFM )
  49. import GHC.Types.Unique.DFM( disjointUDFM, udfmToUfm, anyUDFM, allUDFM )
  50. import GHC.Utils.Outputable (SDoc)
  51. -- | A non-deterministic Variable Set
  52. --
  53. -- A non-deterministic set of variables.
  54. -- See Note [Deterministic UniqFM] in "GHC.Types.Unique.DFM" for explanation why it's not
  55. -- deterministic and why it matters. Use DVarSet if the set eventually
  56. -- gets converted into a list or folded over in a way where the order
  57. -- changes the generated code, for example when abstracting variables.
  58. type VarSet = UniqSet Var
  59. -- | Identifier Set
  60. type IdSet = UniqSet Id
  61. -- | Type Variable Set
  62. type TyVarSet = UniqSet TyVar
  63. -- | Coercion Variable Set
  64. type CoVarSet = UniqSet CoVar
  65. -- | Type or Coercion Variable Set
  66. type TyCoVarSet = UniqSet TyCoVar
  67. emptyVarSet :: VarSet
  68. intersectVarSet :: VarSet -> VarSet -> VarSet
  69. unionVarSet :: VarSet -> VarSet -> VarSet
  70. unionVarSets :: [VarSet] -> VarSet
  71. mapUnionVarSet :: (a -> VarSet) -> [a] -> VarSet
  72. -- ^ map the function over the list, and union the results
  73. unitVarSet :: Var -> VarSet
  74. extendVarSet :: VarSet -> Var -> VarSet
  75. extendVarSetList:: VarSet -> [Var] -> VarSet
  76. elemVarSet :: Var -> VarSet -> Bool
  77. delVarSet :: VarSet -> Var -> VarSet
  78. delVarSetList :: VarSet -> [Var] -> VarSet
  79. minusVarSet :: VarSet -> VarSet -> VarSet
  80. isEmptyVarSet :: VarSet -> Bool
  81. mkVarSet :: [Var] -> VarSet
  82. lookupVarSet_Directly :: VarSet -> Unique -> Maybe Var
  83. lookupVarSet :: VarSet -> Var -> Maybe Var
  84. -- Returns the set element, which may be
  85. -- (==) to the argument, but not the same as
  86. lookupVarSetByName :: VarSet -> Name -> Maybe Var
  87. sizeVarSet :: VarSet -> Int
  88. filterVarSet :: (Var -> Bool) -> VarSet -> VarSet
  89. delVarSetByKey :: VarSet -> Unique -> VarSet
  90. elemVarSetByKey :: Unique -> VarSet -> Bool
  91. partitionVarSet :: (Var -> Bool) -> VarSet -> (VarSet, VarSet)
  92. emptyVarSet = emptyUniqSet
  93. unitVarSet = unitUniqSet
  94. extendVarSet = addOneToUniqSet
  95. extendVarSetList= addListToUniqSet
  96. intersectVarSet = intersectUniqSets
  97. intersectsVarSet:: VarSet -> VarSet -> Bool -- True if non-empty intersection
  98. disjointVarSet :: VarSet -> VarSet -> Bool -- True if empty intersection
  99. subVarSet :: VarSet -> VarSet -> Bool -- True if first arg is subset of second
  100. -- (s1 `intersectsVarSet` s2) doesn't compute s2 if s1 is empty;
  101. -- ditto disjointVarSet, subVarSet
  102. unionVarSet = unionUniqSets
  103. unionVarSets = unionManyUniqSets
  104. elemVarSet = elementOfUniqSet
  105. minusVarSet = minusUniqSet
  106. delVarSet = delOneFromUniqSet
  107. delVarSetList = delListFromUniqSet
  108. isEmptyVarSet = isEmptyUniqSet
  109. mkVarSet = mkUniqSet
  110. lookupVarSet_Directly = lookupUniqSet_Directly
  111. lookupVarSet = lookupUniqSet
  112. lookupVarSetByName set name = lookupUniqSet_Directly set (getUnique name)
  113. sizeVarSet = sizeUniqSet
  114. filterVarSet = filterUniqSet
  115. delVarSetByKey = delOneFromUniqSet_Directly
  116. elemVarSetByKey = elemUniqSet_Directly
  117. partitionVarSet = partitionUniqSet
  118. mapUnionVarSet get_set xs = foldr (unionVarSet . get_set) emptyVarSet xs
  119. -- See comments with type signatures
  120. intersectsVarSet s1 s2 = not (s1 `disjointVarSet` s2)
  121. disjointVarSet s1 s2 = disjointUFM (getUniqSet s1) (getUniqSet s2)
  122. subVarSet s1 s2 = isEmptyVarSet (s1 `minusVarSet` s2)
  123. anyVarSet :: (Var -> Bool) -> VarSet -> Bool
  124. anyVarSet = uniqSetAny
  125. allVarSet :: (Var -> Bool) -> VarSet -> Bool
  126. allVarSet = uniqSetAll
  127. mapVarSet :: Uniquable b => (a -> b) -> UniqSet a -> UniqSet b
  128. mapVarSet = mapUniqSet
  129. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  130. -- If you use this please provide a justification why it doesn't introduce
  131. -- nondeterminism.
  132. nonDetStrictFoldVarSet :: (Var -> a -> a) -> a -> VarSet -> a
  133. nonDetStrictFoldVarSet = nonDetStrictFoldUniqSet
  134. fixVarSet :: (VarSet -> VarSet) -- Map the current set to a new set
  135. -> VarSet -> VarSet
  136. -- (fixVarSet f s) repeatedly applies f to the set s,
  137. -- until it reaches a fixed point.
  138. fixVarSet fn vars
  139. | new_vars `subVarSet` vars = vars
  140. | otherwise = fixVarSet fn new_vars
  141. where
  142. new_vars = fn vars
  143. transCloVarSet :: (VarSet -> VarSet)
  144. -- Map some variables in the set to
  145. -- extra variables that should be in it
  146. -> VarSet -> VarSet
  147. -- (transCloVarSet f s) repeatedly applies f to new candidates, adding any
  148. -- new variables to s that it finds thereby, until it reaches a fixed point.
  149. --
  150. -- The function fn could be (Var -> VarSet), but we use (VarSet -> VarSet)
  151. -- for efficiency, so that the test can be batched up.
  152. -- It's essential that fn will work fine if given new candidates
  153. -- one at a time; ie fn {v1,v2} = fn v1 `union` fn v2
  154. -- Use fixVarSet if the function needs to see the whole set all at once
  155. transCloVarSet fn seeds
  156. = go seeds seeds
  157. where
  158. go :: VarSet -- Accumulating result
  159. -> VarSet -- Work-list; un-processed subset of accumulating result
  160. -> VarSet
  161. -- Specification: go acc vs = acc `union` transClo fn vs
  162. go acc candidates
  163. | isEmptyVarSet new_vs = acc
  164. | otherwise = go (acc `unionVarSet` new_vs) new_vs
  165. where
  166. new_vs = fn candidates `minusVarSet` acc
  167. seqVarSet :: VarSet -> ()
  168. seqVarSet s = s `seq` ()
  169. -- | Determines the pluralisation suffix appropriate for the length of a set
  170. -- in the same way that plural from Outputable does for lists.
  171. pluralVarSet :: VarSet -> SDoc
  172. pluralVarSet = pluralUFM . getUniqSet
  173. -- | Pretty-print a non-deterministic set.
  174. -- The order of variables is non-deterministic and for pretty-printing that
  175. -- shouldn't be a problem.
  176. -- Having this function helps contain the non-determinism created with
  177. -- nonDetEltsUFM.
  178. -- Passing a list to the pretty-printing function allows the caller
  179. -- to decide on the order of Vars (eg. toposort them) without them having
  180. -- to use nonDetEltsUFM at the call site. This prevents from let-binding
  181. -- non-deterministically ordered lists and reusing them where determinism
  182. -- matters.
  183. pprVarSet :: VarSet -- ^ The things to be pretty printed
  184. -> ([Var] -> SDoc) -- ^ The pretty printing function to use on the
  185. -- elements
  186. -> SDoc -- ^ 'SDoc' where the things have been pretty
  187. -- printed
  188. pprVarSet = pprUFM . getUniqSet
  189. -- Deterministic VarSet
  190. -- See Note [Deterministic UniqFM] in GHC.Types.Unique.DFM for explanation why we need
  191. -- DVarSet.
  192. -- | Deterministic Variable Set
  193. type DVarSet = UniqDSet Var
  194. -- | Deterministic Identifier Set
  195. type DIdSet = UniqDSet Id
  196. -- | Deterministic Type Variable Set
  197. type DTyVarSet = UniqDSet TyVar
  198. -- | Deterministic Type or Coercion Variable Set
  199. type DTyCoVarSet = UniqDSet TyCoVar
  200. emptyDVarSet :: DVarSet
  201. emptyDVarSet = emptyUniqDSet
  202. unitDVarSet :: Var -> DVarSet
  203. unitDVarSet = unitUniqDSet
  204. mkDVarSet :: [Var] -> DVarSet
  205. mkDVarSet = mkUniqDSet
  206. -- The new element always goes to the right of existing ones.
  207. extendDVarSet :: DVarSet -> Var -> DVarSet
  208. extendDVarSet = addOneToUniqDSet
  209. elemDVarSet :: Var -> DVarSet -> Bool
  210. elemDVarSet = elementOfUniqDSet
  211. dVarSetElems :: DVarSet -> [Var]
  212. dVarSetElems = uniqDSetToList
  213. subDVarSet :: DVarSet -> DVarSet -> Bool
  214. subDVarSet s1 s2 = isEmptyDVarSet (s1 `minusDVarSet` s2)
  215. unionDVarSet :: DVarSet -> DVarSet -> DVarSet
  216. unionDVarSet = unionUniqDSets
  217. unionDVarSets :: [DVarSet] -> DVarSet
  218. unionDVarSets = unionManyUniqDSets
  219. -- | Map the function over the list, and union the results
  220. mapUnionDVarSet :: (a -> DVarSet) -> [a] -> DVarSet
  221. mapUnionDVarSet get_set xs = foldr (unionDVarSet . get_set) emptyDVarSet xs
  222. intersectDVarSet :: DVarSet -> DVarSet -> DVarSet
  223. intersectDVarSet = intersectUniqDSets
  224. dVarSetIntersectVarSet :: DVarSet -> VarSet -> DVarSet
  225. dVarSetIntersectVarSet = uniqDSetIntersectUniqSet
  226. -- | True if empty intersection
  227. disjointDVarSet :: DVarSet -> DVarSet -> Bool
  228. disjointDVarSet s1 s2 = disjointUDFM (getUniqDSet s1) (getUniqDSet s2)
  229. -- | True if non-empty intersection
  230. intersectsDVarSet :: DVarSet -> DVarSet -> Bool
  231. intersectsDVarSet s1 s2 = not (s1 `disjointDVarSet` s2)
  232. isEmptyDVarSet :: DVarSet -> Bool
  233. isEmptyDVarSet = isEmptyUniqDSet
  234. delDVarSet :: DVarSet -> Var -> DVarSet
  235. delDVarSet = delOneFromUniqDSet
  236. minusDVarSet :: DVarSet -> DVarSet -> DVarSet
  237. minusDVarSet = minusUniqDSet
  238. dVarSetMinusVarSet :: DVarSet -> VarSet -> DVarSet
  239. dVarSetMinusVarSet = uniqDSetMinusUniqSet
  240. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  241. -- If you use this please provide a justification why it doesn't introduce
  242. -- nondeterminism.
  243. nonDetStrictFoldDVarSet :: (Var -> a -> a) -> a -> DVarSet -> a
  244. nonDetStrictFoldDVarSet = nonDetStrictFoldUniqDSet
  245. anyDVarSet :: (Var -> Bool) -> DVarSet -> Bool
  246. anyDVarSet p = anyUDFM p . getUniqDSet
  247. allDVarSet :: (Var -> Bool) -> DVarSet -> Bool
  248. allDVarSet p = allUDFM p . getUniqDSet
  249. mapDVarSet :: Uniquable b => (a -> b) -> UniqDSet a -> UniqDSet b
  250. mapDVarSet = mapUniqDSet
  251. filterDVarSet :: (Var -> Bool) -> DVarSet -> DVarSet
  252. filterDVarSet = filterUniqDSet
  253. sizeDVarSet :: DVarSet -> Int
  254. sizeDVarSet = sizeUniqDSet
  255. -- | Partition DVarSet according to the predicate given
  256. partitionDVarSet :: (Var -> Bool) -> DVarSet -> (DVarSet, DVarSet)
  257. partitionDVarSet = partitionUniqDSet
  258. -- | Delete a list of variables from DVarSet
  259. delDVarSetList :: DVarSet -> [Var] -> DVarSet
  260. delDVarSetList = delListFromUniqDSet
  261. seqDVarSet :: DVarSet -> ()
  262. seqDVarSet s = s `seq` ()
  263. -- | Add a list of variables to DVarSet
  264. extendDVarSetList :: DVarSet -> [Var] -> DVarSet
  265. extendDVarSetList = addListToUniqDSet
  266. -- | Convert a DVarSet to a VarSet by forgetting the order of insertion
  267. dVarSetToVarSet :: DVarSet -> VarSet
  268. dVarSetToVarSet = unsafeUFMToUniqSet . udfmToUfm . getUniqDSet
  269. -- | transCloVarSet for DVarSet
  270. transCloDVarSet :: (DVarSet -> DVarSet)
  271. -- Map some variables in the set to
  272. -- extra variables that should be in it
  273. -> DVarSet -> DVarSet
  274. -- (transCloDVarSet f s) repeatedly applies f to new candidates, adding any
  275. -- new variables to s that it finds thereby, until it reaches a fixed point.
  276. --
  277. -- The function fn could be (Var -> DVarSet), but we use (DVarSet -> DVarSet)
  278. -- for efficiency, so that the test can be batched up.
  279. -- It's essential that fn will work fine if given new candidates
  280. -- one at a time; ie fn {v1,v2} = fn v1 `union` fn v2
  281. transCloDVarSet fn seeds
  282. = go seeds seeds
  283. where
  284. go :: DVarSet -- Accumulating result
  285. -> DVarSet -- Work-list; un-processed subset of accumulating result
  286. -> DVarSet
  287. -- Specification: go acc vs = acc `union` transClo fn vs
  288. go acc candidates
  289. | isEmptyDVarSet new_vs = acc
  290. | otherwise = go (acc `unionDVarSet` new_vs) new_vs
  291. where
  292. new_vs = fn candidates `minusDVarSet` acc