diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Base.hs | 51 | ||||
-rw-r--r-- | src/Environment.hs | 3 | ||||
-rw-r--r-- | src/Evaluator.hs | 12 | ||||
-rw-r--r-- | src/Parser.hs | 8 |
4 files changed, 51 insertions, 23 deletions
diff --git a/src/Base.hs b/src/Base.hs index 08131e8..422e534 100644 --- a/src/Base.hs +++ b/src/Base.hs | |||
@@ -1,10 +1,41 @@ | |||
1 | module Base (Expr (..) | 1 | module Base (Expr (..) |
2 | , Env (..) | 2 | , Env (..) |
3 | , Function (..) | 3 | , LispNumber (..) |
4 | ) where | 4 | ) where |
5 | 5 | ||
6 | import Data.IORef | 6 | import Data.IORef |
7 | 7 | ||
8 | data LispNumber = I Integer | ||
9 | | F Double | ||
10 | deriving (Eq, Ord) | ||
11 | |||
12 | instance Num LispNumber where | ||
13 | -- addition | ||
14 | (I a) + (I b) = I $ a + b | ||
15 | (F a) + (F b) = F $ a + b | ||
16 | (F a) + (I b) = F $ a + fromIntegral b | ||
17 | (I a) + (F b) = F b + I a | ||
18 | |||
19 | -- subtraction | ||
20 | (I a) - (I b) = I $ a - b | ||
21 | (F a) - (F b) = F $ a - b | ||
22 | (F a) - (I b) = F $ a - fromIntegral b | ||
23 | (I a) - (F b) = F b - I a | ||
24 | |||
25 | -- multiplication | ||
26 | (I a) * (I b) = I $ a * b | ||
27 | (F a) * (F b) = F $ a * b | ||
28 | (F a) * (I b) = F $ a * fromIntegral b | ||
29 | (I a) * (F b) = F b * I a | ||
30 | |||
31 | instance Fractional LispNumber where | ||
32 | (I a) / (I b) = F $ fromIntegral a / fromIntegral b | ||
33 | (F a) / (I b) = F $ a / fromIntegral b | ||
34 | (I a) / (F b) = recip $ F b / I a | ||
35 | (F a) / (F b) = F $ a / b | ||
36 | recip (F x) = F $ 1 / x | ||
37 | recip (I x) = F $ 1 / fromIntegral x | ||
38 | |||
8 | -- TODO: use LispNumber (src/Operators.hs) here instead of IntLiteral and FloatLiteral | 39 | -- TODO: use LispNumber (src/Operators.hs) here instead of IntLiteral and FloatLiteral |
9 | -- TODO: add character literals: \#a \#b \#c \#space \#newline | 40 | -- TODO: add character literals: \#a \#b \#c \#space \#newline |
10 | -- TODO: add support for complex numbers, oct and hex numbers | 41 | -- TODO: add support for complex numbers, oct and hex numbers |
@@ -12,19 +43,15 @@ data Expr = List [Expr] | |||
12 | | Vector [Expr] | 43 | | Vector [Expr] |
13 | | DottedList [Expr] Expr | 44 | | DottedList [Expr] Expr |
14 | | StringLiteral String | 45 | | StringLiteral String |
15 | | IntLiteral Integer | 46 | | Number LispNumber |
16 | | FloatLiteral Double | ||
17 | | BoolLiteral Bool | 47 | | BoolLiteral Bool |
18 | | Id String | 48 | | Id String |
49 | | Function { params :: [String] | ||
50 | , body :: Expr | ||
51 | , extendedEnv :: Env | ||
52 | } | ||
19 | deriving (Eq) | 53 | deriving (Eq) |
20 | 54 | ||
21 | data Function = | ||
22 | Function { | ||
23 | params :: [String] | ||
24 | , body :: Expr | ||
25 | , environment :: Env | ||
26 | } | ||
27 | |||
28 | type Env = IORef [(String, IORef Expr)] | 55 | type Env = IORef [(String, IORef Expr)] |
29 | 56 | ||
30 | showLispList :: [Expr] -> String | 57 | showLispList :: [Expr] -> String |
@@ -35,8 +62,8 @@ instance Show Expr where | |||
35 | show (List xs) = "(" ++ showLispList xs ++ ")" | 62 | show (List xs) = "(" ++ showLispList xs ++ ")" |
36 | show (Vector xs) = "#(" ++ showLispList xs ++ ")" | 63 | show (Vector xs) = "#(" ++ showLispList xs ++ ")" |
37 | show (StringLiteral s) = "\"" ++ s ++ "\"" | 64 | show (StringLiteral s) = "\"" ++ s ++ "\"" |
38 | show (IntLiteral n) = show n | 65 | show (Number (I n)) = show n |
39 | show (FloatLiteral n) = show n | 66 | show (Number (F n)) = show n |
40 | show (BoolLiteral True) = "#t" | 67 | show (BoolLiteral True) = "#t" |
41 | show (BoolLiteral False) = "#f" | 68 | show (BoolLiteral False) = "#f" |
42 | show (Id i) = i | 69 | show (Id i) = i |
diff --git a/src/Environment.hs b/src/Environment.hs index b7b7ee6..e38e36c 100644 --- a/src/Environment.hs +++ b/src/Environment.hs | |||
@@ -64,5 +64,4 @@ makeBind (var, val) = do | |||
64 | manyBindings :: Env -> [(String, Expr)] -> IO Env | 64 | manyBindings :: Env -> [(String, Expr)] -> IO Env |
65 | manyBindings env binds = do | 65 | manyBindings env binds = do |
66 | ptr <- readIORef env | 66 | ptr <- readIORef env |
67 | extendedEnv <- (++ ptr) <$> mapM makeBind binds | 67 | newIORef =<< (++ ptr) <$> mapM makeBind binds |
68 | newIORef extendedEnv | ||
diff --git a/src/Evaluator.hs b/src/Evaluator.hs index 3bc1e09..db56068 100644 --- a/src/Evaluator.hs +++ b/src/Evaluator.hs | |||
@@ -9,12 +9,13 @@ import Error.Base (LispError (..), LispResult (..), | |||
9 | unwrap) | 9 | unwrap) |
10 | import Operators | 10 | import Operators |
11 | import Text.ParserCombinators.Parsec | 11 | import Text.ParserCombinators.Parsec |
12 | import qualified Data.Map as M | ||
12 | 13 | ||
13 | apply :: String -> [Expr] -> LispResult Expr | 14 | apply :: String -> [Expr] -> LispResult Expr |
14 | apply fn args = maybe | 15 | apply fn args = maybe |
15 | (throwError $ UnknownFunction fn) | 16 | (throwError $ UnknownFunction fn) |
16 | ($ args) | 17 | ($ args) |
17 | (lookup fn primitives) | 18 | (M.lookup fn primitives) |
18 | 19 | ||
19 | evalUnquoteSplicing :: Env -> Expr -> IOResult Expr | 20 | evalUnquoteSplicing :: Env -> Expr -> IOResult Expr |
20 | evalUnquoteSplicing env (List xs) = List <$> mapM (eval env) xs | 21 | evalUnquoteSplicing env (List xs) = List <$> mapM (eval env) xs |
@@ -39,10 +40,8 @@ evalQuasiQuote env literal = return literal -- just behave like quote other | |||
39 | 40 | ||
40 | eval :: Env -> Expr -> IOResult Expr | 41 | eval :: Env -> Expr -> IOResult Expr |
41 | eval _ v@(StringLiteral s) = return v | 42 | eval _ v@(StringLiteral s) = return v |
42 | eval _ v@(IntLiteral i) = return v | 43 | eval _ v@(Number i) = return v |
43 | eval _ v@(BoolLiteral b) = return v | ||
44 | eval env (Id l) = getVar env l | 44 | eval env (Id l) = getVar env l |
45 | eval _ v@(FloatLiteral f) = return v | ||
46 | eval env v@(Vector xs) = Vector <$> mapM (eval env) xs | 45 | eval env v@(Vector xs) = Vector <$> mapM (eval env) xs |
47 | eval env (List[Id "quote", val]) = return val | 46 | eval env (List[Id "quote", val]) = return val |
48 | eval env (List[Id "quasiquote", val]) = evalQuasiQuote env val | 47 | eval env (List[Id "quasiquote", val]) = evalQuasiQuote env val |
@@ -50,6 +49,7 @@ eval env v@(List[Id "unquote", val]) = throwError $ BadForm "Cannot use | |||
50 | eval env v@(List[Id "unquote-splicing", val]) = throwError $ BadForm "Cannot use `unquote-splicing` outside quasiquote form" v | 49 | eval env v@(List[Id "unquote-splicing", val]) = throwError $ BadForm "Cannot use `unquote-splicing` outside quasiquote form" v |
51 | eval env (List [Id "set!", Id var, val]) = eval env val >>= uncurry (*>) . (setVar env var &&& pure) | 50 | eval env (List [Id "set!", Id var, val]) = eval env val >>= uncurry (*>) . (setVar env var &&& pure) |
52 | eval env (List [Id "define", Id var, val]) = eval env val >>= uncurry (*>) . (defineVar env var &&& pure) | 51 | eval env (List [Id "define", Id var, val]) = eval env val >>= uncurry (*>) . (defineVar env var &&& pure) |
52 | -- eval env (List (Id "lambda":List params:body)) = evalLambda params body env | ||
53 | eval env (List (Id fn : args)) = mapM (eval env) args >>= liftLispResult . apply fn | 53 | eval env (List (Id fn : args)) = mapM (eval env) args >>= liftLispResult . apply fn |
54 | 54 | ||
55 | -- handle bad forms | 55 | -- handle bad forms |
@@ -58,3 +58,7 @@ eval env invalidForm = throwError $ BadForm "lisk can't recognize this form" inv | |||
58 | unwrapList :: Expr -> [Expr] | 58 | unwrapList :: Expr -> [Expr] |
59 | unwrapList (List x) = x | 59 | unwrapList (List x) = x |
60 | unwrapList literal = [literal] | 60 | unwrapList literal = [literal] |
61 | |||
62 | -- evalLambda :: [Expr] -> Expr -> Env -> IOResult Expr | ||
63 | -- evalLambda params body env = do | ||
64 | -- extendedEnv <- manyBindings env | ||
diff --git a/src/Parser.hs b/src/Parser.hs index dfc3225..48dca0e 100644 --- a/src/Parser.hs +++ b/src/Parser.hs | |||
@@ -7,7 +7,7 @@ module Parser ( parseLispValue | |||
7 | , parseComment | 7 | , parseComment |
8 | ) where | 8 | ) where |
9 | 9 | ||
10 | import Base (Expr (..), Function) | 10 | import Base (Expr (..), LispNumber(..)) |
11 | import Control.Applicative ((<$>)) | 11 | import Control.Applicative ((<$>)) |
12 | import Control.Monad (void) | 12 | import Control.Monad (void) |
13 | import Text.Parsec.Char | 13 | import Text.Parsec.Char |
@@ -34,7 +34,7 @@ parseInt :: Parser Expr | |||
34 | parseInt = do | 34 | parseInt = do |
35 | sign <- parseSign | 35 | sign <- parseSign |
36 | val <- many1 digit | 36 | val <- many1 digit |
37 | return $ (IntLiteral . read) $ maybe val (:val) sign | 37 | return $ (Number . I . read) $ maybe val (:val) sign |
38 | 38 | ||
39 | parseFloat :: Parser Expr | 39 | parseFloat :: Parser Expr |
40 | parseFloat = do | 40 | parseFloat = do |
@@ -43,7 +43,7 @@ parseFloat = do | |||
43 | char '.' | 43 | char '.' |
44 | mantissa <- many1 digit | 44 | mantissa <- many1 digit |
45 | let fval = characteristic ++ "." ++ mantissa | 45 | let fval = characteristic ++ "." ++ mantissa |
46 | return $ (FloatLiteral . read) $ maybe fval (:fval) sign | 46 | return $ (Number . F . read) $ maybe fval (:fval) sign |
47 | 47 | ||
48 | parseVector :: Parser Expr | 48 | parseVector :: Parser Expr |
49 | parseVector = do | 49 | parseVector = do |
@@ -112,6 +112,4 @@ parseLispValue = | |||
112 | optionalWhiteSpace >> char ')' | 112 | optionalWhiteSpace >> char ')' |
113 | return $ maybe (List x) (DottedList x) t | 113 | return $ maybe (List x) (DottedList x) t |
114 | <?> "lisp value"; | 114 | <?> "lisp value"; |
115 | -- try parseComment; | ||
116 | -- return pepe; | ||
117 | 115 | ||