/compiler/Eta/BasicTypes/VarSet.hs

https://github.com/typelead/eta · Haskell · 348 lines · 205 code · 65 blank · 78 comment · 0 complexity · 052b8eafc0e05dcb6d977ec57122a208 MD5 · raw file

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