@@ -17,7 +17,7 @@ import Axel.AST
17
17
, statements
18
18
)
19
19
import Axel.Denormalize (denormalizeExpression , denormalizeStatement )
20
- import Axel.Error (Error (MacroError ), fatal )
20
+ import Axel.Error (Error (MacroError ))
21
21
import Axel.Eval (evalMacro )
22
22
import Axel.Normalize (normalizeStatement )
23
23
import qualified Axel.Parse as Parse
@@ -35,16 +35,17 @@ import Axel.Utils.Resources (readDataFile)
35
35
import Axel.Utils.String (replace )
36
36
37
37
import Control.Lens.Operators ((%~) , (^.) )
38
- import Control.Lens.Tuple (_1 , _2 )
39
38
import Control.Monad (foldM )
40
39
import Control.Monad.Except (MonadError , catchError , throwError )
41
40
import Control.Monad.IO.Class (MonadIO , liftIO )
42
41
import Control.Monad.Trans.Control (MonadBaseControl )
43
42
44
- import Data.Function ( (&) )
45
- import Data.List ( foldl' )
43
+ import Data.List ( foldl' , partition )
44
+ import Data.Maybe ( listToMaybe )
46
45
import Data.Semigroup ((<>) )
47
46
47
+ import Debug.Trace (trace )
48
+
48
49
getAstDefinition :: IO String
49
50
getAstDefinition = readDataFile " autogenerated/macros/AST.hs"
50
51
@@ -120,15 +121,17 @@ expansionPass programExpr = do
120
121
extractIndependentStatements $ programToStmts programExpr
121
122
normalizedStmts <- traverse normalizeStatement independentStmts
122
123
let nonconflictingStmts = filter canInclude normalizedStmts
123
- let (macroDefs, auxEnv) =
124
- foldl
125
- (\ acc x ->
126
- case x of
127
- SMacroDefinition macroDef -> acc & _1 %~ (macroDef : )
128
- _ -> acc & _2 %~ (<> [x]))
129
- ([] , [] )
130
- nonconflictingStmts
131
- expandMacros macroDefs auxEnv programExpr
124
+ let maybeFirstMacroDef =
125
+ listToMaybe $ filter isMacroDefinitionStatement nonconflictingStmts
126
+ case maybeFirstMacroDef of
127
+ Just (SMacroDefinition firstMacroDef) ->
128
+ let otherStmts =
129
+ filter (/= SMacroDefinition firstMacroDef) nonconflictingStmts
130
+ in expandMacro
131
+ (trace (toHaskell $ SMacroDefinition firstMacroDef) firstMacroDef)
132
+ otherStmts
133
+ programExpr
134
+ _ -> pure programExpr
132
135
where
133
136
canInclude :: Statement -> Bool
134
137
canInclude =
@@ -156,13 +159,13 @@ exhaustivelyExpandMacros ::
156
159
exhaustivelyExpandMacros = exhaustM expansionPass
157
160
158
161
-- TODO This needs heavy optimization.
159
- expandMacros ::
162
+ expandMacro ::
160
163
(MonadBaseControl IO m , MonadError Error m , MonadIO m )
161
- => [ MacroDefinition ]
164
+ => MacroDefinition
162
165
-> [Statement ]
163
166
-> Parse. Expression
164
167
-> m Parse. Expression
165
- expandMacros macroDefs auxEnv =
168
+ expandMacro macroDef auxEnv =
166
169
bottomUpTraverse $ \ expr ->
167
170
case expr of
168
171
Parse. LiteralChar _ -> pure expr
@@ -178,11 +181,9 @@ expandMacros macroDefs auxEnv =
178
181
Parse. LiteralString _ -> pure $ acc ++ [x]
179
182
Parse. SExpression [] -> pure $ acc ++ [x]
180
183
Parse. SExpression (function: args) ->
181
- lookupMacroDefinition macroDefs function >>= \ case
182
- Just macroDefinition ->
183
- (acc ++ ) <$>
184
- expandMacroApplication macroDefinition auxEnv args
185
- Nothing -> pure $ acc ++ [x]
184
+ if isMacroBeingCalled macroDef function
185
+ then (acc ++ ) <$> expandMacroApplication macroDef auxEnv args
186
+ else pure $ acc ++ [x]
186
187
Parse. Symbol _ -> pure $ acc ++ [x])
187
188
[]
188
189
xs
@@ -195,41 +196,31 @@ expandMacroApplication ::
195
196
-> [Parse. Expression ]
196
197
-> m [Parse. Expression ]
197
198
expandMacroApplication macroDef rawAuxEnv args = do
198
- auxEnv <- exhaustM pruneEnv rawAuxEnv
199
+ auxEnv <-
200
+ exhaustM pruneEnv $ filter (not . isMacroDefinitionStatement) rawAuxEnv
199
201
result <- runMacro auxEnv
200
202
case result of
201
203
Right x -> Parse. parseMultiple x
202
- Left _ -> fatal " expandMacroApplication " " 0001 "
204
+ Left (stderr, _) -> throwError $ MacroError stderr
203
205
where
204
206
pruneEnv auxEnv = do
205
207
result <- runMacro auxEnv
206
208
pure $
207
209
case result of
208
210
Right _ -> auxEnv
209
- Left invalidDefs -> removeDefinitionsByName invalidDefs auxEnv
211
+ Left (_, invalidDefs) -> removeDefinitionsByName invalidDefs auxEnv
210
212
runMacro auxEnv = do
211
213
macroProgram <- generateMacroProgram macroDef auxEnv args
212
214
uncurry3 evalMacro macroProgram
213
215
214
- lookupMacroDefinition ::
215
- (MonadError Error m )
216
- => [MacroDefinition ]
217
- -> Parse. Expression
218
- -> m (Maybe MacroDefinition )
219
- lookupMacroDefinition macroDefs identifierExpr =
216
+ isMacroBeingCalled :: MacroDefinition -> Parse. Expression -> Bool
217
+ isMacroBeingCalled macroDef identifierExpr =
220
218
case identifierExpr of
221
- Parse. LiteralChar _ -> pure Nothing
222
- Parse. LiteralInt _ -> pure Nothing
223
- Parse. LiteralString _ -> pure Nothing
224
- Parse. SExpression _ -> pure Nothing
225
- Parse. Symbol identifier ->
226
- case filter (\ macroDef -> macroDef ^. name == identifier) macroDefs of
227
- [] -> pure Nothing
228
- [macroDef] -> pure $ Just macroDef
229
- _ ->
230
- throwError
231
- (MacroError $
232
- " Multiple macro definitions named: `" <> identifier <> " `!" )
219
+ Parse. LiteralChar _ -> False
220
+ Parse. LiteralInt _ -> False
221
+ Parse. LiteralString _ -> False
222
+ Parse. SExpression _ -> False
223
+ Parse. Symbol identifier -> macroDef ^. name == identifier
233
224
234
225
-- TODO This probably needs heavy optimization. If so, I will need to decrease the running time.
235
226
extractMacroDefinitions :: Statement -> [MacroDefinition ]
@@ -266,11 +257,13 @@ stripMacroDefinitions :: Statement -> Statement
266
257
stripMacroDefinitions =
267
258
\ case
268
259
STopLevel topLevel ->
269
- STopLevel $ (statements %~ filter (not . isMacroDefinition)) topLevel
260
+ STopLevel $
261
+ (statements %~ filter (not . isMacroDefinitionStatement)) topLevel
270
262
x -> x
271
- where
272
- isMacroDefinition (SMacroDefinition _) = True
273
- isMacroDefinition _ = False
263
+
264
+ isMacroDefinitionStatement :: Statement -> Bool
265
+ isMacroDefinitionStatement (SMacroDefinition _) = True
266
+ isMacroDefinitionStatement _ = False
274
267
275
268
replaceName ::
276
269
(MonadError Error m )
0 commit comments