-
+%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
OccName, -- Abstract, instance of Outputable
pprOccName,
- mkSrcOccFS, mkSysOcc, mkSysOccFS, mkSrcVarOcc, mkKindOccFS,
+ mkSrcOccFS, mkSysOcc, mkSysOccFS, mkCCallOcc, mkSrcVarOcc, mkKindOccFS,
mkSuperDictSelOcc, mkDFunOcc, mkForeignExportOcc,
mkDictOcc, mkIPOcc, mkWorkerOcc, mkMethodOcc, mkDefaultMethodOcc,
mkDerivedTyConOcc, mkClassTyConOcc, mkClassDataConOcc, mkSpecOcc,
- isTvOcc, isUvOcc, isDataOcc, isDataSymOcc, isSymOcc, isIPOcc,
+ isSysOcc, isTvOcc, isUvOcc, isDataOcc, isDataSymOcc, isSymOcc, isIPOcc, isValOcc,
occNameFS, occNameString, occNameUserString, occNameSpace, occNameFlavour,
setOccNameSpace,
pprEncodedFS :: EncodedFS -> SDoc
pprEncodedFS fs
= getPprStyle $ \ sty ->
- if userStyle sty then
- text (decode (_UNPK_ fs))
- else
- ptext fs
+ if userStyle sty
+ -- ptext (decodeFS fs) would needlessly pack the string again
+ then text (decode (_UNPK_ fs))
+ else ptext fs
\end{code}
%************************************************************************
\begin{code}
mkSysOcc :: NameSpace -> EncodedString -> OccName
-mkSysOcc occ_sp str = ASSERT( alreadyEncoded str )
+mkSysOcc occ_sp str = ASSERT2( alreadyEncoded str, text str )
OccName occ_sp (_PK_ str)
mkSysOccFS :: NameSpace -> EncodedFS -> OccName
mkSysOccFS occ_sp fs = ASSERT2( alreadyEncodedFS fs, ppr fs )
OccName occ_sp fs
+mkCCallOcc :: 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)
+
-- Kind constructors get a speical 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
isUvOcc (OccName UvName _) = True
isUvOcc other = False
+isValOcc (OccName VarName _) = True
+isValOcc (OccName DataName _) = True
+isValOcc other = False
+
-- Data constructor operator (starts with ':', or '[]')
-- Pretty inefficient!
isDataSymOcc (OccName DataName s) = isLexConSym (decodeFS s)
isDataSymOcc other = False
isDataOcc (OccName DataName _) = True
-isDataOcc oter = False
+isDataOcc other = False
-- Any operator (data constructor or variable)
-- Pretty inefficient!
mkForeignExportOcc = mk_simple_deriv varName "$f"
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}
* Tuples (,,,) are coded as Z3T
-* Alphabetic characters (upper and lower), digits, and '_'
+* Alphabetic characters (upper and lower) and digits
all translate to themselves;
except 'Z', which translates to 'ZZ'
and 'z', which translates to 'zz'
We need both so that we can preserve the variable/tycon distinction
-* Most other printable characters translate to 'Zx' for some
+* Most other printable characters translate to 'zx' or 'Zx' for some
alphabetic character x
-* The others translate as 'Zxdd' where 'dd' is exactly two hexadecimal
+* The others translate as 'zxdd' where 'dd' is exactly two hexadecimal
digits for the ord of the character
Before After
--------------------------
Trak Trak
- foo_wib foo_wib
- > Zg
- >1 Zg1
- foo# fooZh
- foo## fooZhZh
- foo##1 fooZhXh1
+ foo_wib foozuwib
+ > zg
+ >1 zg1
+ foo# foozh
+ foo## foozhzh
+ foo##1 foozhzh1
fooZ fooZZ
- :+ ZcZp
+ :+ Zczp
() Z0T
(,,,,) Z4T
alreadyEncoded :: String -> Bool
alreadyEncoded s = all ok s
where
- ok '_' = True
+ ok ' ' = True
+ -- This is a bit of a lie; if we really wanted spaces
+ -- in names we'd have to encode them. But we do put
+ -- spaces in ccall "occurrences", and we don't want to
+ -- reject them here
ok ch = ISALPHANUM ch
alreadyEncodedFS :: FAST_STRING -> Bool
str = _UNPK_ fast_str
unencodedChar :: Char -> Bool -- True for chars that don't need encoding
-unencodedChar '_' = True
unencodedChar 'Z' = False
unencodedChar 'z' = False
unencodedChar c = ISALPHANUM c
encode_ch 'z' = "zz"
encode_ch '&' = "za"
encode_ch '|' = "zb"
+encode_ch '^' = "zc"
encode_ch '$' = "zd"
encode_ch '=' = "ze"
encode_ch '>' = "zg"
encode_ch '\\' = "zr"
encode_ch '/' = "zs"
encode_ch '*' = "zt"
-encode_ch '^' = "zu"
+encode_ch '_' = "zu"
encode_ch '%' = "zv"
encode_ch c = ['z', 'x', intToDigit hi, intToDigit lo]
where
decode_escape :: EncodedString -> UserString
-decode_escape ('Z' : rest) = 'Z' : decode rest
-decode_escape ('C' : rest) = ':' : decode rest
decode_escape ('L' : rest) = '(' : decode rest
decode_escape ('R' : rest) = ')' : decode rest
decode_escape ('M' : rest) = '[' : decode rest
decode_escape ('N' : rest) = ']' : decode rest
+decode_escape ('C' : rest) = ':' : decode rest
+decode_escape ('Z' : rest) = 'Z' : decode rest
decode_escape ('z' : rest) = 'z' : decode rest
decode_escape ('a' : rest) = '&' : decode rest
decode_escape ('b' : rest) = '|' : decode rest
+decode_escape ('c' : rest) = '^' : decode rest
decode_escape ('d' : rest) = '$' : decode rest
decode_escape ('e' : rest) = '=' : decode rest
decode_escape ('g' : rest) = '>' : decode rest
decode_escape ('r' : rest) = '\\' : decode rest
decode_escape ('s' : rest) = '/' : decode rest
decode_escape ('t' : rest) = '*' : decode rest
-decode_escape ('u' : rest) = '^' : decode rest
+decode_escape ('u' : rest) = '_' : decode rest
decode_escape ('v' : rest) = '%' : decode rest
decode_escape ('x' : d1 : d2 : rest) = chr (digitToInt d1 * 16 + digitToInt d2) : decode rest
isLexConId cs -- Prefix type or data constructors
| _NULL_ cs = False -- e.g. "Foo", "[]", "(,)"
| cs == SLIT("[]") = True
- | c == '(' = True -- (), (,), (,,), ...
- | otherwise = isUpper c || isUpperISO c
- where
- c = _HEAD_ cs
+ | otherwise = startsConId (_HEAD_ cs)
isLexVarId cs -- Ordinary prefix identifiers
| _NULL_ cs = False -- e.g. "x", "_x"
- | otherwise = isLower c || isLowerISO c || c == '_'
- where
- c = _HEAD_ cs
+ | otherwise = startsVarId (_HEAD_ cs)
isLexConSym cs -- Infix type or data constructors
| _NULL_ cs = False -- e.g. ":-:", ":", "->"
- | otherwise = c == ':'
- || cs == SLIT("->")
- where
- c = _HEAD_ cs
+ | cs == SLIT("->") = True
+ | otherwise = startsConSym (_HEAD_ cs)
isLexVarSym cs -- Infix identifiers
| _NULL_ cs = False -- e.g. "+"
- | otherwise = isSymbolASCII c
- || isSymbolISO c
- where
- c = _HEAD_ cs
+ | otherwise = startsVarSym (_HEAD_ cs)
-------------
+startsVarSym, startsVarId, startsConSym, startsConId :: Char -> Bool
+startsVarSym c = isSymbolASCII c || isSymbolISO c -- Infix Ids
+startsConSym c = c == ':' -- Infix data constructors
+startsVarId c = isLower c || isLowerISO c || c == '_' -- Ordinary Ids
+startsConId c = isUpper c || isUpperISO c || c == '(' -- Ordinary type constructors and data constructors
+
+
isSymbolASCII c = c `elem` "!#$%&*+./<=>?@\\^|~-"
isSymbolISO c = ord c `elem` (0xd7 : 0xf7 : [0xa1 .. 0xbf])
isUpperISO (C# c#) = c# `geChar#` '\xc0'# && c# `leChar#` '\xde'# && c# `neChar#` '\xd7'#