2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 \section[Lexical analysis]{Lexical analysis}
6 --------------------------------------------------------
8 There's a known bug in here:
10 If an interface file ends prematurely, Lex tries to
11 do headFS of an empty FastString.
13 An example that provokes the error is
15 f _:_ _forall_ [a] <<<END OF FILE>>>
16 --------------------------------------------------------
19 {-# OPTIONS -#include "ctypes.h" #-}
26 IfaceToken(..), lexIface, IfM, thenIf, returnIf, getSrcLocIf,
33 #include "HsVersions.h"
35 import Char ( ord, isSpace )
36 import List ( isSuffixOf )
38 import IdInfo ( InlinePragInfo(..), CprInfo(..) )
39 import Name ( isLowerISO, isUpperISO )
40 import Module ( IfaceFlavour, hiFile, hiBootFile )
41 import PrelMods ( mkTupNameStr, mkUbxTupNameStr )
42 import CmdLineOpts ( opt_IgnoreIfacePragmas, opt_HiVersion, opt_NoHiCheck )
43 import Demand ( Demand(..) {- instance Read -} )
44 import UniqFM ( UniqFM, listToUFM, lookupUFM)
45 import BasicTypes ( NewOrData(..) )
46 import SrcLoc ( SrcLoc, incSrcLine, srcLocFile )
48 import Maybes ( MaybeErr(..) )
49 import ErrUtils ( Message )
57 #if __GLASGOW_HASKELL__ >= 303
63 import PrelRead ( readRational__ ) -- Glasgow non-std
66 %************************************************************************
68 \subsection{Data types}
70 %************************************************************************
72 The token data type, fairly un-interesting except from one
73 constructor, @ITidinfo@, which is used to lazily lex id info (arity,
74 strictness, unfolding etc).
76 The Idea/Observation here is that the renamer needs to scan through
77 all of an interface file before it can continue. But only a fraction
78 of the information contained in the file turns out to be useful, so
79 delaying as much as possible of the scanning and parsing of an
80 interface file Makes Sense (Heap profiles of the compiler
81 show a reduction in heap usage by at least a factor of two,
84 Hence, the interface file lexer spots when value declarations are
85 being scanned and return the @ITidinfo@ and @ITtype@ constructors
86 for the type and any other id info for that binding (unfolding, strictness
87 etc). These constructors are applied to the result of lexing these sub-chunks.
89 The lexing of the type and id info is all done lazily, of course, so
90 the scanning (and subsequent parsing) will be done *only* on the ids the
91 renamer finds out that it is interested in. The rest will just be junked.
92 Laziness, you know it makes sense :-)
96 = ITcase -- Haskell keywords
121 | ITinterface -- GHC-extension keywords
128 | ITccall (Bool,Bool,Bool) -- (is_dyn, is_casm, may_gc)
138 | ITonce -- usage annotations
143 | ITunfold InlinePragInfo
144 | ITstrict ([Demand], Bool)
145 | ITcprinfo (CprInfo)
149 | ITdotdot -- reserved symbols
162 | ITbiglam -- GHC-extension symbols
164 | ITocurly -- special symbols
175 | ITvarid FAST_STRING -- identifiers
176 | ITconid FAST_STRING
177 | ITvarsym FAST_STRING
178 | ITconsym FAST_STRING
179 | ITqvarid (FAST_STRING,FAST_STRING,IfaceFlavour)
180 | ITqconid (FAST_STRING,FAST_STRING,IfaceFlavour)
181 | ITqvarsym (FAST_STRING,FAST_STRING,IfaceFlavour)
182 | ITqconsym (FAST_STRING,FAST_STRING,IfaceFlavour)
184 | ITpragma StringBuffer
187 | ITstring FAST_STRING
189 | ITrational Rational
191 | ITunknown String -- Used when the lexer can't make sense of it
192 | ITeof -- end of file token
193 deriving Text -- debugging
196 %************************************************************************
198 \subsection{The lexical analyser}
200 %************************************************************************
203 lexIface :: (IfaceToken -> IfM a) -> IfM a
206 -- if bufferExhausted buf then
209 -- trace ("Lexer: '"++[C# (currentChar# buf)]++"'") $
210 case currentChar# buf of
211 -- whitespace and comments, ignore.
212 ' '# -> lexIface cont (stepOn buf)
213 '\t'# -> lexIface cont (stepOn buf)
214 '\n'# -> \ loc -> lexIface cont (stepOn buf) (incSrcLine loc)
216 -- Numbers and comments
218 case lookAhead# buf 1# of
219 -- '-'# -> lex_comment cont (stepOnBy# buf 2#)
222 then lex_num cont (negate) (ord# c -# ord# '0'#) (incLexeme (incLexeme buf))
223 else lex_sym cont buf
225 '{'# -> -- look for "{-##" special iface pragma
226 case lookAhead# buf 1# of
227 '-'# -> case lookAhead# buf 2# of
228 '#'# -> case lookAhead# buf 3# of
231 = doDiscard False (stepOnBy# buf 4#) in
232 cont (ITpragma lexeme) buf'
233 _ -> lex_nested_comment (lexIface cont) buf
234 _ -> cont ITocurly (stepOn buf)
235 -- lex_nested_comment (lexIface cont) buf
236 _ -> cont ITocurly (stepOn buf)
238 -- special symbols ----------------------------------------------------
240 case prefixMatch (stepOn buf) "..)" of
241 Just buf' -> cont ITdotdot (stepOverLexeme buf')
243 case lookAhead# buf 1# of
244 '#'# -> cont IToubxparen (stepOnBy# buf 2#)
245 _ -> cont IToparen (stepOn buf)
246 ')'# -> cont ITcparen (stepOn buf)
247 '}'# -> cont ITccurly (stepOn buf)
248 '#'# -> case lookAhead# buf 1# of
249 ')'# -> cont ITcubxparen (stepOnBy# buf 2#)
250 _ -> lex_sym cont (incLexeme buf)
251 '['# -> cont ITobrack (stepOn buf)
252 ']'# -> cont ITcbrack (stepOn buf)
253 ','# -> cont ITcomma (stepOn buf)
254 ';'# -> cont ITsemi (stepOn buf)
256 -- strings/characters -------------------------------------------------
257 '\"'#{-"-} -> case untilEndOfString# (stepOn buf) of
259 -- the string literal does *not* include the dquotes
260 case lexemeToFastString buf' of
261 v -> cont (ITstring v) (stepOn (stepOverLexeme buf'))
264 -- untilEndOfChar# extends the current lexeme until
265 -- it hits a non-escaped single quote. The lexeme of the
266 -- StringBuffer returned does *not* include the closing quote,
267 -- hence we augment the lexeme and make sure to add the
268 -- starting quote, before `read'ing the string.
270 case untilEndOfChar# (stepOn buf) of
271 buf' -> case reads ('\'':lexemeToString (incLexeme buf')) of
272 [ (ch, rest)] -> cont (ITchar ch) (stepOverLexeme (incLexeme buf'))
274 -- strictness and cpr pragmas and __scc treated specially.
276 case lookAhead# buf 1# of
277 '_'# -> case lookAhead# buf 2# of
279 lex_demand cont (stepOnUntil (not . isSpace)
280 (stepOnBy# buf 3#)) -- past __S
282 lex_cpr cont (stepOnUntil (not . isSpace)
283 (stepOnBy# buf 3#)) -- past __M
285 case prefixMatch (stepOnBy# buf 3#) "cc" of
286 Just buf' -> lex_scc cont (stepOverLexeme buf')
287 Nothing -> lex_id cont buf
291 -- ``thingy'' form for casm
293 case lookAhead# buf 1# of
294 '`'# -> lex_cstring cont (stepOnBy# buf 2#) -- remove the `s and go.
295 _ -> lex_sym cont (incLexeme buf) -- add ` to lexeme and assume
296 -- scanning an id of some sort.
299 if bufferExhausted (stepOn buf) then
302 trace "lexIface: misplaced NUL?" $
303 cont (ITunknown "\NUL") (stepOn buf)
305 c | is_digit c -> lex_num cont (id) (ord# c -# ord# '0'#) (incLexeme buf)
306 | is_symbol c -> lex_sym cont buf
307 | is_upper c -> lex_con cont buf
308 | is_ident c -> lex_id cont buf
311 lex_comment cont buf =
312 -- _trace ("comment: "++[C# (currentChar# buf)]) $
313 case untilChar# buf '\n'# of {buf' -> lexIface cont (stepOverLexeme buf')}
315 -------------------------------------------------------------------------------
317 lex_nested_comment cont buf =
318 case currentChar# buf of
319 '-'# -> case lookAhead# buf 1# of
320 '}'# -> cont (stepOnBy# buf 2#)
321 _ -> lex_nested_comment cont (stepOn buf)
323 '{'# -> case lookAhead# buf 1# of
324 '-'# -> lex_nested_comment
325 (lex_nested_comment cont)
327 _ -> lex_nested_comment cont (stepOn buf)
329 _ -> lex_nested_comment cont (stepOn buf)
331 -------------------------------------------------------------------------------
333 lex_demand cont buf =
334 case read_em [] buf of { (ls,buf') ->
335 case currentChar# buf' of
336 'B'# -> cont (ITstrict (ls, True )) (stepOverLexeme (stepOn buf'))
337 _ -> cont (ITstrict (ls, False)) (stepOverLexeme buf')
340 -- code snatched from Demand.lhs
342 case currentChar# buf of
343 'L'# -> read_em (WwLazy False : acc) (stepOn buf)
344 'A'# -> read_em (WwLazy True : acc) (stepOn buf)
345 'S'# -> read_em (WwStrict : acc) (stepOn buf)
346 'P'# -> read_em (WwPrim : acc) (stepOn buf)
347 'E'# -> read_em (WwEnum : acc) (stepOn buf)
348 ')'# -> (reverse acc, stepOn buf)
349 'U'# -> do_unpack DataType True acc (stepOnBy# buf 2#)
350 'u'# -> do_unpack DataType False acc (stepOnBy# buf 2#)
351 'N'# -> do_unpack NewType True acc (stepOnBy# buf 2#)
352 'n'# -> do_unpack NewType False acc (stepOnBy# buf 2#)
353 _ -> (reverse acc, buf)
355 do_unpack new_or_data wrapper_unpacks acc buf
356 = case read_em [] buf of
357 (stuff, rest) -> read_em (WwUnpack new_or_data wrapper_unpacks stuff : acc) rest
360 case read_em [] buf of { (cpr_inf,buf') ->
361 ASSERT ( null (tail cpr_inf) )
362 cont (ITcprinfo $ head cpr_inf) (stepOverLexeme buf')
365 -- code snatched from lex_demand above
367 case currentChar# buf of
368 '-'# -> read_em (NoCPRInfo : acc) (stepOn buf)
369 '('# -> do_unpack acc (stepOn buf)
370 ')'# -> (reverse acc, stepOn buf)
371 _ -> (reverse acc, buf)
374 = case read_em [] buf of
375 (stuff, rest) -> read_em ((CPRInfo stuff) : acc) rest
379 case currentChar# buf of
380 'C'# -> cont ITsccAllCafs (stepOverLexeme (stepOn buf))
381 other -> cont ITscc buf
384 lex_num :: (IfaceToken -> IfM a) -> (Int -> Int) -> Int# -> IfM a
385 lex_num cont minus acc# buf =
386 --trace ("lex_num: "++[C# (currentChar# buf)]) $
387 case scanNumLit (I# acc#) buf of
389 case currentChar# buf' of
391 -- this case is not optimised at all, as the
392 -- presence of floating point numbers in interface
393 -- files is not that common. (ToDo)
394 case expandWhile# is_digit (incLexeme buf') of
395 buf2 -> -- points to first non digit char
396 let l = case currentChar# buf2 of
397 'e'# -> let buf3 = incLexeme buf2 in
398 case currentChar# buf3 of
399 '-'# -> expandWhile# is_digit (incLexeme buf3)
400 _ -> expandWhile# is_digit buf3
402 in let v = readRational__ (lexemeToString l) in
403 cont (ITrational v) (stepOverLexeme l)
405 _ -> cont (ITinteger (fromInt (minus acc'))) (stepOverLexeme buf')
408 lex_cstring cont buf =
409 case expandUntilMatch buf "\'\'" of
410 buf' -> cont (ITstring (lexemeToFastString (setCurrentPos# buf' (negateInt# 2#))))
411 (stepOverLexeme buf')
413 ------------------------------------------------------------------------------
416 is_ident, is_symbol, is_any, is_upper, is_digit :: Char# -> Bool
418 {-# INLINE is_ctype #-}
419 #if __GLASGOW_HASKELL__ >= 303
420 is_ctype :: Word8 -> Char# -> Bool
421 is_ctype mask = \c ->
422 (indexWord8OffAddr (``char_types'' :: Addr) (ord (C# c)) .&. mask) /= 0
424 is_ctype :: Int -> Char# -> Bool
425 is_ctype (I# mask) = \c ->
426 let (A# ctype) = ``char_types'' :: Addr
427 flag_word = int2Word# (ord# (indexCharOffAddr# ctype (ord# c)))
429 (flag_word `and#` (int2Word# mask)) `neWord#` (int2Word# 0#)
432 is_ident = is_ctype 1
433 is_symbol = is_ctype 2
435 is_space = is_ctype 8
436 is_upper = is_ctype 16
437 is_digit = is_ctype 32
439 -----------------------------------------------------------------------------
440 -- identifiers, symbols etc.
443 case expandWhile# is_ident buf of { buf1 ->
444 case expandWhile# (eqChar# '#'#) buf1 of { buf' -> -- only if GHC extns on
445 let new_buf = stepOverLexeme buf'
446 lexeme = lexemeToFastString buf'
448 case _scc_ "Lex.haskellKeyword" lookupUFM haskellKeywordsFM lexeme of {
449 Just kwd_token -> --trace ("hkeywd: "++_UNPK_(lexeme)) $
450 cont kwd_token new_buf;
452 case lookupUFM ifaceKeywordsFM lexeme of {
453 Just kwd_token -> --trace ("ifacekeywd: "++_UNPK_(lexeme)) $
454 cont kwd_token new_buf;
455 Nothing -> --trace ("id: "++_UNPK_(lexeme)) $
456 cont (mk_var_token lexeme) new_buf
460 case expandWhile# is_symbol buf of
462 | is_comment lexeme -> lex_comment cont new_buf
464 case lookupUFM haskellKeySymsFM lexeme of {
465 Just kwd_token -> --trace ("keysym: "++unpackFS lexeme) $
466 cont kwd_token new_buf ;
467 Nothing -> --trace ("sym: "++unpackFS lexeme) $
468 cont (mk_var_token lexeme) new_buf
470 where lexeme = lexemeToFastString buf'
471 new_buf = stepOverLexeme buf'
475 | otherwise = trundle 0
479 trundle n | n == len = True
480 | otherwise = indexFS fs n == '-' && trundle (n+1)
483 case expandWhile# is_ident buf of { buf1 ->
484 case expandWhile# (eqChar# '#'#) buf1 of { buf' ->
485 case currentChar# buf' of
487 '!'# -> munch hiBootFile
491 just_a_conid = --trace ("con: "++unpackFS lexeme) $
492 cont (ITconid lexeme) new_buf
493 lexeme = lexemeToFastString buf'
494 new_buf = stepOverLexeme buf'
495 munch hif = lex_qid cont lexeme hif (stepOn new_buf) just_a_conid
498 lex_qid cont mod hif buf just_a_conid =
499 case currentChar# buf of
500 '['# -> -- Special case for []
501 case lookAhead# buf 1# of
502 ']'# -> cont (ITqconid (mod,SLIT("[]"),hif)) (stepOnBy# buf 2#)
505 '('# -> -- Special case for (,,,)
506 -- This *is* necessary to deal with e.g. "instance C PrelBase.(,,)"
507 case lookAhead# buf 1# of
508 '#'# -> case lookAhead# buf 2# of
509 ','# -> lex_ubx_tuple cont mod hif (stepOnBy# buf 3#)
512 ')'# -> cont (ITqconid (mod,SLIT("()"),hif)) (stepOnBy# buf 2#)
513 ','# -> lex_tuple cont mod hif (stepOnBy# buf 2#) just_a_conid
516 '-'# -> case lookAhead# buf 1# of
517 '>'# -> cont (ITqconid (mod,SLIT("->"),hif)) (stepOnBy# buf 2#)
518 _ -> lex_id3 cont mod hif buf just_a_conid
519 _ -> lex_id3 cont mod hif buf just_a_conid
521 lex_id3 cont mod hif buf just_a_conid
523 case expandWhile# is_symbol buf of { buf' ->
525 lexeme = lexemeToFastString buf'
526 new_buf = stepOverLexeme buf'
528 case lookupUFM haskellKeySymsFM lexeme of {
529 Just kwd_token -> just_a_conid; -- avoid M.:: etc.
530 Nothing -> cont (mk_qvar_token mod hif lexeme) new_buf
534 case expandWhile# is_ident buf of { buf1 ->
538 case expandWhile# (eqChar# '#'#) buf1 of { buf' -> -- only if GHC extns on
540 lexeme = lexemeToFastString buf'
541 new_buf = stepOverLexeme buf'
543 case _scc_ "Lex.haskellKeyword" lookupUFM haskellKeywordsFM lexeme of {
544 Just kwd_token -> just_a_conid; -- avoid M.where etc.
546 case lookupUFM ifaceKeywordsFM lexeme of { -- only for iface files
547 Just kwd_token -> just_a_conid;
548 Nothing -> cont (mk_qvar_token mod hif lexeme) new_buf
550 where c = currentChar# buf
553 | is_upper f = ITconid pk_str
554 -- _[A-Z] is treated as a constructor in interface files.
555 | f `eqChar#` '_'# && not (_NULL_ tl)
556 && (case _HEAD_ tl of { C# g -> is_upper g }) = ITconid pk_str
557 | is_ident f = ITvarid pk_str
558 | f `eqChar#` ':'# = ITconsym pk_str
559 | otherwise = ITvarsym pk_str
561 (C# f) = _HEAD_ pk_str
564 mk_qvar_token m hif token =
565 case mk_var_token token of
566 ITconid n -> ITqconid (m,n,hif)
567 ITvarid n -> ITqvarid (m,n,hif)
568 ITconsym n -> ITqconsym (m,n,hif)
569 ITvarsym n -> ITqvarsym (m,n,hif)
570 _ -> ITunknown (show token)
573 ----------------------------------------------------------------------------
574 Horrible stuff for dealing with M.(,,,)
577 lex_tuple cont mod hif buf back_off =
581 case currentChar# buf of
582 ','# -> go (n+1) (stepOn buf)
583 ')'# -> cont (ITqconid (mod, snd (mkTupNameStr n),hif)) (stepOn buf)
586 lex_ubx_tuple cont mod hif buf back_off =
590 case currentChar# buf of
591 ','# -> go (n+1) (stepOn buf)
592 '#'# -> case lookAhead# buf 1# of
593 ')'# -> cont (ITqconid (mod, snd (mkUbxTupNameStr n), hif))
599 -----------------------------------------------------------------------------
603 ifaceKeywordsFM :: UniqFM IfaceToken
604 ifaceKeywordsFM = listToUFM $
605 map (\ (x,y) -> (_PK_ x,y))
606 [ ("__interface", ITinterface),
607 ("__export", ITexport),
608 ("__instimport", ITinstimport),
609 ("__forall", ITforall),
610 ("__letrec", ITletrec),
611 ("__coerce", ITcoerce),
612 ("__inline", ITinline),
613 ("__DEFAULT", ITdefaultbranch),
615 ("__integer", ITinteger_lit),
616 ("__float", ITfloat_lit),
617 ("__rational", ITrational_lit),
618 ("__addr", ITaddr_lit),
619 ("__litlit", ITlit_lit),
620 ("__string", ITstring_lit),
625 ("__P", ITspecialise),
627 ("__u", ITunfold NoInlinePragInfo),
628 ("__U", ITunfold IWantToBeINLINEd),
629 ("__UU", ITunfold IMustBeINLINEd),
630 ("__Unot", ITunfold IMustNotBeINLINEd),
631 ("__Ux", ITunfold IAmALoopBreaker),
633 ("__ccall", ITccall (False, False, False)),
634 ("__ccall_GC", ITccall (False, False, True)),
635 ("__dyn_ccall", ITccall (True, False, False)),
636 ("__dyn_ccall_GC", ITccall (True, False, True)),
637 ("__casm", ITccall (False, True, False)),
638 ("__dyn_casm", ITccall (True, True, False)),
639 ("__casm_GC", ITccall (False, True, True)),
640 ("__dyn_casm_GC", ITccall (True, True, True)),
645 haskellKeywordsFM = listToUFM $
646 map (\ (x,y) -> (_PK_ x,y))
648 ( "class", ITclass ),
650 ( "default", ITdefault ),
651 ( "deriving", ITderiving ),
655 ( "import", ITimport ),
657 ( "infix", ITinfix ),
658 ( "infixl", ITinfixl ),
659 ( "infixr", ITinfixr ),
660 ( "instance", ITinstance ),
662 ( "module", ITmodule ),
663 ( "newtype", ITnewtype ),
669 -- These three aren't Haskell keywords at all
670 -- and 'as' is often used as a variable name
672 -- ( "qualified", ITqualified ),
673 -- ( "hiding", IThiding )
677 haskellKeySymsFM = listToUFM $
678 map (\ (x,y) -> (_PK_ x,y))
694 -----------------------------------------------------------------------------
695 doDiscard rips along really fast, looking for a '#-}',
696 indicating the end of the pragma we're skipping
699 doDiscard inStr buf =
700 case currentChar# buf of
702 case lookAhead# buf 1# of { '#'# ->
703 case lookAhead# buf 2# of { '-'# ->
704 case lookAhead# buf 3# of { '}'# ->
705 (lexemeToBuffer buf, stepOverLexeme (setCurrentPos# buf 4#));
706 _ -> doDiscard inStr (incLexeme buf) };
707 _ -> doDiscard inStr (incLexeme buf) };
708 _ -> doDiscard inStr (incLexeme buf) }
711 odd_slashes buf flg i# =
712 case lookAhead# buf i# of
713 '\\'# -> odd_slashes buf (not flg) (i# -# 1#)
716 case lookAhead# buf (negateInt# 1#) of --backwards, actually
717 '\\'# -> -- escaping something..
718 if odd_slashes buf True (negateInt# 2#) then
719 -- odd number of slashes, " is escaped.
720 doDiscard inStr (incLexeme buf)
722 -- even number of slashes, \ is escaped.
723 doDiscard (not inStr) (incLexeme buf)
724 _ -> case inStr of -- forced to avoid build-up
725 True -> doDiscard False (incLexeme buf)
726 False -> doDiscard True (incLexeme buf)
727 _ -> doDiscard inStr (incLexeme buf)
731 -----------------------------------------------------------------------------
734 type IfM a = StringBuffer -- Input string
736 -> MaybeErr a {-error-}Message
738 returnIf :: a -> IfM a
739 returnIf a s l = Succeeded a
741 thenIf :: IfM a -> (a -> IfM b) -> IfM b
742 m `thenIf` k = \s l ->
744 Succeeded a -> k a s l
745 Failed err -> Failed err
747 getSrcLocIf :: IfM SrcLoc
748 getSrcLocIf s l = Succeeded l
751 happyError s l = Failed (ifaceParseErr s l)
755 Note that if the name of the file we're processing ends
756 with `hi-boot', we accept it on faith as having the right
757 version. This is done so that .hi-boot files that comes
758 with hsc don't have to be updated before every release,
759 *and* it allows us to share .hi-boot files with versions
760 of hsc that don't have .hi version checking (e.g., ghc-2.10's)
762 If the version number is 0, the checking is also turned off.
763 (needed to deal with GHC.hi only!)
765 Once we can assume we're compiling with a version of ghc that
766 supports interface file checking, we can drop the special
769 checkVersion :: Maybe Integer -> IfM ()
770 checkVersion mb@(Just v) s l
771 | (v==0) || (v == fromInt opt_HiVersion) || opt_NoHiCheck = Succeeded ()
772 | otherwise = Failed (ifaceVersionErr mb l ([]::[IfaceToken]){-Todo-})
773 checkVersion mb@Nothing s l
774 | "hi-boot" `isSuffixOf` (_UNPK_ (srcLocFile l)) = Succeeded ()
775 | otherwise = Failed (ifaceVersionErr mb l ([]::[IfaceToken]){-Todo-})
777 -----------------------------------------------------------------
779 ifaceParseErr :: StringBuffer -> SrcLoc -> Message
781 = hsep [ppr l, ptext SLIT("Interface-file parse error;"),
782 ptext SLIT("current input ="), text first_bit]
784 first_bit = lexemeToString (stepOnBy# s 100#)
786 ifaceVersionErr hi_vers l toks
787 = hsep [ppr l, ptext SLIT("Interface file version error;"),
788 ptext SLIT("Expected"), int opt_HiVersion,
789 ptext SLIT("found "), pp_version]
793 Nothing -> ptext SLIT("pre ghc-3.02 version")
794 Just v -> ptext SLIT("version") <+> integer v