diff options
author | Akshay <[email protected]> | 2020-10-16 18:22:30 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2020-10-16 18:22:30 +0100 |
commit | 297b498acd205f0fcd68f3cdf7536b480cfac5e3 (patch) | |
tree | ec66452d4f8a95dc042d940edd9ce3921e5dcf2c | |
parent | 55065d6f67cf4b2f0bfaae19b38157a4ca934a62 (diff) |
add basic quasiquote and unquote behaviour
-rw-r--r-- | src/Error/Base.hs | 2 | ||||
-rw-r--r-- | src/Evaluator.hs | 29 |
2 files changed, 20 insertions, 11 deletions
diff --git a/src/Error/Base.hs b/src/Error/Base.hs index ef32d52..747904a 100644 --- a/src/Error/Base.hs +++ b/src/Error/Base.hs | |||
@@ -24,7 +24,7 @@ literal v = "`" <> v <> "`" | |||
24 | 24 | ||
25 | instance Show LispError where | 25 | instance Show LispError where |
26 | show (Parse e) = "Parser Error: " ++ show e | 26 | show (Parse e) = "Parser Error: " ++ show e |
27 | show (BadForm s expr) = "Bad Form: " ++ literal s ++ ": " ++ show expr | 27 | show (BadForm s expr) = "Bad Form: " ++ s ++ ": " ++ show expr |
28 | -- TODO: clean this up | 28 | -- TODO: clean this up |
29 | show (ArgCount fn n es) | 29 | show (ArgCount fn n es) |
30 | | null es = "Invalid arity, " ++ literal fn ++ " expects " ++ show n ++ " or more expression(s)!" | 30 | | null es = "Invalid arity, " ++ literal fn ++ " expects " ++ show n ++ " or more expression(s)!" |
diff --git a/src/Evaluator.hs b/src/Evaluator.hs index e3bf697..1cc9edd 100644 --- a/src/Evaluator.hs +++ b/src/Evaluator.hs | |||
@@ -1,5 +1,7 @@ | |||
1 | module Evaluator (eval) where | 1 | module Evaluator (eval) where |
2 | 2 | ||
3 | import Control.Applicative ((*>)) | ||
4 | import Control.Arrow ((&&&)) | ||
3 | import Control.Monad.Except | 5 | import Control.Monad.Except |
4 | import Environment | 6 | import Environment |
5 | import Error.Base (LispError (..), LispResult (..), | 7 | import Error.Base (LispError (..), LispResult (..), |
@@ -14,6 +16,19 @@ apply fn args = maybe | |||
14 | ($ args) | 16 | ($ args) |
15 | (lookup fn primitives) | 17 | (lookup fn primitives) |
16 | 18 | ||
19 | evalUnquote :: Env -> Expr -> IOResult Expr | ||
20 | evalUnquote env (List [Id "unquote", vs]) = eval env vs | ||
21 | evalUnquote env (List [Id "quote", vs]) = | ||
22 | liftM (List . ([Id "quote"] ++ ) . (: [])) (evalUnquote env vs) | ||
23 | evalUnquote env (List vs) = liftM List $ mapM (evalUnquote env) vs | ||
24 | evalUnquote env (Vector vs) = liftM Vector $ mapM (evalUnquote env) vs | ||
25 | evalUnquote env literal = return literal | ||
26 | |||
27 | evalQuasiQuote :: Env -> Expr -> IOResult Expr | ||
28 | evalQuasiQuote env v@(Vector _) = evalUnquote env v | ||
29 | evalQuasiQuote env q@(List _) = evalUnquote env q -- list of atoms which may be quoted or unquoted | ||
30 | evalQuasiQuote env literal = return literal -- just behave like quote otherwise | ||
31 | |||
17 | eval :: Env -> Expr -> IOResult Expr | 32 | eval :: Env -> Expr -> IOResult Expr |
18 | eval _ v@(StringLiteral s) = return v | 33 | eval _ v@(StringLiteral s) = return v |
19 | eval _ v@(IntLiteral i) = return v | 34 | eval _ v@(IntLiteral i) = return v |
@@ -22,16 +37,10 @@ eval env (Id l) = getVar env l | |||
22 | eval _ v@(FloatLiteral f) = return v | 37 | eval _ v@(FloatLiteral f) = return v |
23 | eval env v@(Vector xs) = liftM Vector $ mapM (eval env) xs | 38 | eval env v@(Vector xs) = liftM Vector $ mapM (eval env) xs |
24 | eval env (List[Id "quote", val]) = return val | 39 | eval env (List[Id "quote", val]) = return val |
25 | eval env (List[Id "quasiquote", val]) = undefined | 40 | eval env (List[Id "quasiquote", val]) = evalQuasiQuote env val |
26 | eval env (List[Id "unquote", val]) = eval env val | 41 | eval env v@(List[Id "unquote", val]) = throwError $ BadForm "Cannot use `unquote` form outside quasiquote context" v |
27 | eval env (List [Id "set!", Id var, val]) = do | 42 | eval env (List [Id "set!", Id var, val]) = eval env val >>= uncurry (*>) . ((setVar env var) &&& pure) |
28 | e <- eval env val | 43 | eval env (List [Id "define", Id var, val]) = eval env val >>= uncurry (*>) . ((defineVar env var) &&& pure) |
29 | setVar env var e | ||
30 | return e | ||
31 | eval env (List [Id "define", Id var, val]) = do | ||
32 | e <- eval env val | ||
33 | defineVar env var e | ||
34 | return e | ||
35 | eval env (List (Id fn : args)) = mapM (eval env) args >>= liftLispResult . apply fn | 44 | eval env (List (Id fn : args)) = mapM (eval env) args >>= liftLispResult . apply fn |
36 | eval env NoReturn = throwError $ BadForm "Invalid usage of non-returning expression" NoReturn | 45 | eval env NoReturn = throwError $ BadForm "Invalid usage of non-returning expression" NoReturn |
37 | 46 | ||