/compiler/Eta/BasicTypes/NameSet.hs

https://github.com/typelead/eta · Haskell · 209 lines · 116 code · 33 blank · 60 comment · 1 complexity · 230db00a9163f023851b85cbed1dc398 MD5 · raw file

  1. {-
  2. (c) The University of Glasgow 2006
  3. (c) The GRASP/AQUA Project, Glasgow University, 1998
  4. -}
  5. module Eta.BasicTypes.NameSet (
  6. -- * Names set type
  7. NameSet,
  8. -- ** Manipulating these sets
  9. emptyNameSet, unitNameSet, mkNameSet, unionNameSet, unionNameSets,
  10. minusNameSet, elemNameSet, nameSetElems, extendNameSet, extendNameSetList,
  11. delFromNameSet, delListFromNameSet, isEmptyNameSet, foldNameSet, filterNameSet,
  12. intersectsNameSet, intersectNameSet, nameSetAll, nameSetElemsStable, nameSetAny,
  13. -- * Free variables
  14. FreeVars,
  15. -- ** Manipulating sets of free variables
  16. isEmptyFVs, emptyFVs, plusFVs, plusFV,
  17. mkFVs, addOneFV, unitFV, delFV, delFVs,
  18. -- * Defs and uses
  19. Defs, Uses, DefUse, DefUses,
  20. -- ** Manipulating defs and uses
  21. emptyDUs, usesOnly, mkDUs, plusDU,
  22. findUses, duDefs, duUses, allUses
  23. ) where
  24. import Eta.BasicTypes.Name
  25. import Eta.Utils.UniqSet
  26. import Data.List ( sortBy )
  27. {-
  28. ************************************************************************
  29. * *
  30. \subsection[Sets of names}
  31. * *
  32. ************************************************************************
  33. -}
  34. type NameSet = UniqSet Name
  35. emptyNameSet :: NameSet
  36. unitNameSet :: Name -> NameSet
  37. extendNameSetList :: NameSet -> [Name] -> NameSet
  38. extendNameSet :: NameSet -> Name -> NameSet
  39. mkNameSet :: [Name] -> NameSet
  40. unionNameSet :: NameSet -> NameSet -> NameSet
  41. unionNameSets :: [NameSet] -> NameSet
  42. minusNameSet :: NameSet -> NameSet -> NameSet
  43. elemNameSet :: Name -> NameSet -> Bool
  44. nameSetElems :: NameSet -> [Name]
  45. isEmptyNameSet :: NameSet -> Bool
  46. delFromNameSet :: NameSet -> Name -> NameSet
  47. delListFromNameSet :: NameSet -> [Name] -> NameSet
  48. foldNameSet :: (Name -> b -> b) -> b -> NameSet -> b
  49. filterNameSet :: (Name -> Bool) -> NameSet -> NameSet
  50. intersectNameSet :: NameSet -> NameSet -> NameSet
  51. intersectsNameSet :: NameSet -> NameSet -> Bool
  52. -- ^ True if there is a non-empty intersection.
  53. -- @s1 `intersectsNameSet` s2@ doesn't compute @s2@ if @s1@ is empty
  54. isEmptyNameSet = isEmptyUniqSet
  55. emptyNameSet = emptyUniqSet
  56. unitNameSet = unitUniqSet
  57. mkNameSet = mkUniqSet
  58. extendNameSetList = addListToUniqSet
  59. extendNameSet = addOneToUniqSet
  60. unionNameSet = unionUniqSets
  61. unionNameSets = unionManyUniqSets
  62. minusNameSet = minusUniqSet
  63. elemNameSet = elementOfUniqSet
  64. nameSetElems = uniqSetToList
  65. delFromNameSet = delOneFromUniqSet
  66. foldNameSet = foldUniqSet
  67. filterNameSet = filterUniqSet
  68. intersectNameSet = intersectUniqSets
  69. delListFromNameSet set ns = foldl delFromNameSet set ns
  70. intersectsNameSet s1 s2 = not (isEmptyNameSet (s1 `intersectNameSet` s2))
  71. nameSetAny :: (Name -> Bool) -> NameSet -> Bool
  72. nameSetAny = uniqSetAny
  73. nameSetAll :: (Name -> Bool) -> NameSet -> Bool
  74. nameSetAll = uniqSetAll
  75. -- | Get the elements of a NameSet with some stable ordering.
  76. -- This only works for Names that originate in the source code or have been
  77. -- tidied.
  78. -- See Note [Deterministic UniqFM] to learn about nondeterminism
  79. nameSetElemsStable :: NameSet -> [Name]
  80. nameSetElemsStable ns =
  81. sortBy stableNameCmp $ nonDetEltsUniqSet ns
  82. -- It's OK to use nonDetEltsUniqSet here because we immediately sort
  83. -- with stableNameCmp
  84. {-
  85. ************************************************************************
  86. * *
  87. \subsection{Free variables}
  88. * *
  89. ************************************************************************
  90. These synonyms are useful when we are thinking of free variables
  91. -}
  92. type FreeVars = NameSet
  93. plusFV :: FreeVars -> FreeVars -> FreeVars
  94. addOneFV :: FreeVars -> Name -> FreeVars
  95. unitFV :: Name -> FreeVars
  96. emptyFVs :: FreeVars
  97. plusFVs :: [FreeVars] -> FreeVars
  98. mkFVs :: [Name] -> FreeVars
  99. delFV :: Name -> FreeVars -> FreeVars
  100. delFVs :: [Name] -> FreeVars -> FreeVars
  101. isEmptyFVs :: NameSet -> Bool
  102. isEmptyFVs = isEmptyNameSet
  103. emptyFVs = emptyNameSet
  104. plusFVs = unionNameSets
  105. plusFV = unionNameSet
  106. mkFVs = mkNameSet
  107. addOneFV = extendNameSet
  108. unitFV = unitNameSet
  109. delFV n s = delFromNameSet s n
  110. delFVs ns s = delListFromNameSet s ns
  111. {-
  112. ************************************************************************
  113. * *
  114. Defs and uses
  115. * *
  116. ************************************************************************
  117. -}
  118. -- | A set of names that are defined somewhere
  119. type Defs = NameSet
  120. -- | A set of names that are used somewhere
  121. type Uses = NameSet
  122. -- | @(Just ds, us) =>@ The use of any member of the @ds@
  123. -- implies that all the @us@ are used too.
  124. -- Also, @us@ may mention @ds@.
  125. --
  126. -- @Nothing =>@ Nothing is defined in this group, but
  127. -- nevertheless all the uses are essential.
  128. -- Used for instance declarations, for example
  129. type DefUse = (Maybe Defs, Uses)
  130. -- | A number of 'DefUse's in dependency order: earlier 'Defs' scope over later 'Uses'
  131. -- In a single (def, use) pair, the defs also scope over the uses
  132. type DefUses = [DefUse]
  133. emptyDUs :: DefUses
  134. emptyDUs = []
  135. usesOnly :: Uses -> DefUses
  136. usesOnly uses = [(Nothing, uses)]
  137. mkDUs :: [(Defs,Uses)] -> DefUses
  138. mkDUs pairs = [(Just defs, uses) | (defs,uses) <- pairs]
  139. plusDU :: DefUses -> DefUses -> DefUses
  140. plusDU = (++)
  141. duDefs :: DefUses -> Defs
  142. duDefs dus = foldr get emptyNameSet dus
  143. where
  144. get (Nothing, _u1) d2 = d2
  145. get (Just d1, _u1) d2 = d1 `unionNameSet` d2
  146. allUses :: DefUses -> Uses
  147. -- ^ Just like 'duUses', but 'Defs' are not eliminated from the 'Uses' returned
  148. allUses dus = foldr get emptyNameSet dus
  149. where
  150. get (_d1, u1) u2 = u1 `unionNameSet` u2
  151. duUses :: DefUses -> Uses
  152. -- ^ Collect all 'Uses', regardless of whether the group is itself used,
  153. -- but remove 'Defs' on the way
  154. duUses dus = foldr get emptyNameSet dus
  155. where
  156. get (Nothing, rhs_uses) uses = rhs_uses `unionNameSet` uses
  157. get (Just defs, rhs_uses) uses = (rhs_uses `unionNameSet` uses)
  158. `minusNameSet` defs
  159. findUses :: DefUses -> Uses -> Uses
  160. -- ^ Given some 'DefUses' and some 'Uses', find all the uses, transitively.
  161. -- The result is a superset of the input 'Uses'; and includes things defined
  162. -- in the input 'DefUses' (but only if they are used)
  163. findUses dus uses
  164. = foldr get uses dus
  165. where
  166. get (Nothing, rhs_uses) uses
  167. = rhs_uses `unionNameSet` uses
  168. get (Just defs, rhs_uses) uses
  169. | defs `intersectsNameSet` uses -- Used
  170. || any (startsWithUnderscore . nameOccName) (nameSetElems defs)
  171. -- At least one starts with an "_",
  172. -- so treat the group as used
  173. = rhs_uses `unionNameSet` uses
  174. | otherwise -- No def is used
  175. = uses