X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Fparser%2FLexer.x;h=0a8c4104a76460aac29c54883cd53462a29445fc;hb=6517f499c5b7a7b9dd217e5394a159ba9df5dd8c;hp=316f21f1e9a9368082e73207a421aad51703f437;hpb=84923cc7de2a93c22a2f72daf9ac863959efae13;p=ghc-hetmet.git diff --git a/compiler/parser/Lexer.x b/compiler/parser/Lexer.x index 316f21f..0a8c410 100644 --- a/compiler/parser/Lexer.x +++ b/compiler/parser/Lexer.x @@ -25,6 +25,7 @@ module Lexer ( Token(..), lexer, pragState, mkPState, PState(..), P(..), ParseResult(..), getSrcLoc, failLocMsgP, failSpanMsgP, srcParseFail, + getMessages, popContext, pushCurrentContext, setLastToken, setSrcLoc, getLexState, popLexState, pushLexState, extension, glaExtsEnabled, bangPatEnabled @@ -32,7 +33,8 @@ module Lexer ( #include "HsVersions.h" -import ErrUtils ( Message ) +import Bag +import ErrUtils import Outputable import StringBuffer import FastString @@ -43,6 +45,7 @@ import DynFlags import Ctype import Util ( maybePrefixMatch, readRational ) +import Control.Monad import Data.Bits import Data.Char ( chr, isSpace ) import Data.Ratio @@ -55,29 +58,30 @@ import Compat.Unicode ( GeneralCategory(..), generalCategory, isPrint, isUpper ) #endif } -$unispace = \x05 -$whitechar = [\ \t\n\r\f\v\xa0 $unispace] +$unispace = \x05 -- Trick Alex into handling Unicode. See alexGetChar. +$whitechar = [\ \n\r\f\v\xa0 $unispace] $white_no_nl = $whitechar # \n +$tab = \t $ascdigit = 0-9 -$unidigit = \x03 +$unidigit = \x03 -- Trick Alex into handling Unicode. See alexGetChar. $decdigit = $ascdigit -- for now, should really be $digit (ToDo) $digit = [$ascdigit $unidigit] $special = [\(\)\,\;\[\]\`\{\}] $ascsymbol = [\!\#\$\%\&\*\+\.\/\<\=\>\?\@\\\^\|\-\~ \xa1-\xbf \xd7 \xf7] -$unisymbol = \x04 +$unisymbol = \x04 -- Trick Alex into handling Unicode. See alexGetChar. $symbol = [$ascsymbol $unisymbol] # [$special \_\:\"\'] -$unilarge = \x01 +$unilarge = \x01 -- Trick Alex into handling Unicode. See alexGetChar. $asclarge = [A-Z \xc0-\xd6 \xd8-\xde] $large = [$asclarge $unilarge] -$unismall = \x02 +$unismall = \x02 -- Trick Alex into handling Unicode. See alexGetChar. $ascsmall = [a-z \xdf-\xf6 \xf8-\xff] $small = [$ascsmall $unismall \_] -$unigraphic = \x06 +$unigraphic = \x06 -- Trick Alex into handling Unicode. See alexGetChar. $graphic = [$small $large $symbol $digit $special $unigraphic \:\"\'] $octit = 0-7 @@ -104,10 +108,16 @@ $docsym = [\| \^ \* \$] @floating_point = @decimal \. @decimal @exponent? | @decimal @exponent +-- normal signed numerical literals can only be explicitly negative, +-- not explicitly positive (contrast @exponent) +@negative = \- +@signed = @negative ? + haskell :- -- everywhere: skip whitespace and comments $white_no_nl+ ; +$tab+ { warn Opt_WarnTabs (text "Tab character") } -- Everywhere: deal with nested comments. We explicitly rule out -- pragmas, "{-#", so that we don't accidentally treat them as comments. @@ -210,13 +220,14 @@ $white_no_nl+ ; -- NOTE: accept -} at the end of a LINE pragma, for compatibility -- with older versions of GHC which generated these. --- We only want RULES pragmas to be picked up when -fglasgow-exts --- is on, because the contents of the pragma is always written using --- glasgow-exts syntax (using forall etc.), so if glasgow exts are not --- enabled, we're sure to get a parse error. +-- We only want RULES pragmas to be picked up when explicit forall +-- syntax is enabled is on, because the contents of the pragma always +-- uses it. If it's not on then we're sure to get a parse error. -- (ToDo: we should really emit a warning when ignoring pragmas) - - "{-#" $whitechar* (RULES|rules) { token ITrules_prag } +-- XXX Now that we can enable this without the -fglasgow-exts hammer, +-- is it better just to let the parse error happen? +<0,glaexts> + "{-#" $whitechar* (RULES|rules) / { ifExtension explicitForallEnabled } { token ITrules_prag } <0,option_prags,glaexts> { "{-#" $whitechar* (INLINE|inline) { token (ITinline_prag True) } @@ -266,8 +277,8 @@ $white_no_nl+ ; -- Haddock comments <0,glaexts> { - "-- " / $docsym { multiline_doc_comment } - "{-" \ ? / $docsym { nested_doc_comment } + "-- " $docsym / { ifExtension haddockEnabled } { multiline_doc_comment } + "{-" \ ? $docsym / { ifExtension haddockEnabled } { nested_doc_comment } } -- "special" symbols @@ -298,9 +309,14 @@ $white_no_nl+ ; \? @varid / { ifExtension ipEnabled } { skip_one_varid ITdupipvarid } } +<0,glaexts> { + "(#" / { ifExtension unboxedTuplesEnabled `alexAndPred` notFollowedBySymbol } + { token IToubxparen } + "#)" / { ifExtension unboxedTuplesEnabled } + { token ITcubxparen } +} + { - "(#" / { notFollowedBySymbol } { token IToubxparen } - "#)" { token ITcubxparen } "{|" { token ITocurlybar } "|}" { token ITccurlybar } } @@ -332,11 +348,11 @@ $white_no_nl+ ; @qual @conid { pop_and (idtoken qconid) } } - { - @qual @varid "#"+ { idtoken qvarid } - @qual @conid "#"+ { idtoken qconid } - @varid "#"+ { varid } - @conid "#"+ { idtoken conid } +<0,glaexts> { + @qual @varid "#"+ / { ifExtension magicHashEnabled } { idtoken qvarid } + @qual @conid "#"+ / { ifExtension magicHashEnabled } { idtoken qconid } + @varid "#"+ / { ifExtension magicHashEnabled } { varid } + @conid "#"+ / { ifExtension magicHashEnabled } { idtoken conid } } -- ToDo: M.(,,,) @@ -348,22 +364,35 @@ $white_no_nl+ ; @consym { consym } } +-- For the normal boxed literals we need to be careful +-- when trying to be close to Haskell98 <0,glaexts> { - @decimal { tok_decimal } - 0[oO] @octal { tok_octal } - 0[xX] @hexadecimal { tok_hexadecimal } + -- Normal integral literals (:: Num a => a, from Integer) + @decimal { tok_num positive 0 0 decimal } + 0[oO] @octal { tok_num positive 2 2 octal } + 0[xX] @hexadecimal { tok_num positive 2 2 hexadecimal } + + -- Normal rational literals (:: Fractional a => a, from Rational) + @floating_point { strtoken tok_float } } { - @decimal \# { prim_decimal } - 0[oO] @octal \# { prim_octal } - 0[xX] @hexadecimal \# { prim_hexadecimal } + -- Unboxed ints (:: Int#) + -- It's simpler (and faster?) to give separate cases to the negatives, + -- especially considering octal/hexadecimal prefixes. + @decimal \# { tok_primint positive 0 1 decimal } + 0[oO] @octal \# { tok_primint positive 2 3 octal } + 0[xX] @hexadecimal \# { tok_primint positive 2 3 hexadecimal } + @negative @decimal \# { tok_primint negative 1 2 decimal } + @negative 0[oO] @octal \# { tok_primint negative 3 4 octal } + @negative 0[xX] @hexadecimal \# { tok_primint negative 3 4 hexadecimal } + + -- Unboxed floats and doubles (:: Float#, :: Double#) + -- prim_{float,double} work with signed literals + @signed @floating_point \# { init_strtoken 1 tok_primfloat } + @signed @floating_point \# \# { init_strtoken 2 tok_primdouble } } -<0,glaexts> @floating_point { strtoken tok_float } - @floating_point \# { init_strtoken 1 prim_float } - @floating_point \# \# { init_strtoken 2 prim_double } - -- Strings and chars are lexed by hand-written code. The reason is -- that even if we recognise the string or char here in the regex -- lexer, we would still have to parse the string afterward in order @@ -374,11 +403,6 @@ $white_no_nl+ ; } { --- work around bug in Alex 2.0 -#if __GLASGOW_HASKELL__ < 503 -unsafeAt arr i = arr ! i -#endif - -- ----------------------------------------------------------------------------- -- The token type @@ -389,7 +413,7 @@ data Token | ITdata | ITdefault | ITderiving - | ITderived + | ITderive | ITdo | ITelse | IThiding @@ -422,7 +446,6 @@ data Token | ITccallconv | ITdotnet | ITmdo - | ITiso | ITfamily -- Pragmas @@ -544,7 +567,7 @@ isSpecial :: Token -> Bool -- not as a keyword. isSpecial ITas = True isSpecial IThiding = True -isSpecial ITderived = True +isSpecial ITderive = True isSpecial ITqualified = True isSpecial ITforall = True isSpecial ITexport = True @@ -556,7 +579,6 @@ isSpecial ITunsafe = True isSpecial ITccallconv = True isSpecial ITstdcallconv = True isSpecial ITmdo = True -isSpecial ITiso = True isSpecial ITfamily = True isSpecial _ = False @@ -576,7 +598,7 @@ reservedWordsFM = listToUFM $ ( "data", ITdata, 0 ), ( "default", ITdefault, 0 ), ( "deriving", ITderiving, 0 ), - ( "derived", ITderived, 0 ), + ( "derive", ITderive, 0 ), ( "do", ITdo, 0 ), ( "else", ITelse, 0 ), ( "hiding", IThiding, 0 ), @@ -597,9 +619,9 @@ reservedWordsFM = listToUFM $ ( "where", ITwhere, 0 ), ( "_scc_", ITscc, 0 ), -- ToDo: remove - ( "forall", ITforall, bit tvBit), - ( "mdo", ITmdo, bit glaExtsBit), - ( "family", ITfamily, bit idxTysBit), + ( "forall", ITforall, bit explicitForallBit), + ( "mdo", ITmdo, bit recursiveDoBit), + ( "family", ITfamily, bit tyFamBit), ( "foreign", ITforeign, bit ffiBit), ( "export", ITexport, bit ffiBit), @@ -616,40 +638,44 @@ reservedWordsFM = listToUFM $ ( "proc", ITproc, bit arrowsBit) ] +reservedSymsFM :: UniqFM (Token, Int -> Bool) reservedSymsFM = listToUFM $ - map (\ (x,y,z) -> (mkFastString x,(y,z))) - [ ("..", ITdotdot, 0) - ,(":", ITcolon, 0) -- (:) is a reserved op, - -- meaning only list cons - ,("::", ITdcolon, 0) - ,("=", ITequal, 0) - ,("\\", ITlam, 0) - ,("|", ITvbar, 0) - ,("<-", ITlarrow, 0) - ,("->", ITrarrow, 0) - ,("@", ITat, 0) - ,("~", ITtilde, 0) - ,("=>", ITdarrow, 0) - ,("-", ITminus, 0) - ,("!", ITbang, 0) - - ,("*", ITstar, bit glaExtsBit .|. - bit idxTysBit) -- For data T (a::*) = MkT - ,(".", ITdot, bit tvBit) -- For 'forall a . t' - - ,("-<", ITlarrowtail, bit arrowsBit) - ,(">-", ITrarrowtail, bit arrowsBit) - ,("-<<", ITLarrowtail, bit arrowsBit) - ,(">>-", ITRarrowtail, bit arrowsBit) + map (\ (x,y,z) -> (mkFastString x,(y,z))) + [ ("..", ITdotdot, always) + -- (:) is a reserved op, meaning only list cons + ,(":", ITcolon, always) + ,("::", ITdcolon, always) + ,("=", ITequal, always) + ,("\\", ITlam, always) + ,("|", ITvbar, always) + ,("<-", ITlarrow, always) + ,("->", ITrarrow, always) + ,("@", ITat, always) + ,("~", ITtilde, always) + ,("=>", ITdarrow, always) + ,("-", ITminus, always) + ,("!", ITbang, always) + + -- For data T (a::*) = MkT + ,("*", ITstar, \i -> glaExtsEnabled i || + kindSigsEnabled i || + tyFamEnabled i) + -- For 'forall a . t' + ,(".", ITdot, explicitForallEnabled) + + ,("-<", ITlarrowtail, arrowsEnabled) + ,(">-", ITrarrowtail, arrowsEnabled) + ,("-<<", ITLarrowtail, arrowsEnabled) + ,(">>-", ITRarrowtail, arrowsEnabled) #if __GLASGOW_HASKELL__ >= 605 - ,("λ", ITlam, bit glaExtsBit) - ,("∷", ITdcolon, bit glaExtsBit) - ,("⇒", ITdarrow, bit glaExtsBit) - ,("∀", ITforall, bit glaExtsBit) - ,("→", ITrarrow, bit glaExtsBit) - ,("←", ITlarrow, bit glaExtsBit) - ,("⋯", ITdotdot, bit glaExtsBit) + ,("∷", ITdcolon, unicodeSyntaxEnabled) + ,("⇒", ITdarrow, unicodeSyntaxEnabled) + ,("∀", ITforall, \i -> unicodeSyntaxEnabled i && + explicitForallEnabled i) + ,("→", ITrarrow, unicodeSyntaxEnabled) + ,("←", ITlarrow, unicodeSyntaxEnabled) + ,("⋯", ITdotdot, unicodeSyntaxEnabled) -- ToDo: ideally, → and ∷ should be "specials", so that they cannot -- form part of a large operator. This would let us have a better -- syntax for kinds: ɑ∷*→* would be a legal kind signature. (maybe). @@ -702,12 +728,17 @@ notFollowedBy char _ _ _ (AI _ _ buf) notFollowedBySymbol _ _ _ (AI _ _ buf) = nextCharIs buf (`notElem` "!#$%&*+./<=>?@\\^|-~") +-- We must reject doc comments as being ordinary comments everywhere. +-- In some cases the doc comment will be selected as the lexeme due to +-- maximal munch, but not always, because the nested comment rule is +-- valid in all states, but the doc-comment rules are only valid in +-- the non-layout states. isNormalComment bits _ _ (AI _ _ buf) | haddockEnabled bits = notFollowedByDocOrPragma | otherwise = nextCharIs buf (/='#') - where - notFollowedByDocOrPragma - = not $ spaceAndP buf (`nextCharIs` (`elem` "|^*$#")) + where + notFollowedByDocOrPragma + = not $ spaceAndP buf (`nextCharIs` (`elem` "|^*$#")) spaceAndP buf p = p buf || nextCharIs buf (==' ') && p (snd (nextChar buf)) @@ -788,13 +819,12 @@ nested_doc_comment span buf _len = withLexedDocType (go "") Just (c,input) -> go (c:commentAcc) input docType False withLexedDocType lexDocComment = do - input <- getInput - case alexGetChar input of - Nothing -> error "Can't happen" - Just ('|', input) -> lexDocComment input ITdocCommentNext False - Just ('^', input) -> lexDocComment input ITdocCommentPrev False - Just ('$', input) -> lexDocComment input ITdocCommentNamed False - Just ('*', input) -> lexDocSection 1 input + input@(AI _ _ buf) <- getInput + case prevChar buf ' ' of + '|' -> lexDocComment input ITdocCommentNext False + '^' -> lexDocComment input ITdocCommentPrev False + '$' -> lexDocComment input ITdocCommentNamed False + '*' -> lexDocSection 1 input where lexDocSection n input = case alexGetChar input of Just ('*', input) -> lexDocSection (n+1) input @@ -924,36 +954,37 @@ consym = sym ITconsym sym con span buf len = case lookupUFM reservedSymsFM fs of - Just (keyword,0) -> return (L span keyword) Just (keyword,exts) -> do - b <- extension (\i -> exts .&. i /= 0) + b <- extension exts if b then return (L span keyword) else return (L span $! con fs) _other -> return (L span $! con fs) where fs = lexemeToFastString buf len -tok_decimal span buf len - = return (L span (ITinteger $! parseInteger buf len 10 octDecDigit)) - -tok_octal span buf len - = return (L span (ITinteger $! parseInteger (offsetBytes 2 buf) (len-2) 8 octDecDigit)) - -tok_hexadecimal span buf len - = return (L span (ITinteger $! parseInteger (offsetBytes 2 buf) (len-2) 16 hexDigit)) - -prim_decimal span buf len - = return (L span (ITprimint $! parseInteger buf (len-1) 10 octDecDigit)) - -prim_octal span buf len - = return (L span (ITprimint $! parseInteger (offsetBytes 2 buf) (len-3) 8 octDecDigit)) - -prim_hexadecimal span buf len - = return (L span (ITprimint $! parseInteger (offsetBytes 2 buf) (len-3) 16 hexDigit)) - +-- Variations on the integral numeric literal. +tok_integral :: (Integer -> Token) + -> (Integer -> Integer) + -- -> (StringBuffer -> StringBuffer) -> (Int -> Int) + -> Int -> Int + -> (Integer, (Char->Int)) -> Action +tok_integral itint transint transbuf translen (radix,char_to_int) span buf len = + return $ L span $ itint $! transint $ parseUnsignedInteger + (offsetBytes transbuf buf) (subtract translen len) radix char_to_int + +-- some conveniences for use with tok_integral +tok_num = tok_integral ITinteger +tok_primint = tok_integral ITprimint +positive = id +negative = negate +decimal = (10,octDecDigit) +octal = (8,octDecDigit) +hexadecimal = (16,hexDigit) + +-- readRational can understand negative rationals, exponents, everything. tok_float str = ITrational $! readRational str -prim_float str = ITprimfloat $! readRational str -prim_double str = ITprimdouble $! readRational str +tok_primfloat str = ITprimfloat $! readRational str +tok_primdouble str = ITprimdouble $! readRational str -- ----------------------------------------------------------------------------- -- Layout processing @@ -1021,7 +1052,7 @@ do_layout_left span _buf _len = do setLine :: Int -> Action setLine code span buf len = do - let line = parseInteger buf len 10 octDecDigit + let line = parseUnsignedInteger buf len 10 octDecDigit setSrcLoc (mkSrcLoc (srcSpanFile span) (fromIntegral line - 1) 0) -- subtract one: the line number refers to the *following* line popLexState @@ -1301,6 +1332,14 @@ getCharOrFail = do Just (c,i) -> do setInput i; return c -- ----------------------------------------------------------------------------- +-- Warnings + +warn :: DynFlag -> SDoc -> Action +warn option warning span _buf _len = do + addWarning option (mkWarnMsg span alwaysQualify warning) + lexToken + +-- ----------------------------------------------------------------------------- -- The Parse Monad data LayoutContext @@ -1318,6 +1357,8 @@ data ParseResult a data PState = PState { buffer :: StringBuffer, + dflags :: DynFlags, + messages :: Messages, last_loc :: SrcSpan, -- pos of previous token last_offs :: !Int, -- offset of the previous token from the -- beginning of the current line. @@ -1408,6 +1449,9 @@ alexGetChar (AI loc ofs s) adj_c | c <= '\x06' = non_graphic | c <= '\xff' = c + -- Alex doesn't handle Unicode, so when Unicode + -- character is encoutered we output these values + -- with the actual character value hidden in the state. | otherwise = case generalCategory c of UppercaseLetter -> upper @@ -1478,23 +1522,34 @@ parrBit = 2 arrowsBit = 4 thBit = 5 ipBit = 6 -tvBit = 7 -- Scoped type variables enables 'forall' keyword +explicitForallBit = 7 -- the 'forall' keyword and '.' symbol bangPatBit = 8 -- Tells the parser to understand bang-patterns -- (doesn't affect the lexer) -idxTysBit = 9 -- indexed type families: 'family' keyword and kind sigs +tyFamBit = 9 -- indexed type families: 'family' keyword and kind sigs haddockBit = 10 -- Lex and parse Haddock comments +magicHashBit = 11 -- # in both functions and operators +kindSigsBit = 12 -- Kind signatures on type variables +recursiveDoBit = 13 -- mdo +unicodeSyntaxBit = 14 -- the forall symbol, arrow symbols, etc +unboxedTuplesBit = 15 -- (# and #) glaExtsEnabled, ffiEnabled, parrEnabled :: Int -> Bool -glaExtsEnabled flags = testBit flags glaExtsBit -ffiEnabled flags = testBit flags ffiBit -parrEnabled flags = testBit flags parrBit -arrowsEnabled flags = testBit flags arrowsBit -thEnabled flags = testBit flags thBit -ipEnabled flags = testBit flags ipBit -tvEnabled flags = testBit flags tvBit -bangPatEnabled flags = testBit flags bangPatBit -idxTysEnabled flags = testBit flags idxTysBit -haddockEnabled flags = testBit flags haddockBit +always _ = True +glaExtsEnabled flags = testBit flags glaExtsBit +ffiEnabled flags = testBit flags ffiBit +parrEnabled flags = testBit flags parrBit +arrowsEnabled flags = testBit flags arrowsBit +thEnabled flags = testBit flags thBit +ipEnabled flags = testBit flags ipBit +explicitForallEnabled flags = testBit flags explicitForallBit +bangPatEnabled flags = testBit flags bangPatBit +tyFamEnabled flags = testBit flags tyFamBit +haddockEnabled flags = testBit flags haddockBit +magicHashEnabled flags = testBit flags magicHashBit +kindSigsEnabled flags = testBit flags kindSigsBit +recursiveDoEnabled flags = testBit flags recursiveDoBit +unicodeSyntaxEnabled flags = testBit flags unicodeSyntaxBit +unboxedTuplesEnabled flags = testBit flags unboxedTuplesBit -- PState for parsing options pragmas -- @@ -1502,6 +1557,10 @@ pragState :: StringBuffer -> SrcLoc -> PState pragState buf loc = PState { buffer = buf, + messages = emptyMessages, + -- XXX defaultDynFlags is not right, but we don't have a real + -- dflags handy + dflags = defaultDynFlags, last_loc = mkSrcSpan loc loc, last_offs = 0, last_len = 0, @@ -1519,6 +1578,8 @@ mkPState :: StringBuffer -> SrcLoc -> DynFlags -> PState mkPState buf loc flags = PState { buffer = buf, + dflags = flags, + messages = emptyMessages, last_loc = mkSrcSpan loc loc, last_offs = 0, last_len = 0, @@ -1530,21 +1591,39 @@ mkPState buf loc flags = -- we begin in the layout state if toplev_layout is set } where - bitmap = glaExtsBit `setBitIf` dopt Opt_GlasgowExts flags - .|. ffiBit `setBitIf` dopt Opt_FFI flags - .|. parrBit `setBitIf` dopt Opt_PArr flags - .|. arrowsBit `setBitIf` dopt Opt_Arrows flags - .|. thBit `setBitIf` dopt Opt_TH flags - .|. ipBit `setBitIf` dopt Opt_ImplicitParams flags - .|. tvBit `setBitIf` dopt Opt_ScopedTypeVariables flags - .|. bangPatBit `setBitIf` dopt Opt_BangPatterns flags - .|. idxTysBit `setBitIf` dopt Opt_IndexedTypes flags - .|. haddockBit `setBitIf` dopt Opt_Haddock flags + bitmap = glaExtsBit `setBitIf` dopt Opt_GlasgowExts flags + .|. ffiBit `setBitIf` dopt Opt_FFI flags + .|. parrBit `setBitIf` dopt Opt_PArr flags + .|. arrowsBit `setBitIf` dopt Opt_Arrows flags + .|. thBit `setBitIf` dopt Opt_TH flags + .|. ipBit `setBitIf` dopt Opt_ImplicitParams flags + .|. explicitForallBit `setBitIf` dopt Opt_ScopedTypeVariables flags + .|. explicitForallBit `setBitIf` dopt Opt_PolymorphicComponents flags + .|. explicitForallBit `setBitIf` dopt Opt_ExistentialQuantification flags + .|. explicitForallBit `setBitIf` dopt Opt_Rank2Types flags + .|. explicitForallBit `setBitIf` dopt Opt_RankNTypes flags + .|. bangPatBit `setBitIf` dopt Opt_BangPatterns flags + .|. tyFamBit `setBitIf` dopt Opt_TypeFamilies flags + .|. haddockBit `setBitIf` dopt Opt_Haddock flags + .|. magicHashBit `setBitIf` dopt Opt_MagicHash flags + .|. kindSigsBit `setBitIf` dopt Opt_KindSignatures flags + .|. recursiveDoBit `setBitIf` dopt Opt_RecursiveDo flags + .|. unicodeSyntaxBit `setBitIf` dopt Opt_UnicodeSyntax flags + .|. unboxedTuplesBit `setBitIf` dopt Opt_UnboxedTuples flags -- setBitIf :: Int -> Bool -> Int b `setBitIf` cond | cond = bit b | otherwise = 0 +addWarning :: DynFlag -> WarnMsg -> P () +addWarning option w + = P $ \s@PState{messages=(ws,es), dflags=d} -> + let ws' = if dopt option d then ws `snocBag` w else ws + in POk s{messages=(ws', es)} () + +getMessages :: PState -> Messages +getMessages PState{messages=ms} = ms + getContext :: P [LayoutContext] getContext = P $ \s@PState{context=ctx} -> POk s ctx