import EnvSimple import Parser import Repl type Symbol = String data Value = VNum Integer | VFun Symbol Environment Expr data Expr = EId Symbol | ENum Integer | EPlus Expr Expr | ETimes Expr Expr | EApp Expr Expr | ELet Symbol Expr Expr | ELetFun Symbol Symbol Expr Expr deriving Show type Environment = Env Value eval :: Environment -> Expr -> Value eval env (ENum n) = VNum n eval env (EId id) = lookup_variable env id eval env (EPlus e1 e2) = case (eval env e1, eval env e2) of (VNum x1, VNum x2) -> VNum (x1 + x2) _ -> error "addition of non-numbers" eval env (ETimes e1 e2) = case (eval env e1, eval env e2) of (VNum x1, VNum x2) -> VNum (x1 * x2) _ -> error "multiplication of non-numbers" eval env (EApp f a) = let val = eval env a in case eval env f of VFun p e b -> eval (bind_variable env p val) b _ -> error "application of non-function" eval env (ELet x e b) = eval (bind_variable env x (eval env e)) b eval env (ELetFun f arg body e) = eval (bind_variable env f (VFun arg env body)) e desugar :: PExpr -> Expr desugar (PId id) = EId id desugar (PNum n) = ENum n desugar (PPlus e1 e2) = EPlus (desugar e1) (desugar e2) desugar (PTimes e1 e2) = ETimes (desugar e1) (desugar e2) desugar (PMinus e1 e2) = EPlus (desugar e1) (ETimes (ENum (-1)) (desugar e2)) desugar (PApp f [a]) = EApp (desugar f) (desugar a) desugar (PDecl (PLet x _ e) b) = ELet x (desugar e) (desugar b) desugar (PDecl (PLetFun f [(arg,_)] _ b) e) = ELetFun f arg (desugar b) (desugar e) desugar _ = error "unsupported syntactic construct" instance Show Value where show (VNum n) = show n show (VFun a _ b) = "fun (" ++ a ++ ") { " ++ show b ++ " }" run str = ("", show (eval empty_env (desugar (parse str)))) main :: IO () main = repl run Nothing