Skip to content

Commit 2139e9b

Browse files
committed
WIP
1 parent 32d8a1d commit 2139e9b

File tree

5 files changed

+62
-65
lines changed

5 files changed

+62
-65
lines changed

axel.cabal

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
--
33
-- see: https://github.com/sol/hpack
44
--
5-
-- hash: 72e1c0a2ad6eab54ed0144120fbe5cb23511fea32286f226574a144ccf14631f
5+
-- hash: 8d0ab6a7586d20892da1b6d2e8108404859096bc5719a7f3a8e30ebb8d4c4cf1
66

77
name: axel
88
version: 0.1.0.0
@@ -20,6 +20,7 @@ extra-source-files:
2020
README.org
2121
scripts/build.sh
2222
scripts/clean.sh
23+
scripts/lint.sh
2324
data-files:
2425
resources/autogenerated/macros/AST.hs
2526
resources/macros/MacroDefinitionAndEnvironmentHeader.hs

examples/do/app/Main.axel

+16-14
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
(module Main)
22

33
(defmacro fnCase
4-
((cases) (<$> (fn (varId)
5-
[`(fn (~varId)
6-
(case ~varId ~@cases))])
7-
AST.gensym)))
4+
((cases) (<$> (fn (varId)
5+
[`(fn (~varId)
6+
(case ~varId ~@cases))])
7+
AST.gensym)))
88

