Alan Zimmerman pushed to branch wip/az/ghc-cpp at Glasgow Haskell Compiler / GHC
Commits:
-
14999739
by Alan Zimmerman at 2025-06-21T17:03:55+01:00
-
e4491409
by Alan Zimmerman at 2025-06-22T15:14:55+01:00
2 changed files:
Changes:
| ... | ... | @@ -37,104 +37,86 @@ import Data.Map qualified as Map |
| 37 | 37 | import Data.Maybe
|
| 38 | 38 | |
| 39 | 39 | import Data.Semigroup qualified as S
|
| 40 | -import GHC.Driver.Errors.Types (PsMessage)
|
|
| 41 | -import GHC.Parser.Lexer qualified as Lexer
|
|
| 42 | 40 | import GHC.Parser.PreProcess.Eval
|
| 43 | 41 | import GHC.Parser.PreProcess.ParsePP
|
| 44 | 42 | import GHC.Parser.PreProcess.Parser qualified as Parser
|
| 45 | 43 | import GHC.Parser.PreProcess.ParserM
|
| 46 | 44 | import GHC.Parser.PreProcess.State
|
| 47 | 45 | import GHC.Prelude
|
| 48 | -import GHC.Types.Error (MsgEnvelope)
|
|
| 49 | 46 | import GHC.Types.SrcLoc
|
| 50 | 47 | import GHC.Utils.Outputable
|
| 51 | 48 | import GHC.Utils.Panic (panic)
|
| 52 | 49 | |
| 53 | 50 | -- ---------------------------------------------------------------------
|
| 54 | 51 | |
| 55 | --- We evaluate to an Int, which we convert to a bool
|
|
| 52 | +-- We evaluate to an Int, which we convert to a bool
|
|
| 56 | 53 | cppCond :: SrcSpan -> String -> PP Bool
|
| 57 | 54 | cppCond loc str = do
|
| 58 | - s <- getPpState
|
|
| 55 | + r <- runPM $ cppCond' loc str
|
|
| 56 | + return $ fromMaybe False r
|
|
| 57 | + |
|
| 58 | +cppCond' :: SrcSpan -> String -> PPM Bool
|
|
| 59 | +cppCond' loc str = do
|
|
| 60 | + s <- liftPM getPpState
|
|
| 59 | 61 | expanded <- expand loc (pp_defines s) str
|
| 60 | - case expanded of
|
|
| 62 | + v <- case Parser.parseExpr expanded of
|
|
| 61 | 63 | Left err -> do
|
| 62 | - Lexer.addError err
|
|
| 63 | - return False
|
|
| 64 | - Right expanded -> do
|
|
| 65 | - v <- case Parser.parseExpr expanded of
|
|
| 66 | - Left err -> do
|
|
| 67 | - let detail =
|
|
| 68 | - if str == expanded || expanded == ""
|
|
| 69 | - then
|
|
| 70 | - [ text str
|
|
| 71 | - ]
|
|
| 72 | - else
|
|
| 73 | - [ text expanded
|
|
| 74 | - , text "expanded from:"
|
|
| 75 | - , text str
|
|
| 76 | - ]
|
|
| 77 | - addGhcCPPError
|
|
| 78 | - loc
|
|
| 79 | - ( hang
|
|
| 80 | - (text "Error evaluating CPP condition:")
|
|
| 81 | - 2
|
|
| 82 | - ( text err
|
|
| 83 | - <+> text "of"
|
|
| 84 | - $+$ vcat detail
|
|
| 85 | - )
|
|
| 86 | - )
|
|
| 87 | - return 0
|
|
| 88 | - Right tree -> return (eval tree)
|
|
| 89 | - return (toBool v)
|
|
| 64 | + let detail =
|
|
| 65 | + if str == expanded || expanded == ""
|
|
| 66 | + then
|
|
| 67 | + [text str]
|
|
| 68 | + else
|
|
| 69 | + [ text expanded
|
|
| 70 | + , text "expanded from:"
|
|
| 71 | + , text str
|
|
| 72 | + ]
|
|
| 73 | + liftPM $
|
|
| 74 | + addGhcCPPError'
|
|
| 75 | + loc
|
|
| 76 | + "Error evaluating CPP condition:"
|
|
| 77 | + ( text err
|
|
| 78 | + <+> text "of"
|
|
| 79 | + $+$ vcat detail
|
|
| 80 | + )
|
|
| 81 | + return 0
|
|
| 82 | + Right tree -> return (eval tree)
|
|
| 83 | + return (toBool v)
|
|
| 90 | 84 | |
| 91 | 85 | -- ---------------------------------------------------------------------
|
| 92 | 86 | |
| 93 | -expand :: SrcSpan -> MacroDefines -> String -> PP (Either (MsgEnvelope PsMessage) String)
|
|
| 87 | +expand :: SrcSpan -> MacroDefines -> String -> PPM String
|
|
| 94 | 88 | expand loc s str = do
|
| 95 | 89 | case cppLex False str of
|
| 96 | 90 | Left err -> do
|
| 97 | - return
|
|
| 98 | - ( Left $
|
|
| 99 | - mkGhcCPPError
|
|
| 100 | - loc
|
|
| 101 | - ( hang
|
|
| 102 | - (text "Error evaluating CPP condition:")
|
|
| 103 | - 2
|
|
| 104 | - (text err <+> text "of" $+$ text str)
|
|
| 105 | - )
|
|
| 106 | - )
|
|
| 91 | + liftPM $
|
|
| 92 | + addGhcCPPError'
|
|
| 93 | + loc
|
|
| 94 | + "Error evaluating CPP condition:"
|
|
| 95 | + (text err <+> text "of" $+$ text str)
|
|
| 96 | + failPM
|
|
| 107 | 97 | Right tks -> do
|
| 108 | - expandedToks <- expandToks loc maxExpansions s tks
|
|
| 109 | - case expandedToks of
|
|
| 110 | - Left err -> return (Left err)
|
|
| 111 | - Right toks -> return $ Right $ combineToks $ map t_str toks
|
|
| 98 | + toks <- expandToks loc maxExpansions s tks
|
|
| 99 | + return $ combineToks $ map t_str toks
|
|
| 112 | 100 | |
| 113 | 101 | maxExpansions :: Int
|
| 114 | 102 | maxExpansions = 15
|
| 115 | 103 | |
| 116 | -expandToks :: SrcSpan -> Int -> MacroDefines -> [Token] -> PP (Either (MsgEnvelope PsMessage) [Token])
|
|
| 104 | +expandToks :: SrcSpan -> Int -> MacroDefines -> [Token] -> PPM [Token]
|
|
| 117 | 105 | expandToks loc 0 _ ts = do
|
| 118 | - return $
|
|
| 119 | - Left $
|
|
| 120 | - mkGhcCPPError
|
|
| 121 | - loc
|
|
| 122 | - ( hang
|
|
| 123 | - (text "CPP macro expansion limit hit:")
|
|
| 124 | - 2
|
|
| 125 | - (text (combineToks $ map t_str ts))
|
|
| 126 | - )
|
|
| 106 | + liftPM $
|
|
| 107 | + addGhcCPPError'
|
|
| 108 | + loc
|
|
| 109 | + "CPP macro expansion limit hit:"
|
|
| 110 | + (text (combineToks $ map t_str ts))
|
|
| 111 | + failPM
|
|
| 127 | 112 | expandToks loc cnt s ts = do
|
| 128 | - expansion <- doExpandToks loc False s ts
|
|
| 129 | - case expansion of
|
|
| 130 | - Left err -> return (Left err)
|
|
| 131 | - Right (!expansionDone, !r) ->
|
|
| 132 | - if expansionDone
|
|
| 133 | - then expandToks loc (cnt - 1) s r
|
|
| 134 | - else return (Right r)
|
|
| 135 | - |
|
| 136 | -doExpandToks :: SrcSpan -> Bool -> MacroDefines -> [Token] -> PP (Either (MsgEnvelope PsMessage) (Bool, [Token]))
|
|
| 137 | -doExpandToks _loc ed _ [] = return $ Right (ed, [])
|
|
| 113 | + (!expansionDone, !r) <- doExpandToks loc False s ts
|
|
| 114 | + if expansionDone
|
|
| 115 | + then expandToks loc (cnt - 1) s r
|
|
| 116 | + else return r
|
|
| 117 | + |
|
| 118 | +doExpandToks :: SrcSpan -> Bool -> MacroDefines -> [Token] -> PPM (Bool, [Token])
|
|
| 119 | +doExpandToks _loc ed _ [] = return (ed, [])
|
|
| 138 | 120 | doExpandToks loc ed s (TIdentifierLParen n : ts) =
|
| 139 | 121 | -- TIdentifierLParen has no meaning here (only in a #define), so
|
| 140 | 122 | -- restore it to its constituent tokens
|
| ... | ... | @@ -145,32 +127,26 @@ doExpandToks loc _ s (TIdentifier "defined" : ts) = do |
| 145 | 127 | case expandedArgs of
|
| 146 | 128 | (Just [[TIdentifier macro_name]], rest0) ->
|
| 147 | 129 | case Map.lookup macro_name s of
|
| 148 | - Nothing -> return $ Right (True, TInteger "0" : rest0)
|
|
| 149 | - Just _ -> return $ Right (True, TInteger "1" : rest0)
|
|
| 130 | + Nothing -> return (True, TInteger "0" : rest0)
|
|
| 131 | + Just _ -> return (True, TInteger "1" : rest0)
|
|
| 150 | 132 | (Nothing, TIdentifier macro_name : ts0) ->
|
| 151 | 133 | case Map.lookup macro_name s of
|
| 152 | - Nothing -> return $ Right (True, TInteger "0" : ts0)
|
|
| 153 | - Just _ -> return $ Right (True, TInteger "1" : ts0)
|
|
| 134 | + Nothing -> return (True, TInteger "0" : ts0)
|
|
| 135 | + Just _ -> return (True, TInteger "1" : ts0)
|
|
| 154 | 136 | (Nothing, _) -> do
|
| 155 | - return $
|
|
| 156 | - Left $
|
|
| 157 | - mkGhcCPPError
|
|
| 158 | - loc
|
|
| 159 | - ( hang
|
|
| 160 | - (text "CPP defined: expected an identifier, got:")
|
|
| 161 | - 2
|
|
| 162 | - (text (concatMap t_str ts))
|
|
| 163 | - )
|
|
| 137 | + liftPM $
|
|
| 138 | + addGhcCPPError'
|
|
| 139 | + loc
|
|
| 140 | + "CPP defined: expected an identifier, got:"
|
|
| 141 | + (text (concatMap t_str ts))
|
|
| 142 | + failPM -- TODO:AZ make part of addGhcCPPError'?
|
|
| 164 | 143 | (Just args, _) -> do
|
| 165 | - return $
|
|
| 166 | - Left $
|
|
| 167 | - mkGhcCPPError
|
|
| 168 | - loc
|
|
| 169 | - ( hang
|
|
| 170 | - (text "CPP defined: expected a single arg, got:")
|
|
| 171 | - 2
|
|
| 172 | - (text (intercalate "," (map (concatMap t_str) args)))
|
|
| 173 | - )
|
|
| 144 | + liftPM $
|
|
| 145 | + addGhcCPPError'
|
|
| 146 | + loc
|
|
| 147 | + "CPP defined: expected a single arg, got:"
|
|
| 148 | + (text (intercalate "," (map (concatMap t_str) args)))
|
|
| 149 | + failPM -- TODO:AZ make part of addGhcCPPError'?
|
|
| 174 | 150 | doExpandToks loc ed s (TIdentifier n : ts) = do
|
| 175 | 151 | (args, rest0) <- getExpandArgs loc ts
|
| 176 | 152 | let
|
| ... | ... | @@ -183,15 +159,11 @@ doExpandToks loc ed s (TIdentifier n : ts) = do |
| 183 | 159 | (ed0, r, rest1) = case m_args of
|
| 184 | 160 | Nothing -> (True, rhs, ts)
|
| 185 | 161 | Just _ -> (True, replace_args args m_args rhs, rest0)
|
| 186 | - expansion <- doExpandToks loc ed' s ts'
|
|
| 187 | - case expansion of
|
|
| 188 | - Left err -> return $ Left err
|
|
| 189 | - Right (ed'', rest) -> return $ Right (ed'', expanded ++ rest)
|
|
| 162 | + (ed'', rest) <- doExpandToks loc ed' s ts'
|
|
| 163 | + return (ed'', expanded ++ rest)
|
|
| 190 | 164 | doExpandToks loc ed s (t : ts) = do
|
| 191 | - expansion <- doExpandToks loc ed s ts
|
|
| 192 | - case expansion of
|
|
| 193 | - Left err -> return (Left err)
|
|
| 194 | - Right (ed', r) -> return $ Right (ed', t : r)
|
|
| 165 | + (ed', r) <- doExpandToks loc ed s ts
|
|
| 166 | + return (ed', t : r)
|
|
| 195 | 167 | |
| 196 | 168 | {-
|
| 197 | 169 | Note: ['defined' unary operator]
|
| ... | ... | @@ -263,17 +235,15 @@ inner parentheses do not separate arguments. |
| 263 | 235 | {- | Look for possible arguments to a macro expansion.
|
| 264 | 236 | The only thing we look for are commas, open parens, and close parens.
|
| 265 | 237 | -}
|
| 266 | -getExpandArgs :: SrcSpan -> [Token] -> PP (Maybe [[Token]], [Token])
|
|
| 238 | +getExpandArgs :: SrcSpan -> [Token] -> PPM (Maybe [[Token]], [Token])
|
|
| 267 | 239 | getExpandArgs loc ts =
|
| 268 | 240 | case pArgs ts of
|
| 269 | 241 | Left err -> do
|
| 270 | - addGhcCPPError
|
|
| 271 | - loc
|
|
| 272 | - ( hang
|
|
| 273 | - (text "CPP: cannot expand macro arguments:")
|
|
| 274 | - 2
|
|
| 242 | + liftPM $
|
|
| 243 | + addGhcCPPError'
|
|
| 244 | + loc
|
|
| 245 | + "CPP: cannot expand macro arguments:"
|
|
| 275 | 246 | (text err <+> text "in" $+$ text (concatMap t_str ts))
|
| 276 | - )
|
|
| 277 | 247 | return (Nothing, ts)
|
| 278 | 248 | Right r -> return r
|
| 279 | 249 |
| ... | ... | @@ -8,6 +8,7 @@ module GHC.Parser.PreProcess.State ( |
| 8 | 8 | PpState (..),
|
| 9 | 9 | initPpState,
|
| 10 | 10 | PP,
|
| 11 | + PPM,
|
|
| 11 | 12 | PpScope (..),
|
| 12 | 13 | PpGroupState (..),
|
| 13 | 14 | MacroDefines,
|
| ... | ... | @@ -32,8 +33,11 @@ module GHC.Parser.PreProcess.State ( |
| 32 | 33 | ghcCppEnabled,
|
| 33 | 34 | setInLinePragma,
|
| 34 | 35 | getInLinePragma,
|
| 35 | - mkGhcCPPError,
|
|
| 36 | - addGhcCPPError,
|
|
| 36 | + PM (..),
|
|
| 37 | + runPM,
|
|
| 38 | + liftPM,
|
|
| 39 | + failPM,
|
|
| 40 | + addGhcCPPError',
|
|
| 37 | 41 | ) where
|
| 38 | 42 | |
| 39 | 43 | import Data.List.NonEmpty ((<|))
|
| ... | ... | @@ -51,12 +55,51 @@ import GHC.Types.SrcLoc |
| 51 | 55 | import GHC.Utils.Error
|
| 52 | 56 | |
| 53 | 57 | import GHC.Prelude
|
| 54 | -import GHC.Utils.Outputable (text, (<+>))
|
|
| 58 | +import GHC.Utils.Outputable (hang, text, (<+>))
|
|
| 55 | 59 | |
| 56 | 60 | -- ---------------------------------------------------------------------
|
| 57 | 61 | |
| 62 | +type PPM = PM PpState
|
|
| 58 | 63 | type PP = P PpState
|
| 59 | 64 | |
| 65 | +-- ---------------------------------------------------------------------
|
|
| 66 | + |
|
| 67 | +-- | The parsing monad, isomorphic to @StateT PState Maybe@.
|
|
| 68 | +newtype PM p a = PM {unPM :: PState p -> ParseResult p (Maybe a)}
|
|
| 69 | + |
|
| 70 | +instance Functor (PM p) where
|
|
| 71 | + fmap = liftM
|
|
| 72 | + |
|
| 73 | +instance Applicative (PM p) where
|
|
| 74 | + pure = returnP
|
|
| 75 | + (<*>) = ap
|
|
| 76 | + |
|
| 77 | +instance Monad (PM p) where
|
|
| 78 | + (>>=) = thenP
|
|
| 79 | + |
|
| 80 | +returnP :: a -> PM p a
|
|
| 81 | +returnP a = a `seq` (PM $ \s -> POk s (Just a))
|
|
| 82 | + |
|
| 83 | +failPM :: PM p a
|
|
| 84 | +failPM = PM $ \s -> POk s Nothing
|
|
| 85 | + |
|
| 86 | +thenP :: PM p a -> (a -> PM p b) -> PM p b
|
|
| 87 | +(PM m) `thenP` k = PM $ \s ->
|
|
| 88 | + case m s of
|
|
| 89 | + POk s1 Nothing -> POk s1 Nothing
|
|
| 90 | + POk s1 (Just a) -> (unPM (k a)) s1
|
|
| 91 | + PFailed s1 -> PFailed s1
|
|
| 92 | + |
|
| 93 | +runPM :: PM p a -> P p (Maybe a)
|
|
| 94 | +runPM m = P $ \s -> (unPM m) s
|
|
| 95 | + |
|
| 96 | +liftPM :: P p a -> PM p a
|
|
| 97 | +liftPM m = PM $ \s -> case (unP m) s of
|
|
| 98 | + POk s1 a -> POk s1 (Just a)
|
|
| 99 | + PFailed s1 -> PFailed s1
|
|
| 100 | + |
|
| 101 | +-- ---------------------------------------------------------------------
|
|
| 102 | + |
|
| 60 | 103 | data CppState
|
| 61 | 104 | = CppIgnoring
|
| 62 | 105 | | CppNormal
|
| ... | ... | @@ -238,15 +281,15 @@ acceptingStateChange old new = |
| 238 | 281 | -- Exit a scope group
|
| 239 | 282 | popAccepting :: SrcSpan -> PP AcceptingResult
|
| 240 | 283 | popAccepting loc = do
|
| 241 | - scopes <- getScopes
|
|
| 242 | - new_scope <- case scopes of
|
|
| 243 | - c :| [] -> do
|
|
| 244 | - addGhcCPPError loc (text "#endif without #if")
|
|
| 245 | - return (c :| [])
|
|
| 246 | - _ :| (h : t) -> return (h :| t)
|
|
| 247 | - setScopes new_scope
|
|
| 248 | - let current = scopeValue scopes
|
|
| 249 | - return (acceptingStateChange current (scopeValue new_scope))
|
|
| 284 | + scopes <- getScopes
|
|
| 285 | + new_scope <- case scopes of
|
|
| 286 | + c :| [] -> do
|
|
| 287 | + addGhcCPPError loc (text "#endif without #if")
|
|
| 288 | + return (c :| [])
|
|
| 289 | + _ :| (h : t) -> return (h :| t)
|
|
| 290 | + setScopes new_scope
|
|
| 291 | + let current = scopeValue scopes
|
|
| 292 | + return (acceptingStateChange current (scopeValue new_scope))
|
|
| 250 | 293 | |
| 251 | 294 | scopeValue :: NonEmpty PpScope -> Bool
|
| 252 | 295 | scopeValue s = pp_accepting $ NonEmpty.head s
|
| ... | ... | @@ -266,7 +309,7 @@ parentScope = |
| 266 | 309 | c :| [] -> c -- Perhaps should return enabled instead
|
| 267 | 310 | _ :| (h : _t) -> h
|
| 268 | 311 | in
|
| 269 | - POk s new_scope
|
|
| 312 | + POk s (new_scope)
|
|
| 270 | 313 | |
| 271 | 314 | -- Get the current scope value
|
| 272 | 315 | getScope :: PP PpScope
|
| ... | ... | @@ -415,8 +458,21 @@ insertMacroDef (MacroName name args) def md = |
| 415 | 458 | |
| 416 | 459 | -- ---------------------------------------------------------------------
|
| 417 | 460 | |
| 461 | +mkGhcCPPError' :: SrcSpan -> String -> SDoc -> MsgEnvelope PsMessage
|
|
| 462 | +mkGhcCPPError' loc title detail =
|
|
| 463 | + mkGhcCPPError
|
|
| 464 | + loc
|
|
| 465 | + ( hang
|
|
| 466 | + (text title)
|
|
| 467 | + 2
|
|
| 468 | + detail
|
|
| 469 | + )
|
|
| 470 | + |
|
| 471 | +addGhcCPPError' :: SrcSpan -> String -> SDoc -> PP ()
|
|
| 472 | +addGhcCPPError' loc title detail = Lexer.addError $ mkGhcCPPError' loc title detail
|
|
| 473 | + |
|
| 418 | 474 | mkGhcCPPError :: SrcSpan -> SDoc -> MsgEnvelope PsMessage
|
| 419 | 475 | mkGhcCPPError loc err = mkPlainErrorMsgEnvelope loc $ PsErrGhcCpp err
|
| 420 | 476 | |
| 421 | -addGhcCPPError :: SrcSpan -> SDoc -> P p ()
|
|
| 477 | +addGhcCPPError :: SrcSpan -> SDoc -> PP ()
|
|
| 422 | 478 | addGhcCPPError loc err = Lexer.addError $ mkGhcCPPError loc err |