Handling arguments

This commit is contained in:
Zoe Roux
2021-11-09 11:38:33 +01:00
parent 569ce977ae
commit 7c1da5eef7
4 changed files with 50 additions and 5 deletions

View File

@@ -7,9 +7,12 @@ import LispParser
import Evaluator
import LispEnv
import Expressions
import System.Environment (getArgs)
import System.Exit (exitSuccess, exitFailure, exitWith, ExitCode (ExitFailure))
import Control.Exception (IOException, catch)
main :: IO ()
main = runInputT defaultSettings (loop defaultEnv)
runRepl :: LispEnv -> IO ()
runRepl env = runInputT defaultSettings (loop env)
where
loop :: LispEnv -> InputT IO ()
loop env = do
@@ -30,3 +33,42 @@ main = runInputT defaultSettings (loop defaultEnv)
(Left err) -> outputStrLn err >> return env
(_, lo) -> outputStrLn ("**Error: Invalid syntax near: " ++ lo ++ "**")
>> return env
evalFiles :: [String] -> LispEnv -> Either String (Atom, LispEnv)
evalFiles [x] env = evalFile x env
evalFiles (x:xs) env = do
(ret, nEnv) <- evalFile x env
evalFiles xs nEnv
evalFiles [] env = undefined
evalFile :: String -> LispEnv -> Either String (Atom, LispEnv)
evalFile file env =
case parse pLisp file of
(Just statements, []) -> evalStatements statements env
(_, lo) -> Left $ "**Parse error near " ++ lo ++ "**"
evalStatements :: [Statement] -> LispEnv -> Either String (Atom, LispEnv)
evalStatements [x] env = eval x env
evalStatements (x:xs) env = do
(ret, nEnv) <- eval x env
evalStatements xs nEnv
evalStatements [] env = Right (ANothing, env)
main :: IO ()
main = do
(args, repl) <- parseArgs <$> getArgs
files <- catch (sequence $ readFile <$> args) handler
case evalFiles files defaultEnv of
Right (ret, env) -> if repl then runRepl env else print ret
Left err -> putStrLn err >> exitWith (ExitFailure 84)
where
handler :: IOException -> IO [String]
handler e = putStrLn ("Error: " ++ show e) >> exitWith (ExitFailure 84)
parseArgs :: [String] -> ([String], Bool)
parseArgs ("-i":xs) = let (files, _) = parseArgs xs
in (files, True)
parseArgs (x:xs) = let (files, repl) = parseArgs xs
in (x:files, repl)
parseArgs [] = ([], False)

3
example/fact.lisp Normal file
View File

@@ -0,0 +1,3 @@
(define (fact x)
(cond ((eq? x 1) 1)
(#t (* x (fact (- x 1))))))

View File

@@ -3,7 +3,7 @@ module LispParser where
import BasicParser
( Parser, pCharIf, pUntil, pInt, pFloat, tokenify, pToken, pString )
import Expressions ( SExpr(..), Atom(..), Statement(..) )
import Control.Applicative ( Alternative(some, (<|>)) )
import Control.Applicative ( Alternative(some, many, (<|>)) )
_pAtom :: Parser Atom
_pAtom = AInt <$> pInt
@@ -64,4 +64,4 @@ pStatement = pCharIf (== '(')
<|> Atom <$> pAtom
pLisp :: Parser [Statement]
pLisp = some $ tokenify pStatement
pLisp = many $ tokenify pStatement

View File

@@ -51,7 +51,7 @@ evalMult [] env = Right (AInt 1, env)
evalDiv :: [Statement] -> LispEnv -> Either String (Atom, LispEnv)
evalDiv [_, Atom (AInt 0)] env = Left "**Error: Division by 0 is undefined.**"
evalDiv [_, Atom (AFloat 0)] env = Left "**Error: Division by 0 is undefined.**"
evalDiv [Atom (AInt f), Atom (AInt s)] env = Right (AInt (f `div` s), env)
evalDiv [Atom (AInt f), Atom (AInt s)] env = Right (AInt (f `quot` s), env)
evalDiv [Atom (AFloat f), Atom (AFloat s)] env = Right (AFloat (f / s), env)
evalDiv [Atom (AFloat f), Atom (AInt s)] env = Right (AFloat (f / fromIntegral s), env)
evalDiv [Atom (AInt f), Atom (AFloat s)] env = Right (AFloat (fromIntegral f / s), env)