[project @ 2000-06-12 13:40:20 by panne]
[ghc-hetmet.git] / ghc / compiler / basicTypes / OccName.lhs
index 0735434..94b50bb 100644 (file)
@@ -7,19 +7,19 @@
 \begin{code}
 module OccName (
        -- The NameSpace type; abstact
-       NameSpace, tcName, clsName, tcClsName, dataName, varName, tvName,
-       nameSpaceString, 
+       NameSpace, tcName, clsName, tcClsName, dataName, varName, ipName,
+       tvName, uvName, nameSpaceString, 
 
        -- The OccName type
        OccName,        -- Abstract, instance of Outputable
        pprOccName, 
 
-       mkSrcOccFS, mkSysOcc, mkSysOccFS, mkSrcVarOcc, mkKindOccFS,
+       mkSrcOccFS, mkSysOcc, mkSysOccFS, mkCCallOcc, mkSrcVarOcc, mkKindOccFS,
        mkSuperDictSelOcc, mkDFunOcc, mkForeignExportOcc,
-       mkDictOcc, mkWorkerOcc, mkMethodOcc, mkDefaultMethodOcc,
+       mkDictOcc, mkIPOcc, mkWorkerOcc, mkMethodOcc, mkDefaultMethodOcc,
        mkDerivedTyConOcc, mkClassTyConOcc, mkClassDataConOcc, mkSpecOcc,
        
-       isTvOcc, isDataOcc, isDataSymOcc, isSymOcc,
+       isSysOcc, isTvOcc, isUvOcc, isDataOcc, isDataSymOcc, isSymOcc, isIPOcc, isValOcc,
 
        occNameFS, occNameString, occNameUserString, occNameSpace, occNameFlavour, 
        setOccNameSpace,
@@ -58,7 +58,7 @@ code the encoding operation is not performed on each occurrence.
 These type synonyms help documentation.
 
 \begin{code}
-type UserFS     = FAST_STRING  -- As the user typed it
+type UserFS    = FAST_STRING   -- As the user typed it
 type EncodedFS = FAST_STRING   -- Encoded form
 
 type UserString = String       -- As the user typed it
@@ -68,10 +68,10 @@ type EncodedString = String -- Encoded form
 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}
 
 %************************************************************************
@@ -82,10 +82,12 @@ pprEncodedFS fs
 
 \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.  
+                               -- in the same name space for now.
               deriving( Eq, Ord )
 
 -- Though type constructors and classes are in the same name space now,
@@ -96,13 +98,17 @@ tcClsName = TcClsName               -- Not sure which!
 
 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}
 
@@ -156,13 +162,20 @@ already encoded
 
 \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
@@ -211,23 +224,33 @@ occNameFlavour (OccName sp _) = nameSpaceString sp
 \end{code}
 
 \begin{code}
-isTvOcc, isDataSymOcc, isSymOcc :: OccName -> Bool
+isTvOcc, isDataSymOcc, isSymOcc, isUvOcc :: OccName -> Bool
 
 isTvOcc (OccName TvName _) = True
 isTvOcc other              = False
 
+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!
 isSymOcc (OccName DataName s) = isLexConSym (decodeFS s)
 isSymOcc (OccName VarName s)  = isLexSym (decodeFS s)
+
+isIPOcc (OccName IPName _) = True
+isIPOcc _                 = False
 \end{code}
 
 
@@ -271,7 +294,7 @@ mk_deriv occ_sp sys_prefix str = mkSysOcc occ_sp (encode sys_prefix ++ str)
 \end{code}
 
 \begin{code}
-mkDictOcc, mkWorkerOcc, mkDefaultMethodOcc,
+mkDictOcc, mkIPOcc, mkWorkerOcc, mkDefaultMethodOcc,
           mkClassTyConOcc, mkClassDataConOcc, mkSpecOcc
    :: OccName -> OccName
 
@@ -282,10 +305,18 @@ mkDerivedTyConOcc  = mk_simple_deriv tcName   ":" -- The : prefix makes sure it
 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"
 
 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}
@@ -298,18 +329,16 @@ mkSuperDictSelOcc index cls_occ
 
 
 \begin{code}
-mkDFunOcc :: OccName   -- class, eg "Ord"
-         -> OccName    -- tycon (or something convenient from the instance type)
-                       --      eg "Maybe"
-         -> Int        -- Unique to distinguish dfuns which share the previous two
-                       --      eg 3
-         -> OccName    -- "dOrdMaybe3"
-
-mkDFunOcc cls_occ tycon_occ index
-  = mk_deriv VarName "$f" (show_index ++ cls_str ++ tycon_str)
+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"
+
+mkDFunOcc string index
+  = mk_deriv VarName "$f" (show_index ++ string)
   where
-    cls_str   = occNameString cls_occ
-    tycon_str = occNameString tycon_occ
     show_index | index == 0 = ""
               | otherwise  = show index
 \end{code}
@@ -400,29 +429,29 @@ The basic encoding scheme is this.
 
 * 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
 
@@ -434,7 +463,10 @@ The basic encoding scheme is this.
 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
@@ -464,7 +496,6 @@ encodeFS fast_str  | all unencodedChar str = fast_str
                     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
@@ -484,6 +515,7 @@ encode_ch 'Z'  = "ZZ"
 encode_ch 'z'  = "zz"
 encode_ch '&'  = "za"
 encode_ch '|'  = "zb"
+encode_ch '^'  = "zc"
 encode_ch '$'  = "zd"
 encode_ch '='  = "ze"
 encode_ch '>'  = "zg"
@@ -497,7 +529,7 @@ encode_ch '\'' = "zq"
 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
@@ -518,16 +550,17 @@ decode (c   : rest) = c : decode rest
 
 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
@@ -541,7 +574,7 @@ decode_escape ('q' : 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
 
@@ -581,32 +614,29 @@ isLexSym cs = isLexConSym cs || isLexVarSym cs
 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'#