99
(defmacro quasiquote
1010
(([(AST.SExpression xs)])
@@ -20,18 +20,20 @@
2020
(pure [(AST.SExpression ['AST.SExpression (AST.SExpression ['concat (AST.SExpression (: 'list (map quasiquoteElem xs)))])])])))
2121
(([atom]) (pure [(AST.SExpression ['quote atom])])))
2222

23+
(= do' (-> ([] AST.Expression) AST.Expression)
24+
(() (fnCase
25+
((: var (: '<- (: val rest)))
26+
`(>>= ~val (fn (~var) ~(do' rest))))
27+
((: val rest)
28+
(case rest
29+
([]
30+
val)
31+
(_
32+
`(>> ~val ~(do' rest))))))))
33+
2334
(defmacro do
2435
((input)
25-
(let ((go (fnCase
26-
((: var (: '<- (: val rest)))
27-
`(>>= ~val (fn (~var) ~(go rest))))
28-
((: val rest)
29-
(case rest
30-
([]
31-
val)
32-
(_
33-
`(>> ~val ~(go rest))))))))
34-
(pure [(go input)]))))
36+
(pure [(do' input)])))
3537

3638
(= main (IO Unit)
3739
(() (do

src/Axel/AST.hs

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import Axel.Utils.Display
2121
)
2222
import Axel.Utils.Recursion (Recursive(bottomUpFmap, bottomUpTraverse))
2323

24+
import Control.Arrow ((***))
2425
import Control.Lens.Operators ((%~), (^.))
2526
import Control.Lens.TH (makeFieldsNoPrefix)
2627
import Control.Lens.Tuple (_1, _2)
@@ -350,7 +351,7 @@ instance Recursive Expression where
350351
ECaseBlock caseBlock ->
351352
ECaseBlock $
352353
caseBlock & expr %~ bottomUpFmap f & matches %~
353-
map (\(a, b) -> (bottomUpFmap f a, bottomUpFmap f b))
354+
map (bottomUpFmap f *** bottomUpFmap f)
354355
EEmptySExpression -> f x
355356
EFunctionApplication functionApplication ->
356357
EFunctionApplication $

src/Axel/Eval.hs

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ execInterpreter ::
1818
(MonadError Error m, MonadIO m)
1919
=> FilePath
2020
-> FilePath
21-
-> m (Either [String] String)
21+
-> m (Either (String, [String]) String)
2222
execInterpreter scaffoldFilePath macroDefinitionAndEnvironmentFilePath = do
2323
debugResult <- liftIO $ buildWithGHC scaffoldFilePath
2424
case debugResult of
@@ -31,14 +31,14 @@ execInterpreter scaffoldFilePath macroDefinitionAndEnvironmentFilePath = do
3131
jsonLog
3232
case invalidDefinitionNames of
3333
[] -> throwError $ MacroError stderr
34-
_ -> pure $ Left invalidDefinitionNames
34+
_ -> pure $ Left (stderr, invalidDefinitionNames)
3535

3636
evalMacro ::
3737
(MonadBaseControl IO m, MonadError Error m, MonadIO m)
3838
=> String
3939
-> String
4040
-> String
41-
-> m (Either [String] String)
41+
-> m (Either (String, [String]) String)
4242
evalMacro astDefinition scaffold macroDefinitionAndEnvironment =
4343
withTempDirectory $ \directoryName ->
4444
withCurrentDirectoryLifted directoryName $ do

src/Axel/Macros.hs

+39-46
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Axel.AST
1717
, statements
1818
)
1919
import Axel.Denormalize (denormalizeExpression, denormalizeStatement)
20-
import Axel.Error (Error(MacroError), fatal)
20+
import Axel.Error (Error(MacroError))
2121
import Axel.Eval (evalMacro)
2222
import Axel.Normalize (normalizeStatement)
2323
import qualified Axel.Parse as Parse
@@ -35,16 +35,17 @@ import Axel.Utils.Resources (readDataFile)
3535
import Axel.Utils.String (replace)
3636

3737
import Control.Lens.Operators ((%~), (^.))
38-
import Control.Lens.Tuple (_1, _2)
3938
import Control.Monad (foldM)
4039
import Control.Monad.Except (MonadError, catchError, throwError)
4140
import Control.Monad.IO.Class (MonadIO, liftIO)
4241
import Control.Monad.Trans.Control (MonadBaseControl)
4342

44-
import Data.Function ((&))
45-
import Data.List (foldl')
43+
import Data.List (foldl', partition)
44+
import Data.Maybe (listToMaybe)
4645
import Data.Semigroup ((<>))
4746

47+
import Debug.Trace (trace)
48+
4849
getAstDefinition :: IO String
4950
getAstDefinition = readDataFile "autogenerated/macros/AST.hs"
5051

@@ -120,15 +121,17 @@ expansionPass programExpr = do
120121
extractIndependentStatements $ programToStmts programExpr
121122
normalizedStmts <- traverse normalizeStatement independentStmts
122123
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
132135
where
133136
canInclude :: Statement -> Bool
134137
canInclude =
@@ -156,13 +159,13 @@ exhaustivelyExpandMacros ::
156159
exhaustivelyExpandMacros = exhaustM expansionPass
157160

158161
-- TODO This needs heavy optimization.
159-
expandMacros ::
162+
expandMacro ::
160163
(MonadBaseControl IO m, MonadError Error m, MonadIO m)
161-
=> [MacroDefinition]
164+
=> MacroDefinition
162165
-> [Statement]
163166
-> Parse.Expression
164167
-> m Parse.Expression
165-
expandMacros macroDefs auxEnv =
168+
expandMacro macroDef auxEnv =
166169
bottomUpTraverse $ \expr ->
167170
case expr of
168171
Parse.LiteralChar _ -> pure expr
@@ -178,11 +181,9 @@ expandMacros macroDefs auxEnv =
178181
Parse.LiteralString _ -> pure $ acc ++ [x]
179182
Parse.SExpression [] -> pure $ acc ++ [x]
180183
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]
186187
Parse.Symbol _ -> pure $ acc ++ [x])
187188
[]
188189
xs
@@ -195,41 +196,31 @@ expandMacroApplication ::
195196
-> [Parse.Expression]
196197
-> m [Parse.Expression]
197198
expandMacroApplication macroDef rawAuxEnv args = do
198-
auxEnv <- exhaustM pruneEnv rawAuxEnv
199+
auxEnv <-
200+
exhaustM pruneEnv $ filter (not . isMacroDefinitionStatement) rawAuxEnv
199201
result <- runMacro auxEnv
200202
case result of
201203
Right x -> Parse.parseMultiple x
202-
Left _ -> fatal "expandMacroApplication" "0001"
204+
Left (stderr, _) -> throwError $ MacroError stderr
203205
where
204206
pruneEnv auxEnv = do
205207
result <- runMacro auxEnv
206208
pure $
207209
case result of
208210
Right _ -> auxEnv
209-
Left invalidDefs -> removeDefinitionsByName invalidDefs auxEnv
211+
Left (_, invalidDefs) -> removeDefinitionsByName invalidDefs auxEnv
210212
runMacro auxEnv = do
211213
macroProgram <- generateMacroProgram macroDef auxEnv args
212214
uncurry3 evalMacro macroProgram
213215

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 =
220218
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
233224

234225
-- TODO This probably needs heavy optimization. If so, I will need to decrease the running time.
235226
extractMacroDefinitions :: Statement -> [MacroDefinition]
@@ -266,11 +257,13 @@ stripMacroDefinitions :: Statement -> Statement
266257
stripMacroDefinitions =
267258
\case
268259
STopLevel topLevel ->
269-
STopLevel $ (statements %~ filter (not . isMacroDefinition)) topLevel
260+
STopLevel $
261+
(statements %~ filter (not . isMacroDefinitionStatement)) topLevel
270262
x -> x
271-
where
272-
isMacroDefinition (SMacroDefinition _) = True
273-
isMacroDefinition _ = False
263+
264+
isMacroDefinitionStatement :: Statement -> Bool
265+
isMacroDefinitionStatement (SMacroDefinition _) = True
266+
isMacroDefinitionStatement _ = False
274267

275268
replaceName ::
276269
(MonadError Error m)

0 commit comments

Comments
 (0)