import EnvSimple import Parser import Repl type Symbol = String data Expr = ENum Integer | EId Symbol | EPlus Expr Expr | ETimes Expr Expr | EApp Symbol Expr | ELet Symbol Expr Expr deriving Show type Environment = Env Integer type FunDefs = Env (Symbol, Expr) eval :: FunDefs -> Environment -> Expr -> Integer eval fdefs env (ENum n) = n eval fdefs env (EId id) = lookup_variable env id eval fdefs env (EPlus e1 e2) = eval fdefs env e1 + eval fdefs env e2 eval fdefs env (ETimes e1 e2) = eval fdefs env e1 * eval fdefs env e2 eval fdefs env (EApp f a) = let val = eval fdefs env a in let (p, b) = lookup_variable fdefs f in eval fdefs (bind_variable empty_env p val) b eval fdefs env (ELet x e b) = eval fdefs (bind_variable env x (eval fdefs env e)) b desugar :: FunDefs -> PExpr -> (FunDefs, Expr) desugar_expr (PNum n) = ENum n desugar_expr (PId id) = EId id desugar_expr (PPlus e1 e2) = EPlus (desugar_expr e1) (desugar_expr e2) desugar_expr (PTimes e1 e2) = ETimes (desugar_expr e1) (desugar_expr e2) desugar_expr (PMinus e1 e2) = EPlus (desugar_expr e1) (ETimes (ENum (-1)) (desugar_expr e2)) desugar_expr (PApp (PId f) [a]) = EApp f (desugar_expr a) desugar_expr (PDecl (PLet x _ e) b) = ELet x (desugar_expr e) (desugar_expr b) desugar_expr _ = error "unsupported syntactic construct\n" desugar fdefs (PDecl (PLetFun f [(a,_)] _ b) e) = desugar (bind_variable fdefs f (a, desugar_expr b)) e desugar fdefs e = (fdefs, desugar_expr e) run str = let (fdefs, expr) = desugar empty_env (parse str) in ("", show (eval fdefs empty_env expr)) main :: IO () main = repl run Nothing