Last active
December 25, 2015 17:49
-
-
Save darkf/7015779 to your computer and use it in GitHub Desktop.
Barebones interpreter in Haskell showing `State s a`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.Monad.State (State, runState, evalState, get, put) | |
import qualified Data.Map as M | |
data AST = Add AST AST | |
| Def String AST | |
| Var String | |
| StrConst String | |
| IntConst Int | |
deriving (Show, Eq) | |
data Value = IntV Int | |
| StrV String | |
deriving (Show, Eq) | |
type Env = M.Map String Value -- an environment | |
type InterpState = State Env -- interpreter state (pass along the global environment) | |
(IntV l) +$ (IntV r) = IntV (l + r) | |
(StrV l) +$ (StrV r) = StrV (l ++ r) | |
l +$ r = error $ "cannot + " ++ show l ++ " and " ++ show r | |
eval :: AST -> InterpState Value | |
eval (IntConst i) = return $ IntV i | |
eval (StrConst s) = return $ StrV s | |
eval (Var var) = get >>= \m -> | |
case M.lookup var m of | |
Just v -> return v | |
Nothing -> error $ "unbound variable " ++ var | |
eval (Def name v') = do | |
v <- eval v' | |
m <- get | |
put $ M.insert name v m | |
return v | |
eval (Add l r) = do | |
l <- eval l | |
r <- eval r | |
return $ l +$ r | |
evalProgram :: [AST] -> Value -- fold the state from each node and return the result | |
evalProgram nodes = evalState (foldr1 (>>) $ map eval nodes) M.empty | |
main = do | |
print $ evalProgram prg | |
print $ evalProgram prg2 | |
where | |
prg = [Def "x" (IntConst 5), | |
Def "y" (IntConst 3), | |
Add (Var "x") (Var "y")] | |
prg2 = [Add (StrConst "hi ") (StrConst "there")] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment