11import Control.Monad.Except (liftIO , runExceptT )
2- import qualified Data.Map as Map
2+ import qualified Data.Map.Strict as Map
33
44import Readline (addHistory , readline , load_history )
55import Types
66import Reader (read_str )
7- import Printer (_pr_list , _pr_str )
7+ import Printer (_pr_list , _pr_str )
88
9- --
10- -- Set this to True for a trace of each call to Eval.
11- --
12- traceEval :: Bool
13- traceEval = False
9+ type Env = Map. Map String MalVal
1410
1511-- read
1612
@@ -19,34 +15,32 @@ mal_read = read_str
1915
2016-- eval
2117
22- apply_ast :: MalVal -> [MalVal ] -> IOThrows MalVal
23- apply_ast first rest = do
24- evd <- eval first
18+ apply_ast :: MalVal -> [MalVal ] -> Env -> IOThrows MalVal
19+ apply_ast first rest env = do
20+ evd <- eval env first
2521 case evd of
26- MalFunction _ f -> f =<< mapM eval rest
22+ MalFunction _ f -> f =<< mapM ( eval env) rest
2723 _ -> throwStr . (++) " invalid apply: " =<< liftIO (_pr_list True " " $ first : rest)
2824
29- eval :: MalVal -> IOThrows MalVal
30- eval ast = do
31- case traceEval of
32- True -> liftIO $ do
33- putStr " EVAL: "
34- putStrLn =<< _pr_str True ast
35- False -> pure ()
25+ eval :: Env -> MalVal -> IOThrows MalVal
26+ eval env ast = do
27+ -- putStr "EVAL: "
28+ -- putStrLn =<< mal_print ast
3629 case ast of
3730 MalSymbol sym -> do
38- case Map. lookup sym repl_env of
31+ let maybeVal = Map. lookup sym env
32+ case maybeVal of
3933 Nothing -> throwStr $ " '" ++ sym ++ " ' not found"
4034 Just val -> return val
41- MalSeq _ (Vect False ) (a1 : as) -> apply_ast a1 as
42- MalSeq _ (Vect True ) xs -> MalSeq (MetaData Nil ) (Vect True ) <$> mapM eval xs
43- MalHashMap _ xs -> MalHashMap (MetaData Nil ) <$> mapM eval xs
35+ MalSeq _ (Vect False ) (a1 : as) -> apply_ast a1 as env
36+ MalSeq _ (Vect True ) xs -> MalSeq (MetaData Nil ) (Vect True ) <$> mapM ( eval env) xs
37+ MalHashMap _ xs -> MalHashMap (MetaData Nil ) <$> mapM ( eval env) xs
4438 _ -> return ast
4539
4640-- print
4741
48- mal_print :: MalVal -> IOThrows String
49- mal_print = liftIO . Printer. _pr_str True
42+ mal_print :: MalVal -> IO String
43+ mal_print = _pr_str True
5044
5145-- repl
5246
@@ -66,35 +60,27 @@ divd :: Fn
6660divd [MalNumber a, MalNumber b] = return $ MalNumber $ a `div` b
6761divd _ = throwStr $ " illegal arguments to /"
6862
69- repl_env :: Map. Map String MalVal
70- repl_env = Map. fromList [(" +" , _func add),
71- (" -" , _func sub),
72- (" *" , _func mult),
73- (" /" , _func divd)]
74-
75- rep :: String -> IOThrows String
76- rep line = mal_print =<< eval =<< mal_read line
77-
78- repl_loop :: IO ()
79- repl_loop = do
63+ repl_loop :: Env -> IO ()
64+ repl_loop env = do
8065 line <- readline " user> "
8166 case line of
8267 Nothing -> return ()
83- Just " " -> repl_loop
68+ Just " " -> repl_loop env
8469 Just str -> do
8570 addHistory str
86- res <- runExceptT $ rep str
71+ res <- runExceptT $ eval env =<< mal_read str
8772 out <- case res of
88- Left mv -> (++) " Error: " <$> liftIO ( Printer. _pr_str True mv)
89- Right val -> return val
73+ Left mv -> (++) " Error: " <$> mal_print mv
74+ Right val -> mal_print val
9075 putStrLn out
91- repl_loop
92-
93- _func :: Fn -> MalVal
94- _func f = MalFunction (MetaData Nil ) f
76+ repl_loop env
9577
9678main :: IO ()
9779main = do
98- load_history
80+ let repl_env = Map. fromList [(" +" , MalFunction (MetaData Nil ) add),
81+ (" -" , MalFunction (MetaData Nil ) sub),
82+ (" *" , MalFunction (MetaData Nil ) mult),
83+ (" /" , MalFunction (MetaData Nil ) divd)]
9984
100- repl_loop
85+ load_history
86+ repl_loop repl_env
0 commit comments