From b5054ba12b7dcadcb27dbd55ee81c5ffe0076049 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Mon, 8 Nov 2021 16:15:24 +0100 Subject: [PATCH] Adding cond --- app/Main.hs | 5 +++-- src/Evaluator.hs | 2 ++ src/Expressions.hs | 6 +++++- src/LispEnv.hs | 23 +++++++++++++++++------ src/LispParser.hs | 1 + 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 38a72bd..6ab71ef 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -4,9 +4,9 @@ import System.Console.Haskeline ( defaultSettings, getInputLine, outputStrLn, runInputT, InputT ) import BasicParser import LispParser -import Expressions import Evaluator import LispEnv +import Expressions main :: IO () main = runInputT defaultSettings (loop defaultEnv) @@ -25,7 +25,8 @@ main = runInputT defaultSettings (loop defaultEnv) case parse pStatement input of (Just res, []) -> case eval res env of - (Right (str, env)) -> outputStrLn (show str) >> return env + (Right (ANothing, env)) -> return env + (Right (at, env)) -> outputStrLn (show at) >> return env (Left err) -> outputStrLn err >> return env (_, lo) -> outputStrLn ("**Error: Invalid syntax near: " ++ lo ++ "**") >> return env diff --git a/src/Evaluator.hs b/src/Evaluator.hs index c46a5ba..fe8e502 100644 --- a/src/Evaluator.hs +++ b/src/Evaluator.hs @@ -54,6 +54,8 @@ showType v@(ACons _ _) = "(Cons " ++ show v ++ ")" showType v@AProcedure {} = "(Procedure " ++ show v ++ ")" showType v@ABuiltin {} = "(Builtin " ++ show v ++ ")" showType ATrue = "(True #t)" +showType AFalse = "(False #f)" +showType ANothing = "(Nothing)" setupLocalVars :: [String] -> [Statement] -> LispEnv -> Either String LispEnv setupLocalVars (n:names) (v:values) env = do diff --git a/src/Expressions.hs b/src/Expressions.hs index c6176fa..1e3843c 100644 --- a/src/Expressions.hs +++ b/src/Expressions.hs @@ -10,12 +10,16 @@ data Atom = AQuote Atom | AProcedure String [String] SExpr | ABuiltin String ([Statement] -> LispEnv -> Either String (Atom, LispEnv)) | - ATrue + ATrue | + AFalse | + ANothing newtype SExpr = SExpr [Statement] instance Show Atom where show ATrue = "#t" + show ANothing = "" + show AFalse = "#f" show (AInt int) = show int show (ASymbol symb) = symb show (AString str) = "\"" ++ str ++ "\"" diff --git a/src/LispEnv.hs b/src/LispEnv.hs index cfc18dc..60387e0 100644 --- a/src/LispEnv.hs +++ b/src/LispEnv.hs @@ -9,7 +9,8 @@ defaultEnv = [ ("car", ABuiltin "car" evalCar), ("cdr", ABuiltin "cdr" evalCdr), ("eq?", ABuiltin "eq?" evalEq), - ("atom?", ABuiltin "atom?" evalAtom) + ("atom?", ABuiltin "atom?" evalAtom), + ("cond", ABuiltin "cond" evalCond) ] evalCons :: [Statement] -> LispEnv -> Either String (Atom, LispEnv) @@ -42,18 +43,19 @@ evalCdr _ _ = Left "**Error: incorect argument count in cdr**" _fromBool :: Bool -> Atom _fromBool True = ATrue -_fromBool False = ANil +_fromBool False = AFalse evalEq :: [Statement] -> LispEnv -> Either String (Atom, LispEnv) evalEq [Atom (AInt f), Atom (AInt s)] env = Right (_fromBool (f == s), env) evalEq [Atom (ASymbol f), Atom (ASymbol s)] env = Right (_fromBool (f == s), env) -evalEq [Atom (AString f), Atom (AString s)] env = Right (ANil, env) -- TODO Should do a reference equal +evalEq [Atom (AString f), Atom (AString s)] env = Right (AFalse, env) -- TODO Should do a reference equal evalEq [Atom (AFloat f), Atom (AFloat s)] env = Right (_fromBool(f == s), env) -evalEq [Atom (ACons _ _), _] env = Right (ANil, env) +evalEq [Atom (ACons _ _), _] env = Right (AFalse, env) evalEq [Atom ANil, Atom ANil] env = Right (ATrue, env) evalEq [Atom (AProcedure f _ _), Atom (AProcedure s _ _)] env = Right (_fromBool (f == s), env) evalEq [Atom (ABuiltin f _), Atom (ABuiltin s _)] env = Right (_fromBool (f == s), env) evalEq [Atom ATrue, Atom ATrue] env = Right (ATrue, env) +evalEq [Atom AFalse, Atom AFalse] env = Right (ATrue, env) evalEq [Expr exp, other] env = do (first, nEnv) <- evalS exp env evalEq [Atom first, other] nEnv @@ -65,10 +67,19 @@ evalEq [other, Atom (AQuote quoted)] env = evalEq [Atom quoted, other] env evalEq _ _ = Left "**Error: Invalid arguments in eq?**" evalAtom :: [Statement] -> LispEnv -> Either String (Atom, LispEnv) -evalAtom [Atom (ACons _ _)] env = Right (ANil, env) +evalAtom [Atom (ACons _ _)] env = Right (AFalse, env) evalAtom [Atom (AQuote quoted)] env = evalAtom [Atom quoted] env evalAtom [Expr expr] env = do (atm, nEnv) <- evalS expr env evalAtom [Atom atm] nEnv evalAtom [Atom _] env = Right (ATrue, env) -evalAtom _ _ = Left "**Error: Invalid arguments in atom?**" \ No newline at end of file +evalAtom _ _ = Left "**Error: Invalid arguments in atom?**" + +evalCond :: [Statement] -> LispEnv -> Either String (Atom, LispEnv) +evalCond (Expr (SExpr [cond, value]):xs) env = do + (res, nEnv) <- eval cond env + case res of + AFalse -> evalCond xs nEnv + _ -> eval value nEnv +evalCond [] env = Right (ANothing, env) +evalCond _ _ = Left "**Error: Invalid syntax for cond.**" \ No newline at end of file diff --git a/src/LispParser.hs b/src/LispParser.hs index cce19fe..dddcbac 100644 --- a/src/LispParser.hs +++ b/src/LispParser.hs @@ -9,6 +9,7 @@ _pAtom :: Parser Atom _pAtom = AInt <$> pInt <|> AFloat <$> pFloat <|> ATrue <$ pString "#t" + <|> AFalse <$ pString "#f" <|> pCharIf (== '"') *> (AString <$> pUntil (== '"')) <* pCharIf (== '"') <|> ANil <$ pString "nil" <|> ASymbol <$> pToken