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 | EFun Symbol Expr | EApp Expr Expr | ELet Symbol Expr Expr | EIf Expr Expr Expr Expr deriving Show type Environment = Env Value eval :: Environment -> Expr -> Value eval env (ENum n) = VNum n eval env (EFun arg body) = VFun arg env body 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 e 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 (EIf c1 c2 t e) = let v1 = eval env c1 in let v2 = eval env c2 in case (v1,v2) of (VNum n1, VNum n2) -> if n1 == n2 then eval env t else eval env e _ -> error "comparison of non-numbers" 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 (PFun [(p,_)] b) = EFun p (desugar b) 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 args _ b) e) = ELet f (desugar (PFun args b)) (desugar e) desugar (PIf (PEqual c1 c2) t e) = EIf (desugar c1) (desugar c2) (desugar t) (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