\begin{code}
module OccName (
-- The NameSpace type; abstact
- NameSpace, tcName, clsName, tcClsName, dataName, varName, ipName,
- tvName, uvName, nameSpaceString,
+ NameSpace, tcName, clsName, tcClsName, dataName, varName,
+ tvName, nameSpaceString,
-- The OccName type
OccName, -- Abstract, instance of Outputable
pprOccName,
- mkSrcOccFS, mkSysOcc, mkSysOccFS, mkCCallOcc, mkSrcVarOcc, mkKindOccFS,
+ mkOccFS, mkSysOcc, mkSysOccFS, mkFCallOcc, mkVarOcc, mkKindOccFS,
mkSuperDictSelOcc, mkDFunOcc, mkForeignExportOcc,
mkDictOcc, mkIPOcc, mkWorkerOcc, mkMethodOcc, mkDefaultMethodOcc,
mkDerivedTyConOcc, mkClassTyConOcc, mkClassDataConOcc, mkSpecOcc,
+ mkGenOcc1, mkGenOcc2, mkLocalOcc,
- isSysOcc, isTvOcc, isUvOcc, isDataOcc, isDataSymOcc, isSymOcc, isIPOcc, isValOcc,
+ isTvOcc, isTcOcc, isDataOcc, isDataSymOcc, isSymOcc, isValOcc,
occNameFS, occNameString, occNameUserString, occNameSpace, occNameFlavour,
setOccNameSpace,
#include "HsVersions.h"
-import Char ( isDigit, isAlpha, isUpper, isLower, ISALPHANUM, ord, chr, digitToInt )
+import Char ( isDigit, isUpper, isLower, ISALPHANUM, ord, chr, digitToInt )
import Util ( thenCmp )
+import Unique ( Unique )
import FiniteMap ( FiniteMap, emptyFM, lookupFM, addToFM, elemFM )
import Outputable
import GlaExts
\begin{code}
data NameSpace = VarName -- Variables
- | IPName -- Implicit Parameters
| DataName -- Data constructors
| TvName -- Type variables
- | UvName -- Usage variables
| TcClsName -- Type constructors and classes; Haskell has them
-- in the same name space for now.
deriving( Eq, Ord )
dataName = DataName
tvName = TvName
-uvName = UvName
varName = VarName
-ipName = IPName
nameSpaceString :: NameSpace -> String
nameSpaceString DataName = "Data constructor"
nameSpaceString VarName = "Variable"
-nameSpaceString IPName = "Implicit Param"
nameSpaceString TvName = "Type variable"
-nameSpaceString UvName = "Usage variable"
nameSpaceString TcClsName = "Type constructor or class"
\end{code}
mkSysOccFS occ_sp fs = ASSERT2( alreadyEncodedFS fs, ppr fs )
OccName occ_sp fs
-mkCCallOcc :: EncodedString -> OccName
+mkFCallOcc :: EncodedString -> OccName
-- This version of mkSysOcc doesn't check that the string is already encoded,
-- because it will be something like "{__ccall f dyn Int# -> Int#}"
-- This encodes a lot into something that then parses like an Id.
-- But then alreadyEncoded complains about the braces!
-mkCCallOcc str = OccName varName (_PK_ str)
+mkFCallOcc str = OccName varName (_PK_ str)
--- Kind constructors get a speical function. Uniquely, they are not encoded,
+-- Kind constructors get a special function. Uniquely, they are not encoded,
-- so that they have names like '*'. This means that *even in interface files*
-- we'll get kinds like (* -> (* -> *)). We can't use mkSysOcc because it
-- has an ASSERT that doesn't hold.
*Source-code* things are encoded.
\begin{code}
-mkSrcOccFS :: NameSpace -> UserFS -> OccName
-mkSrcOccFS occ_sp fs = mkSysOccFS occ_sp (encodeFS fs)
+mkOccFS :: NameSpace -> UserFS -> OccName
+mkOccFS occ_sp fs = mkSysOccFS occ_sp (encodeFS fs)
-mkSrcVarOcc :: UserFS -> OccName
-mkSrcVarOcc fs = mkSysOccFS varName (encodeFS fs)
+mkVarOcc :: UserFS -> OccName
+mkVarOcc fs = mkSysOccFS varName (encodeFS fs)
\end{code}
\end{code}
\begin{code}
-isTvOcc, isDataSymOcc, isSymOcc, isUvOcc :: OccName -> Bool
+isTvOcc, isDataSymOcc, isSymOcc, isTcOcc :: OccName -> Bool
isTvOcc (OccName TvName _) = True
isTvOcc other = False
-isUvOcc (OccName UvName _) = True
-isUvOcc other = False
+isTcOcc (OccName TcClsName _) = True
+isTcOcc other = False
isValOcc (OccName VarName _) = True
isValOcc (OccName DataName _) = True
-- Pretty inefficient!
isSymOcc (OccName DataName s) = isLexConSym (decodeFS s)
isSymOcc (OccName VarName s) = isLexSym (decodeFS s)
-
-isIPOcc (OccName IPName _) = True
-isIPOcc _ = False
\end{code}
$dm... default methods
$p... superclass selectors
$w... workers
- $T... compiler-generated tycons for dictionaries
- $D... ...ditto data cons
+ :T... compiler-generated tycons for dictionaries
+ :D... ...ditto data cons
$sf.. specialised version of f
in encoded form these appear as Zdfxxx etc
:... keywords (export:, letrec: etc.)
+--- I THINK THIS IS WRONG!
This knowledge is encoded in the following functions.
-@mk_deriv@ generates an @OccName@ from the one-char prefix and a string.
+@mk_deriv@ generates an @OccName@ from the prefix and a string.
NB: The string must already be encoded!
\begin{code}
mk_deriv :: NameSpace
-> String -- Distinguishes one sort of derived name from another
-> EncodedString -- Must be already encoded!! We don't want to encode it a
- -- second time because encoding isn't itempotent
+ -- second time because encoding isn't idempotent
-> OccName
mk_deriv occ_sp sys_prefix str = mkSysOcc occ_sp (encode sys_prefix ++ str)
:: OccName -> OccName
-- These derived variables have a prefix that no Haskell value could have
-mkWorkerOcc = mk_simple_deriv varName "$w"
-mkDefaultMethodOcc = mk_simple_deriv varName "$dm"
-mkDerivedTyConOcc = mk_simple_deriv tcName ":" -- The : prefix makes sure it classifies
-mkClassTyConOcc = mk_simple_deriv tcName ":T" -- as a tycon/datacon
-mkClassDataConOcc = mk_simple_deriv dataName ":D" --
-mkDictOcc = mk_simple_deriv varName "$d"
-mkIPOcc = mk_simple_deriv varName "$i"
-mkSpecOcc = mk_simple_deriv varName "$s"
-mkForeignExportOcc = mk_simple_deriv varName "$f"
-
+mkWorkerOcc = mk_simple_deriv varName "$w"
+mkDefaultMethodOcc = mk_simple_deriv varName "$dm"
+mkDerivedTyConOcc = mk_simple_deriv tcName ":" -- The : prefix makes sure it classifies
+mkClassTyConOcc = mk_simple_deriv tcName ":T" -- as a tycon/datacon
+mkClassDataConOcc = mk_simple_deriv dataName ":D" --
+mkDictOcc = mk_simple_deriv varName "$d"
+mkIPOcc = mk_simple_deriv varName "$i"
+mkSpecOcc = mk_simple_deriv varName "$s"
+mkForeignExportOcc = mk_simple_deriv varName "$f"
+mkGenOcc1 = mk_simple_deriv varName "$gfrom" -- Generics
+mkGenOcc2 = mk_simple_deriv varName "$gto" -- Generics
mk_simple_deriv sp px occ = mk_deriv sp px (occNameString occ)
-
-
-isSysOcc :: OccName -> Bool -- True for all these '$' things
-isSysOcc occ = case occNameUserString occ of
- ('$' : _ ) -> True
- other -> False -- We don't care about the ':' ones
- -- isSysOcc is only called for Ids anyway
\end{code}
\begin{code}
mkSuperDictSelOcc :: Int -- Index of superclass, eg 3
-> OccName -- Class, eg "Ord"
- -> OccName -- eg "p3Ord"
+ -> OccName -- eg "$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 uniq occ
+ = mk_deriv varName ("$L" ++ show uniq) (occNameString occ)
+ -- The Unique might print with characters
+ -- that need encoding (e.g. 'z'!)
\end{code}
\begin{code}
mkDFunOcc :: EncodedString -- Typically the class and type glommed together e.g. "OrdMaybe"
- -> Int -- Unique to distinguish dfuns which share the previous two
- -- eg 3
- -- The requirement is that the (string,index) pair be unique in this module
-
- -> OccName -- "$fOrdMaybe3"
+ -> OccName -- "$fOrdMaybe"
-mkDFunOcc string index
- = mk_deriv VarName "$f" (show_index ++ string)
- where
- show_index | index == 0 = ""
- | otherwise = show index
+mkDFunOcc string = mk_deriv VarName "$f" string
\end{code}
We used to add a '$m' to indicate a method, but that gives rise to bad
foo## foozhzh
foo##1 foozhzh1
fooZ fooZZ
- :+ Zczp
- () Z0T
- (,,,,) Z4T
-
+ :+ ZCzp
+ () Z0T 0-tuple
+ (,,,,) Z5T 5-tuple
+ (# #) Z1H unboxed 1-tuple (note the space)
+ (#,,,,#) Z5H unboxed 5-tuple
+ (NB: There is no Z1T nor Z0H.)
\begin{code}
-- alreadyEncoded is used in ASSERTs to check for encoded
encode :: UserString -> EncodedString
encode cs = case maybe_tuple cs of
- Just n -> 'Z' : show n ++ "T" -- Tuples go to Z2T etc
+ Just n -> n -- Tuples go to Z2T etc
Nothing -> go cs
where
go [] = []
go (c:cs) = encode_ch c ++ go cs
--- ToDo: Unboxed tuples too, perhaps?
-maybe_tuple ('(' : cs) = check_tuple (0::Int) cs
-maybe_tuple other = Nothing
+maybe_tuple "(# #)" = Just("Z1H")
+maybe_tuple ('(' : '#' : cs) = case count_commas (0::Int) cs of
+ (n, '#' : ')' : cs) -> Just ('Z' : shows (n+1) "H")
+ other -> Nothing
+maybe_tuple "()" = Just("Z0T")
+maybe_tuple ('(' : cs) = case count_commas (0::Int) cs of
+ (n, ')' : cs) -> Just ('Z' : shows (n+1) "T")
+ other -> Nothing
+maybe_tuple other = Nothing
-check_tuple :: Int -> String -> Maybe Int
-check_tuple n (',' : cs) = check_tuple (n+1) cs
-check_tuple n ")" = Just n
-check_tuple n other = Nothing
+count_commas :: Int -> String -> (Int, String)
+count_commas n (',' : cs) = count_commas (n+1) cs
+count_commas n cs = (n,cs)
encodeFS :: UserFS -> EncodedFS
encodeFS fast_str | all unencodedChar str = fast_str
unencodedChar :: Char -> Bool -- True for chars that don't need encoding
unencodedChar 'Z' = False
unencodedChar 'z' = False
-unencodedChar c = ISALPHANUM c
+unencodedChar c = c >= 'a' && c <= 'z'
+ || c >= 'A' && c <= 'Z'
+ || c >= '0' && c <= '9'
encode_ch :: Char -> EncodedString
encode_ch c | unencodedChar c = [c] -- Common case first
| isDigit c = go (digitToInt c) rest
where
go n (c : rest) | isDigit c = go (10*n + digitToInt c) rest
- go n ('T' : rest) = '(' : replicate n ',' ++ ')' : decode rest
+ go 0 ('T' : rest) = "()" ++ (decode rest)
+ go n ('T' : rest) = '(' : replicate (n-1) ',' ++ ')' : decode rest
+ go 1 ('H' : rest) = "(# #)" ++ (decode rest)
+ go n ('H' : rest) = '(' : '#' : replicate (n-1) ',' ++ '#' : ')' : decode rest
go n ('U' : rest) = chr n : decode rest
go n other = pprPanic "decode_escape" (ppr n <+> text (c:rest))
%************************************************************************
%* *
-n\subsection{Lexical categories}
+\subsection{Lexical categories}
%* *
%************************************************************************