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 |