module Main where import SimpleLexer import Expr import StackMachine import qualified Data.Map as Map type Variable = String data Command = Let Variable Expr | Eval Expr parseLet :: [Token] -> Maybe (Command, [Token]) parseLet (Ident "let" : Ident v : Sep '=' : rest) = case parseExpr rest of Nothing -> Nothing Just (e, rest') -> Just (Let v e, rest') parseLet _ = Nothing parseCommand :: [Token] -> Maybe (Command, [Token]) parseCommand toks = case parseLet toks of Nothing -> fmap (pupd1 Eval) $ parseExpr toks r -> r type VarAssign = Map.Map Variable Integer evalExpr :: VarAssign -> Expr -> Either String Integer evalExpr va (Num n) = Right n evalExpr va (Var v) = case Map.lookup v va of Nothing -> Left $ "Variable ``" ++ v ++ "'' undefined!" Just k -> Right k evalExpr va (Bin e1 op e2) = case evalExpr va e1 of Left e -> Left e Right m -> case evalExpr va e2 of Left e -> Left e Right n -> evalOp op m n evalOp :: Op -> Integer -> Integer -> Either String Integer evalOp (MkOp "+") m n = Right (m + n) evalOp (MkOp "-") m n = Right (m - n) evalOp (MkOp "*") m n = Right (m * n) evalOp (MkOp "/") m 0 = Left "division by zero!" evalOp (MkOp "/") m n = Right (m `div` n) evalOp (MkOp s) _ _ = Left $ "unknown operator ``" ++ s ++ "''" type State = VarAssign trInterp1 :: Transition State String String trInterp1 (s, input) = case parseCommand (simpleLexer input) of Nothing -> (s, "<<< syntax error >>>") Just (c, toks@(_ : _)) -> (s, "<<< spurious trailing material: " ++ show toks) Just (Let v e,[]) -> case evalExpr s e of Left e -> (s, "> error: " ++ e) Right n -> (Map.insert v n s, "> " ++ v ++ " = " ++ show n) Just (Eval e,[]) -> (s, case evalExpr s e of Left e -> "> error: " ++ e Right n -> "> " ++ show n ) main :: IO () main = runprocess trInterp1 Map.empty