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