[project @ 2001-10-17 15:39:08 by simonpj]
[ghc-hetmet.git] / ghc / compiler / parser / Lex.lhs
index 353200f..0d04782 100644 (file)
@@ -36,13 +36,13 @@ module Lex (
 import Char            ( isSpace, toUpper )
 import List             ( isSuffixOf )
 
-import IdInfo          ( InlinePragInfo(..) )
 import PrelNames       ( mkTupNameStr )
 import CmdLineOpts     ( opt_HiVersion, opt_NoHiCheck )
 import ForeignCall     ( Safety(..) )
-import Demand          ( Demand(..) {- instance Read -} )
+import NewDemand       ( StrictSig(..), Demand(..), Keepity(..), 
+                         DmdResult(..), mkTopDmdType )
 import UniqFM           ( listToUFM, lookupUFM )
-import BasicTypes      ( NewOrData(..), Boxity(..) )
+import BasicTypes      ( Boxity(..) )
 import SrcLoc          ( SrcLoc, incSrcLine, srcLocFile, srcLocLine,
                          replaceSrcLine, mkSrcLoc )
 
@@ -122,6 +122,7 @@ data Token
   | ITwith
   | ITstdcallconv
   | ITccallconv
+  | ITdotnet
 
   | ITinterface                        -- interface keywords
   | IT__export
@@ -150,8 +151,8 @@ data Token
   | ITarity 
   | ITspecialise
   | ITnocaf
-  | ITunfold InlinePragInfo
-  | ITstrict ([Demand], Bool)
+  | ITunfold
+  | ITstrict StrictSig
   | ITrules
   | ITcprinfo
   | ITdeprecated
@@ -308,6 +309,7 @@ ghcExtensionKeywordsFM = listToUFM $
        ( "with",       ITwith ),
        ( "stdcall",    ITstdcallconv),
        ( "ccall",      ITccallconv),
+       ( "dotnet",     ITdotnet),
         ("_ccall_",    ITccall (False, False, PlayRisky)),
         ("_ccall_GC_", ITccall (False, False, PlaySafe)),
         ("_casm_",     ITccall (False, True,  PlayRisky)),
@@ -343,7 +345,7 @@ ghcExtensionKeywordsFM = listToUFM $
        ("__C",                 ITnocaf),
        ("__R",                 ITrules),
         ("__D",                        ITdeprecated),
-        ("__U",                        ITunfold NoInlinePragInfo),
+        ("__U",                        ITunfold),
        
         ("__ccall",            ITccall (False, False, PlayRisky)),
         ("__ccall_GC",         ITccall (False, False, PlaySafe)),
@@ -403,7 +405,7 @@ lexer cont buf s@(PState{
   where
        line = srcLocLine loc
 
-       tab y bol atbol buf = -- trace ("tab: " ++ show (I# y) ++ " : " ++ show (currentChar buf)) $
+       tab y bol atbol buf = --trace ("tab: " ++ show (I# y) ++ " : " ++ show (currentChar buf)) $
          case currentChar# buf of
 
            '\NUL'# ->
@@ -437,6 +439,9 @@ lexer cont buf s@(PState{
                  let lexeme = mkFastString -- ToDo: too slow
                                  (map toUpper (lexemeToString buf2)) in
                  case lookupUFM pragmaKeywordsFM lexeme of
+                       -- ignore RULES pragmas when -fglasgow-exts is off
+                       Just ITrules_prag | not (flag glaexts) ->
+                          skip_to_end (stepOnBy# buf 2#) s'
                        Just ITline_prag -> 
                           line_prag skip_to_end buf2 s'
                        Just other -> is_a_token
@@ -445,7 +450,7 @@ lexer cont buf s@(PState{
 
                else skip_to_end (stepOnBy# buf 2#) s'
                where
-                   skip_to_end = nested_comment (lexer cont)
+                   skip_to_end = skipNestedComment (lexer cont)
 
                -- special GHC extension: we grok cpp-style #line pragmas
            '#'# | lexemeIndex buf ==# bol ->   -- the '#' must be in column 0
@@ -491,26 +496,34 @@ line_prag cont buf s@PState{loc=loc} =
      _other -> cont (stepOverLexeme buf3) s{loc = replaceSrcLine loc l}
   }}}}
 
-nested_comment :: P a -> P a
-nested_comment cont buf = loop buf
+skipNestedComment :: P a -> P a
+skipNestedComment cont buf state = skipNestedComment' (loc state) cont buf state
+
+skipNestedComment' :: SrcLoc -> P a -> P a
+skipNestedComment' orig_loc cont buf = loop buf
  where
    loop buf = 
      case currentChar# buf of
-       '\NUL'# | bufferExhausted (stepOn buf) -> 
-               lexError "unterminated `{-'" buf -- -}
-       '-'# | lookAhead# buf 1# `eqChar#` '}'# ->
-               cont (stepOnBy# buf 2#)
+       '-'# | lookAhead# buf 1# `eqChar#` '}'# -> cont (stepOnBy# buf 2#)
 
        '{'# | lookAhead# buf 1# `eqChar#` '-'# ->
-             nested_comment (nested_comment cont) (stepOnBy# buf 2#)
+             skipNestedComment 
+               (skipNestedComment' orig_loc cont) 
+               (stepOnBy# buf 2#)
 
        '\n'# -> \ s@PState{loc=loc} ->
                 let buf' = stepOn buf in
-                nested_comment cont buf'
-                       s{loc = incSrcLine loc, bol = currentIndex# buf',
-                         atbol = 1#}
+                loop buf' s{loc = incSrcLine loc, 
+                            bol = currentIndex# buf',
+                            atbol = 1#}
+
+       -- pass the original SrcLoc to lexError so that the error is
+       -- reported at the line it was originally on, not the line at
+       -- the end of the file.
+       '\NUL'# | bufferExhausted (stepOn buf) -> 
+               \s -> lexError "unterminated `{-'" buf s{loc=orig_loc} -- -}
 
-       _   -> nested_comment cont (stepOn buf)
+       _   -> loop (stepOn buf)
 
 -- When we are lexing the first token of a line, check whether we need to
 -- insert virtual semicolons or close braces due to layout.
@@ -550,7 +563,7 @@ lexBOL cont buf s@(PState{
 
 lexToken :: (Token -> P a) -> Int# -> P a
 lexToken cont glaexts buf =
- -- trace "lexToken" $
+-- trace "lexToken" $
   case currentChar# buf of
 
     -- special symbols ----------------------------------------------------
@@ -593,9 +606,11 @@ lexToken cont glaexts buf =
           '-'# -> case lookAhead# buf 2# of
                    '#'# -> case lookAhead# buf 3# of
                                '#'# -> 
-                                  let (lexeme, buf') 
-                                         = doDiscard 0# (stepOnBy# (stepOverLexeme buf) 4#) in
-                                            cont (ITpragma lexeme) buf'
+                                  lexPragma
+                                     cont
+                                     (\ cont lexeme buf' -> cont (ITpragma lexeme) buf')
+                                     0#
+                                     (stepOnBy# (stepOverLexeme buf) 4#)
                                _ -> lex_prag cont (setCurrentPos# buf 3#)
                    _    -> cont ITocurly (incLexeme buf) 
           _ -> (layoutOff `thenP_` cont ITocurly)  (incLexeme buf) 
@@ -816,29 +831,37 @@ silly_escape_chars = [
 lex_demand cont buf = 
  case read_em [] buf of { (ls,buf') -> 
  case currentChar# buf' of
-   'B'# -> cont (ITstrict (ls, True )) (incLexeme buf')
-   _    -> cont (ITstrict (ls, False)) buf'
+   'b'# -> cont (ITstrict (StrictSig (mkTopDmdType ls BotRes))) (incLexeme buf')
+   'm'# -> cont (ITstrict (StrictSig (mkTopDmdType ls RetCPR))) (incLexeme buf')
+   _    -> cont (ITstrict (StrictSig (mkTopDmdType ls TopRes))) buf'
  }
  where
-   -- code snatched from Demand.lhs
   read_em acc buf = 
    case currentChar# buf of
-    'L'# -> read_em (WwLazy False : acc) (stepOn buf)
-    'A'# -> read_em (WwLazy True  : acc) (stepOn buf)
-    'S'# -> read_em (WwStrict     : acc) (stepOn buf)
-    'P'# -> read_em (WwPrim       : acc) (stepOn buf)
-    'E'# -> read_em (WwEnum       : acc) (stepOn buf)
+    'L'# -> read_em (Lazy : acc) (stepOn buf)
+    'A'# -> read_em (Abs : acc) (stepOn buf)
+    'V'# -> read_em (Eval : acc) (stepOn buf)
+    'X'# -> read_em (Err : acc) (stepOn buf)
+    'B'# -> read_em (Bot : acc) (stepOn buf)
     ')'# -> (reverse acc, stepOn buf)
-    'U'# -> do_unpack DataType True  acc (stepOnBy# buf 2#)
-    'u'# -> do_unpack DataType False acc (stepOnBy# buf 2#)
-    'N'# -> do_unpack NewType True  acc (stepOnBy# buf 2#)
-    'n'# -> do_unpack NewType False acc (stepOnBy# buf 2#)
+    'C'# -> do_call acc (stepOnBy# buf 2#)
+    'D'# -> do_unpack1 Defer acc (stepOnBy# buf 1#)
+    'U'# -> do_unpack1 Drop acc (stepOnBy# buf 1#)
+    'S'# -> do_unpack1 Keep acc (stepOnBy# buf 1#)
     _    -> (reverse acc, buf)
 
-  do_unpack new_or_data wrapper_unpacks acc buf
-   = case read_em [] buf of
-      (stuff, rest) -> read_em (WwUnpack new_or_data wrapper_unpacks stuff : acc) rest
+  do_unpack1 keepity acc buf
+    = case currentChar# buf of
+       '('# -> do_unpack2 keepity acc (stepOnBy# buf 1#)
+       _    -> read_em (Seq keepity [] : acc) buf
 
+  do_unpack2 keepity acc buf
+    = case read_em [] buf of
+        (stuff, rest) -> read_em (Seq keepity stuff : acc) rest
+
+  do_call acc buf
+    = case read_em [] buf of
+        ([dmd], rest) -> read_em (Call dmd : acc) rest
 
 ------------------
 lex_scc cont buf =
@@ -950,23 +973,36 @@ lex_sym cont buf =
        where lexeme = lexemeToFastString buf'
 
 
-lex_con cont glaexts buf = 
- -- trace ("con: "{-++unpackFS lexeme-}) $
- case expandWhile# is_ident buf          of { buf1 ->
- case slurp_trailing_hashes buf1 glaexts of { buf' ->
+-- lex_con recursively collects components of a qualified identifer.
+-- The argument buf is the StringBuffer representing the lexeme
+-- identified so far, where the next character is upper-case.
 
- case currentChar# buf' of
-     '.'# -> munch
+lex_con cont glaexts buf =
+ -- trace ("con: "{-++unpackFS lexeme-}) $
+ let empty_buf = stepOverLexeme buf in
+ case expandWhile# is_ident empty_buf    of { buf1 ->
+ case slurp_trailing_hashes buf1 glaexts of { con_buf ->
+
+ let all_buf = mergeLexemes buf con_buf
+     
+     con_lexeme = lexemeToFastString con_buf
+     mod_lexeme = lexemeToFastString (decLexeme buf)
+     all_lexeme = lexemeToFastString all_buf
+
+     just_a_conid
+       | emptyLexeme buf = cont (ITconid con_lexeme)               all_buf
+       | otherwise       = cont (ITqconid (mod_lexeme,con_lexeme)) all_buf
+ in
+
+ case currentChar# all_buf of
+     '.'# -> maybe_qualified cont glaexts all_lexeme 
+               (incLexeme all_buf) just_a_conid
      _    -> just_a_conid
-   where
-    just_a_conid = cont (ITconid lexeme) buf'
-    lexeme = lexemeToFastString buf'
-    munch = lex_qid cont glaexts lexeme (incLexeme buf') just_a_conid
- }}
-
-lex_qid cont glaexts mod buf just_a_conid =
- -- trace ("quid: "{-++unpackFS lexeme-}) $
+  }}
+
+
+maybe_qualified cont glaexts mod buf just_a_conid =
+ -- trace ("qid: "{-++unpackFS lexeme-}) $
  case currentChar# buf of
   '['# ->      -- Special case for []
     case lookAhead# buf 1# of
@@ -987,9 +1023,14 @@ lex_qid cont glaexts mod buf just_a_conid =
   '-'# -> case lookAhead# buf 1# of
             '>'# -> cont (ITqconid (mod,SLIT("(->)"))) (setCurrentPos# buf 2#)
             _    -> lex_id3 cont glaexts mod buf just_a_conid
+
   _    -> lex_id3 cont glaexts mod buf just_a_conid
 
+
 lex_id3 cont glaexts mod buf just_a_conid
+  | is_upper (currentChar# buf) =
+     lex_con cont glaexts buf
+
   | is_symbol (currentChar# buf) =
      let 
        start_new_lexeme = stepOverLexeme buf
@@ -1082,20 +1123,21 @@ lex_ubx_tuple cont mod buf back_off =
 \end{code}
 
 -----------------------------------------------------------------------------
-doDiscard rips along really fast, looking for a '##-}', 
+'lexPragma' rips along really fast, looking for a '##-}', 
 indicating the end of the pragma we're skipping
 
 \begin{code}
-doDiscard inStr buf =
+lexPragma cont contf inStr buf =
  case currentChar# buf of
    '#'# | inStr ==# 0# ->
        case lookAhead# buf 1# of { '#'# -> 
        case lookAhead# buf 2# of { '-'# ->
        case lookAhead# buf 3# of { '}'# -> 
-          (lexemeToBuffer buf, stepOverLexeme (setCurrentPos# buf 4#));
-       _    -> doDiscard inStr (incLexeme buf) };
-        _    -> doDiscard inStr (incLexeme buf) };
-        _    -> doDiscard inStr (incLexeme buf) }
+           contf cont (lexemeToBuffer buf)
+                     (stepOverLexeme (setCurrentPos# buf 4#));
+       _    -> lexPragma cont contf inStr (incLexeme buf) };
+        _    -> lexPragma cont contf inStr (incLexeme buf) };
+        _    -> lexPragma cont contf inStr (incLexeme buf) }
 
    '"'# ->
        let
@@ -1110,19 +1152,24 @@ doDiscard inStr buf =
         '\\'# -> -- escaping something..
           if odd_slashes buf True (negateInt# 2#) 
                then  -- odd number of slashes, " is escaped.
-                     doDiscard inStr (incLexeme buf)
+                     lexPragma cont contf inStr (incLexeme buf)
                else  -- even number of slashes, \ is escaped.
-                     doDiscard not_inStr (incLexeme buf)
-         _ -> doDiscard not_inStr (incLexeme buf)
+                     lexPragma cont contf not_inStr (incLexeme buf)
+         _ -> lexPragma cont contf not_inStr (incLexeme buf)
 
    '\''# | inStr ==# 0# ->
        case lookAhead# buf 1# of { '"'# ->
        case lookAhead# buf 2# of { '\''# ->
-          doDiscard inStr (setCurrentPos# buf 3#);
-       _ -> doDiscard inStr (incLexeme buf) };
-       _ -> doDiscard inStr (incLexeme buf) }
+          lexPragma cont contf inStr (setCurrentPos# buf 3#);
+       _ -> lexPragma cont contf inStr (incLexeme buf) };
+       _ -> lexPragma cont contf inStr (incLexeme buf) }
+
+    -- a sign that the input is ill-formed, since pragmas are
+    -- assumed to always be properly closed (in .hi files).
+   '\NUL'# -> trace "lexPragma: unexpected end-of-file" $ 
+             cont (ITunknown "\NUL") buf
 
-   _ -> doDiscard inStr (incLexeme buf)
+   _ -> lexPragma cont contf inStr (incLexeme buf)
 
 \end{code}