%
\begin{code}
+-- |
+-- #name_types#
+-- GHC uses several kinds of name internally:
+--
+-- * 'OccName.OccName' represents names as strings with just a little more information:
+-- the "namespace" that the name came from, e.g. the namespace of value, type constructors or
+-- data constructors
+--
+-- * 'RdrName.RdrName': see "RdrName#name_types"
+--
+-- * 'Name.Name': see "Name#name_types"
+--
+-- * 'Id.Id': see "Id#name_types"
+--
+-- * 'Var.Var': see "Var#name_types"
module OccName (
- -- * The NameSpace type; abstact
- NameSpace, tcName, clsName, tcClsName, dataName, varName,
+ -- * The 'NameSpace' type
+ NameSpace, -- Abstract
+
+ -- ** Construction
+ -- $real_vs_source_data_constructors
+ tcName, clsName, tcClsName, dataName, varName,
tvName, srcDataName,
- -- ** Printing
+ -- ** Pretty Printing
pprNameSpace, pprNonVarNameSpace, pprNameSpaceBrief,
- -- * The OccName type
+ -- * The 'OccName' type
OccName, -- Abstract, instance of Outputable
pprOccName,
-- ** Construction
mkOccName, mkOccNameFS,
mkVarOcc, mkVarOccFS,
- mkTyVarOcc,
+ mkDataOcc, mkDataOccFS,
+ mkTyVarOcc, mkTyVarOccFS,
+ mkTcOcc, mkTcOccFS,
+ mkClsOcc, mkClsOccFS,
mkDFunOcc,
mkTupleOcc,
setOccNameSpace,
- -- ** Derived OccNames
+ -- ** Derived 'OccName's
+ isDerivedOccName,
mkDataConWrapperOcc, mkWorkerOcc, mkDefaultMethodOcc,
- mkDerivedTyConOcc, mkNewTyCoOcc,
+ mkDerivedTyConOcc, mkNewTyCoOcc,
+ mkCon2TagOcc, mkTag2ConOcc, mkMaxTagOcc,
mkClassTyConOcc, mkClassDataConOcc, mkDictOcc, mkIPOcc,
mkSpecOcc, mkForeignExportOcc, mkGenOcc1, mkGenOcc2,
mkDataTOcc, mkDataCOcc, mkDataConWorkerOcc,
occNameFS, occNameString, occNameSpace,
isVarOcc, isTvOcc, isTcOcc, isDataOcc, isDataSymOcc, isSymOcc, isValOcc,
- parenSymOcc, reportIfUnused, isTcClsName, isVarName,
+ parenSymOcc, reportIfUnused,
+
+ isTcClsNameSpace, isTvNameSpace, isDataConNameSpace, isVarNameSpace, isValNameSpace,
isTupleOcc_maybe,
- -- The OccEnv type
+ -- * The 'OccEnv' type
OccEnv, emptyOccEnv, unitOccEnv, extendOccEnv, mapOccEnv,
lookupOccEnv, mkOccEnv, mkOccEnv_C, extendOccEnvList, elemOccEnv,
occEnvElts, foldOccEnv, plusOccEnv, plusOccEnv_C, extendOccEnv_C,
filterOccEnv, delListFromOccEnv, delFromOccEnv,
- -- The OccSet type
+ -- * The 'OccSet' type
OccSet, emptyOccSet, unitOccSet, mkOccSet, extendOccSet,
extendOccSetList,
unionOccSets, unionManyOccSets, minusOccSet, elemOccSet, occSetElts,
foldOccSet, isEmptyOccSet, intersectOccSet, intersectsOccSet,
- -- Tidying up
+ -- * Tidying up
TidyOccEnv, emptyTidyOccEnv, tidyOccName, initTidyOccEnv,
- -- The basic form of names
+ -- * Lexical characteristics of Haskell names
isLexCon, isLexVar, isLexId, isLexSym,
isLexConId, isLexConSym, isLexVarId, isLexVarSym,
startsVarSym, startsVarId, startsConSym, startsConId
) where
-#include "HsVersions.h"
-
import Util
import Unique
import BasicTypes
import GHC.Exts
import Data.Char
+\end{code}
+\begin{code}
-- Unicode TODO: put isSymbol in libcompat
#if !defined(__GLASGOW_HASKELL__) || __GLASGOW_HASKELL__ > 604
#else
+isSymbol :: a -> Bool
isSymbol = const False
#endif
-- Note [Data Constructors]
-- see also: Note [Data Constructor Naming] in DataCon.lhs
---
--- "Source" data constructors are the data constructors mentioned
--- in Haskell source code
--
--- "Real" data constructors are the data constructors of the
--- representation type, which may not be the same as the source
--- type
-
--- Example:
--- data T = T !(Int,Int)
+-- $real_vs_source_data_constructors
+-- There are two forms of data constructor:
+--
+-- [Source data constructors] The data constructors mentioned in Haskell source code
+--
+-- [Real data constructors] The data constructors of the representation type, which may not be the same as the source type
+--
+-- For example:
+--
+-- > data T = T !(Int, Int)
+--
+-- The source datacon has type @(Int, Int) -> T@
+-- The real datacon has type @Int -> Int -> T@
--
--- The source datacon has type (Int,Int) -> T
--- The real datacon has type Int -> Int -> T
-- GHC chooses a representation based on the strictness etc.
tcName, clsName, tcClsName :: NameSpace
tvName = TvName
varName = VarName
-isTcClsName :: NameSpace -> Bool
-isTcClsName TcClsName = True
-isTcClsName _ = False
+isDataConNameSpace :: NameSpace -> Bool
+isDataConNameSpace DataName = True
+isDataConNameSpace _ = False
+
+isTcClsNameSpace :: NameSpace -> Bool
+isTcClsNameSpace TcClsName = True
+isTcClsNameSpace _ = False
+
+isTvNameSpace :: NameSpace -> Bool
+isTvNameSpace TvName = True
+isTvNameSpace _ = False
+
+isVarNameSpace :: NameSpace -> Bool -- Variables or type variables, but not constructors
+isVarNameSpace TvName = True
+isVarNameSpace VarName = True
+isVarNameSpace _ = False
-isVarName :: NameSpace -> Bool -- Variables or type variables, but not constructors
-isVarName TvName = True
-isVarName VarName = True
-isVarName _ = False
+isValNameSpace :: NameSpace -> Bool
+isValNameSpace DataName = True
+isValNameSpace VarName = True
+isValNameSpace _ = False
pprNameSpace :: NameSpace -> SDoc
-pprNameSpace DataName = ptext SLIT("data constructor")
-pprNameSpace VarName = ptext SLIT("variable")
-pprNameSpace TvName = ptext SLIT("type variable")
-pprNameSpace TcClsName = ptext SLIT("type constructor or class")
+pprNameSpace DataName = ptext (sLit "data constructor")
+pprNameSpace VarName = ptext (sLit "variable")
+pprNameSpace TvName = ptext (sLit "type variable")
+pprNameSpace TcClsName = ptext (sLit "type constructor or class")
pprNonVarNameSpace :: NameSpace -> SDoc
pprNonVarNameSpace VarName = empty
pprNameSpaceBrief :: NameSpace -> SDoc
pprNameSpaceBrief DataName = char 'd'
pprNameSpaceBrief VarName = char 'v'
-pprNameSpaceBrief TvName = ptext SLIT("tv")
-pprNameSpaceBrief TcClsName = ptext SLIT("tc")
+pprNameSpaceBrief TvName = ptext (sLit "tv")
+pprNameSpaceBrief TcClsName = ptext (sLit "tc")
\end{code}
mkVarOccFS :: FastString -> OccName
mkVarOccFS fs = mkOccNameFS varName fs
-mkTyVarOcc :: FastString -> OccName
-mkTyVarOcc fs = mkOccNameFS tvName fs
+mkDataOcc :: String -> OccName
+mkDataOcc = mkOccName dataName
+
+mkDataOccFS :: FastString -> OccName
+mkDataOccFS = mkOccNameFS dataName
+
+mkTyVarOcc :: String -> OccName
+mkTyVarOcc = mkOccName tvName
+
+mkTyVarOccFS :: FastString -> OccName
+mkTyVarOccFS fs = mkOccNameFS tvName fs
+
+mkTcOcc :: String -> OccName
+mkTcOcc = mkOccName tcName
+
+mkTcOccFS :: FastString -> OccName
+mkTcOccFS = mkOccNameFS tcName
+
+mkClsOcc :: String -> OccName
+mkClsOcc = mkOccName clsName
+
+mkClsOccFS :: FastString -> OccName
+mkClsOccFS = mkOccNameFS clsName
\end{code}
setOccNameSpace :: NameSpace -> OccName -> OccName
setOccNameSpace sp (OccName _ occ) = OccName sp occ
-isVarOcc, isTvOcc, isDataSymOcc, isSymOcc, isTcOcc, isValOcc, isDataOcc :: OccName -> Bool
+isVarOcc, isTvOcc, isTcOcc, isDataOcc :: OccName -> Bool
isVarOcc (OccName VarName _) = True
isVarOcc _ = False
isTcOcc (OccName TcClsName _) = True
isTcOcc _ = False
+-- | /Value/ 'OccNames's are those that are either in
+-- the variable or data constructor namespaces
+isValOcc :: OccName -> Bool
isValOcc (OccName VarName _) = True
isValOcc (OccName DataName _) = True
isValOcc _ = False
--- Data constructor operator (starts with ':', or '[]')
--- Pretty inefficient!
-isDataSymOcc (OccName DataName s) = isLexConSym s
-isDataSymOcc (OccName VarName s)
- | isLexConSym s = pprPanic "isDataSymOcc: check me" (ppr s)
- -- Jan06: I don't think this should happen
-isDataSymOcc _ = False
-
isDataOcc (OccName DataName _) = True
isDataOcc (OccName VarName s)
| isLexCon s = pprPanic "isDataOcc: check me" (ppr s)
-- Jan06: I don't think this should happen
isDataOcc _ = False
--- Any operator (data constructor or variable)
+-- | Test if the 'OccName' is a data constructor that starts with
+-- a symbol (e.g. @:@, or @[]@)
+isDataSymOcc :: OccName -> Bool
+isDataSymOcc (OccName DataName s) = isLexConSym s
+isDataSymOcc (OccName VarName s)
+ | isLexConSym s = pprPanic "isDataSymOcc: check me" (ppr s)
+ -- Jan06: I don't think this should happen
+isDataSymOcc _ = False
-- Pretty inefficient!
+
+-- | Test if the 'OccName' is that for any operator (whether
+-- it is a data constructor or variable or whatever)
+isSymOcc :: OccName -> Bool
isSymOcc (OccName DataName s) = isLexConSym s
isSymOcc (OccName TcClsName s) = isLexConSym s
isSymOcc (OccName VarName s) = isLexSym s
isSymOcc (OccName TvName s) = isLexSym s
+-- Pretty inefficient!
parenSymOcc :: OccName -> SDoc -> SDoc
--- Wrap parens around an operator
+-- ^ Wrap parens around an operator
parenSymOcc occ doc | isSymOcc occ = parens doc
| otherwise = doc
\end{code}
\begin{code}
reportIfUnused :: OccName -> Bool
- -- Haskell 98 encourages compilers to suppress warnings about
- -- unused names in a pattern if they start with "_".
+-- ^ Haskell 98 encourages compilers to suppress warnings about
+-- unused names in a pattern if they start with @_@: this implements
+-- that test
reportIfUnused occ = case occNameString occ of
('_' : _) -> False
_other -> True
d... dictionary identifiers
(local variables, so no name-clash worries)
- $f... dict-fun identifiers (from inst decls)
- $dm... default methods
- $p... superclass selectors
- $w... workers
+ \$f... dict-fun identifiers (from inst decls)
+ \$dm... default methods
+ \$p... superclass selectors
+ \$w... workers
:T... compiler-generated tycons for dictionaries
:D... ...ditto data cons
:Co... ...ditto coercions
- $sf.. specialised version of f
+ \$sf.. specialised version of f
in encoded form these appear as Zdfxxx etc
This knowledge is encoded in the following functions.
-
@mk_deriv@ generates an @OccName@ from the prefix and a string.
NB: The string must already be encoded!
-> OccName
mk_deriv occ_sp sys_prefix str = mkOccName occ_sp (sys_prefix ++ str)
+
+isDerivedOccName :: OccName -> Bool
+isDerivedOccName occ =
+ case occNameString occ of
+ '$':c:_ | isAlphaNum c -> True
+ ':':c:_ | isAlphaNum c -> True
+ _other -> False
\end{code}
\begin{code}
mkClassTyConOcc, mkClassDataConOcc, mkDictOcc, mkIPOcc,
mkSpecOcc, mkForeignExportOcc, mkGenOcc1, mkGenOcc2,
mkDataTOcc, mkDataCOcc, mkDataConWorkerOcc, mkNewTyCoOcc,
- mkInstTyCoOcc, mkEqPredCoOcc,
+ mkInstTyCoOcc, mkEqPredCoOcc,
+ mkCon2TagOcc, mkTag2ConOcc, mkMaxTagOcc,
mkVectOcc, mkVectTyConOcc, mkVectDataConOcc, mkVectIsoOcc,
mkPArrayTyConOcc, mkPArrayDataConOcc, mkPReprTyConOcc, mkPADFunOcc
:: OccName -> OccName
mkInstTyCoOcc = mk_simple_deriv tcName ":CoF" -- derived from rep ty
mkEqPredCoOcc = mk_simple_deriv tcName "$co"
+-- used in derived instances
+mkCon2TagOcc = mk_simple_deriv varName "$con2tag_"
+mkTag2ConOcc = mk_simple_deriv varName "$tag2con_"
+mkMaxTagOcc = mk_simple_deriv varName "$maxtag_"
+
-- Generic derivable classes
mkGenOcc1 = mk_simple_deriv varName "$gfrom"
mkGenOcc2 = mk_simple_deriv varName "$gto"
\end{code}
\begin{code}
-mkSuperDictSelOcc :: Int -- Index of superclass, eg 3
- -> OccName -- Class, eg "Ord"
- -> OccName -- eg "$p3Ord"
+mkSuperDictSelOcc :: Int -- ^ Index of superclass, e.g. 3
+ -> OccName -- ^ Class, e.g. @Ord@
+ -> OccName -- ^ Derived 'Occname', e.g. @$p3Ord@
mkSuperDictSelOcc index cls_occ
= mk_deriv varName "$p" (show index ++ occNameString cls_occ)
-mkLocalOcc :: Unique -- Unique
- -> OccName -- Local name (e.g. "sat")
- -> OccName -- Nice unique version ("$L23sat")
+mkLocalOcc :: Unique -- ^ Unique to combine with the 'OccName'
+ -> OccName -- ^ Local name, e.g. @sat@
+ -> OccName -- ^ Nice unique version, e.g. @$L23sat@
mkLocalOcc uniq occ
= mk_deriv varName ("$L" ++ show uniq) (occNameString occ)
-- The Unique might print with characters
-- that need encoding (e.g. 'z'!)
\end{code}
-Derive a name for the representation type constructor of a data/newtype
-instance.
-
\begin{code}
-mkInstTyTcOcc :: Int -- Index
- -> OccName -- Family name (e.g. "Map")
- -> OccName -- Nice unique version (":R23Map")
+-- | Derive a name for the representation type constructor of a @data@/@newtype@
+-- instance.
+mkInstTyTcOcc :: Int -- ^ DFun Index
+ -> OccName -- ^ Family name, e.g. @Map@
+ -> OccName -- ^ Nice unique version, e.g. @:R23Map@
mkInstTyTcOcc index occ
= mk_deriv tcName (":R" ++ show index) (occNameString occ)
\end{code}
\begin{code}
-mkDFunOcc :: String -- Typically the class and type glommed together e.g. "OrdMaybe"
+mkDFunOcc :: String -- ^ Typically the class and type glommed together e.g. @OrdMaybe@.
-- Only used in debug mode, for extra clarity
- -> Bool -- True <=> hs-boot instance dfun
- -> Int -- Unique index
- -> OccName -- "$f3OrdMaybe"
+ -> Bool -- ^ Is this a hs-boot instance DFun?
+ -> Int -- ^ Unique index
+ -> OccName -- ^ E.g. @$f3OrdMaybe@
-- In hs-boot files we make dict funs like $fx7ClsTy, which get bound to the real
-- thing when we compile the mother module. Reason: we don't know exactly
-------------
isLexConId cs -- Prefix type or data constructors
- | nullFS cs = False -- e.g. "Foo", "[]", "(,)"
- | cs == FSLIT("[]") = True
- | otherwise = startsConId (headFS cs)
+ | nullFS cs = False -- e.g. "Foo", "[]", "(,)"
+ | cs == (fsLit "[]") = True
+ | otherwise = startsConId (headFS cs)
isLexVarId cs -- Ordinary prefix identifiers
| nullFS cs = False -- e.g. "x", "_x"
| otherwise = startsVarId (headFS cs)
isLexConSym cs -- Infix type or data constructors
- | nullFS cs = False -- e.g. ":-:", ":", "->"
- | cs == FSLIT("->") = True
- | otherwise = startsConSym (headFS cs)
+ | nullFS cs = False -- e.g. ":-:", ":", "->"
+ | cs == (fsLit "->") = True
+ | otherwise = startsConSym (headFS cs)
isLexVarSym cs -- Infix identifiers
| nullFS cs = False -- e.g. "+"