aboutsummaryrefslogtreecommitdiff
path: root/src/Environment.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Environment.hs')
-rw-r--r--src/Environment.hs69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/Environment.hs b/src/Environment.hs
new file mode 100644
index 0000000..7b3f365
--- /dev/null
+++ b/src/Environment.hs
@@ -0,0 +1,69 @@
1module Environment ( Env
2 , setVar
3 , getVar
4 , defineVar
5 , manyBindings
6 , newEnv
7 , liftLispResult
8 , IOResult
9 ) where
10
11import Control.Monad (liftM, mapM)
12import Control.Monad.Except
13import Data.IORef
14import Data.Maybe (isJust)
15import Error.Base (LispError (..), LispResult (..), unwrap)
16import Parser (Expr (..))
17
18type Env = IORef [(String, IORef Expr)]
19
20newEnv :: IO Env
21newEnv = newIORef []
22
23type IOResult = ExceptT LispError IO
24
25liftLispResult :: LispResult a -> IOResult a
26liftLispResult (Left err) = throwError err
27liftLispResult (Right val) = return val
28
29isBound :: Env -> String -> IO Bool
30isBound env var = do
31 ptr <- readIORef env
32 return $ isJust $ lookup var ptr
33
34-- env modifiers
35
36getVar :: Env -> String -> IOResult Expr
37getVar env var = do
38 ptr <- liftIO $ readIORef env
39 maybe (throwError $ UnboundVariable var)
40 (liftIO . readIORef)
41 $ lookup var ptr
42
43setVar :: Env -> String -> Expr -> IOResult ()
44setVar env var val = do
45 ptr <- liftIO $ readIORef env
46 maybe (throwError $ UnboundVariable var)
47 (liftIO . (flip writeIORef val))
48 $ lookup var ptr
49
50defineVar :: Env -> String -> Expr -> IOResult ()
51defineVar env var val = do
52 alreadyBound <- liftIO $ isBound env var
53 if alreadyBound
54 then setVar env var val
55 else liftIO $ do
56 newRef <- newIORef val
57 ptr <- readIORef env
58 writeIORef env $ (var, newRef):ptr
59
60makeBind :: (String, Expr) -> IO (String, IORef Expr)
61makeBind (var, val) = do
62 n <- newIORef val
63 return (var, n)
64
65manyBindings :: Env -> [(String, Expr)] -> IO Env
66manyBindings env binds = do
67 ptr <- readIORef env
68 extendedEnv <- liftM (++ ptr) $ mapM makeBind binds
69 newIORef extendedEnv