aboutsummaryrefslogtreecommitdiff
path: root/src/Haskell/Env.hs
blob: 6b742215e032a2ddf9c43698d72400b818b1df09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
module Haskell.Env where

import Control.Monad
import Data.List
import qualified Data.Map.Strict as Map
import Haskell.AST


data Env = Env { eDefs :: Map.Map Name Expr }
  deriving (Show)

instance Pretty Env where
    pretty (Env defs) =
        intercalate "\n" [n ++ " = " ++ pretty e | (n, e) <- Map.assocs defs]

emptyEnv :: Env
emptyEnv = Env Map.empty

envFromAST :: AST -> Either String Env
envFromAST = addAST emptyEnv

addAST :: Env -> AST -> Either String Env
addAST env (AST tops) = foldM addTop env tops

addTop :: Env -> Toplevel -> Either String Env
addTop env (TopDef def) = addDef env def
addTop _ _ = Left "Only plain top-level definitions supported for the moment"

addDef :: Env -> Def -> Either String Env
addDef env (Def n ex) =
    if envContains env n
        then Left $ "Name '" ++ n ++ "' already present in environment"
        else Right $ env { eDefs = Map.insert n ex (eDefs env) }

envContains :: Env -> Name -> Bool
envContains env name = Map.member name (eDefs env)

forget :: Env -> Name -> Either String Env
forget env name =
    if envContains env name
        then Right $ env { eDefs = Map.delete name (eDefs env) }
        else Left $ "Name '" ++ name ++ "' not found in environment"

reAdd :: Env -> Def -> Either String Env
reAdd env def@(Def name _) = forget env name >>= flip addDef def

get :: Env -> Name -> Either String Expr
get env name = case Map.lookup name (eDefs env) of
    Nothing -> Left "Name doesn't exist"
    Just ex -> Right ex