-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: command line interface options
- Loading branch information
Showing
2 changed files
with
89 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,94 @@ | ||
{-# LANGUAGE NamedFieldPuns #-} | ||
|
||
module Main where | ||
|
||
import qualified Ast.Types as T | ||
import qualified Ast.Parser as P | ||
import qualified Codegen.Codegen as C | ||
import qualified Control.Monad as M | ||
import qualified Control.Monad.Trans.Except as E | ||
import qualified Data.Text.Lazy as TL | ||
import qualified LLVM.Pretty as P | ||
import qualified LLVM.Pretty as LLVM | ||
import qualified Options.Applicative as O | ||
import qualified System.Exit as EX | ||
import qualified System.IO as S | ||
|
||
data CompileError | ||
= ParseError String | ||
| CodegenError String | ||
deriving (Show) | ||
|
||
data Options = Options | ||
{ input :: Maybe FilePath, | ||
out :: FilePath, | ||
verbose :: Bool | ||
} | ||
|
||
optionsParser :: O.Parser Options | ||
optionsParser = | ||
Options | ||
<$> O.optional | ||
( O.strOption | ||
( O.long "input" | ||
<> O.short 'i' | ||
<> O.metavar "FILENAME" | ||
<> O.help "Input file to read from (defaults to STDIN)" | ||
) | ||
) | ||
<*> O.strOption | ||
( O.long "out" | ||
<> O.metavar "FILENAME" | ||
<> O.help "Output file for the generated LLVM IR" | ||
<> O.value "demo/generated.ll" | ||
) | ||
<*> O.switch | ||
( O.long "verbose" | ||
<> O.short 'v' | ||
<> O.help "Enable verbose logging" | ||
) | ||
|
||
optionsInfo :: O.ParserInfo Options | ||
optionsInfo = | ||
O.info | ||
(O.helper <*> optionsParser) | ||
( O.fullDesc | ||
<> O.progDesc "A compiler that generates LLVM IR from a scheme-like language" | ||
<> O.header "Scheme-to-LLVM Compiler" | ||
) | ||
|
||
compile :: String -> E.ExceptT CompileError IO String | ||
compile input = do | ||
ast <- case P.parse input of | ||
Left err -> E.throwE $ ParseError (show err) | ||
Right res -> return res | ||
|
||
case C.codegen ast of | ||
Left err -> E.throwE $ CodegenError (show err) | ||
Right lmod -> return $ TL.unpack $ LLVM.ppllvm lmod | ||
|
||
logMsg :: Bool -> String -> IO () | ||
logMsg verbose msg = M.when verbose $ S.hPutStrLn S.stderr ("[LOG] " ++ msg) | ||
|
||
readInput :: Maybe FilePath -> IO String | ||
readInput Nothing = getContents | ||
readInput (Just filePath) = readFile filePath | ||
|
||
handleError :: String -> String -> Bool -> IO a | ||
handleError errType errMsg verbose = do | ||
S.hPutStrLn S.stderr $ "Error: " ++ errMsg | ||
logMsg verbose $ "Compilation failed during " ++ errType ++ "." | ||
EX.exitWith $ EX.ExitFailure 84 | ||
|
||
main :: IO () | ||
main = do | ||
let ast = | ||
T.AST | ||
[ T.Define "value" (T.Lit (T.LInt 21)), | ||
T.Define | ||
"$$generated" | ||
( T.If | ||
(T.Lit (T.LInt 1)) | ||
( T.Call | ||
( T.Lambda | ||
["x"] | ||
( T.Seq | ||
[ T.Define "example" (T.Lit (T.LInt 2)), | ||
T.Op T.Mult (T.Var "x") (T.Var "example") | ||
] | ||
) | ||
) | ||
(T.Seq [T.Var "value"]) | ||
) | ||
( T.Call | ||
( T.Lambda ["y"] (T.Seq [T.Op T.Sub (T.Var "y") (T.Lit (T.LInt 1))]) | ||
) | ||
(T.Seq [T.Lit (T.LInt 2)]) | ||
) | ||
) | ||
] | ||
|
||
let output = case C.codegen ast of | ||
Left err -> error (show err) | ||
Right lmod -> TL.unpack $ P.ppllvm lmod | ||
writeFile "demo/generated.ll" output | ||
Options {input, out, verbose} <- O.execParser optionsInfo | ||
source <- readInput input | ||
|
||
logMsg verbose "Starting compilation..." | ||
result <- E.runExceptT $ compile source | ||
|
||
case result of | ||
Left (ParseError err) -> handleError "parsing" err verbose | ||
Left (CodegenError err) -> handleError "parsing" err verbose | ||
Right llvm -> do | ||
writeFile out llvm | ||
logMsg verbose $ "Compilation successful! Output written to: " ++ out |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters