/compiler/basicTypes/NameSet.hs
http://github.com/ghc/ghc · Haskell · 213 lines · 118 code · 34 blank · 61 comment · 1 complexity · a874168de25e86614293f156e34afdc3 MD5 · raw file
- {-
- (c) The University of Glasgow 2006
- (c) The GRASP/AQUA Project, Glasgow University, 1998
- -}
- {-# LANGUAGE CPP #-}
- module NameSet (
- -- * Names set type
- NameSet,
- -- ** Manipulating these sets
- emptyNameSet, unitNameSet, mkNameSet, unionNameSet, unionNameSets,
- minusNameSet, elemNameSet, extendNameSet, extendNameSetList,
- delFromNameSet, delListFromNameSet, isEmptyNameSet, filterNameSet,
- intersectsNameSet, 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
- ) where
- #include "HsVersions.h"
- import Name
- import UniqSet
- import UniqFM
- 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
- -- ^ 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
- delListFromNameSet set ns = foldl delFromNameSet set ns
- intersectsNameSet s1 s2 = not (isEmptyNameSet (s1 `intersectNameSet` 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 $ nonDetEltsUFM ns
- -- It's OK to use nonDetEltsUFM 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 = [DefUse]
- emptyDUs :: DefUses
- emptyDUs = []
- usesOnly :: Uses -> DefUses
- usesOnly uses = [(Nothing, uses)]
- mkDUs :: [(Defs,Uses)] -> DefUses
- mkDUs pairs = [(Just defs, uses) | (defs,uses) <- pairs]
- plusDU :: DefUses -> DefUses -> DefUses
- plusDU = (++)
- 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