{-# LANGUAGE FlexibleContexts, LambdaCase #-} module Task12 where import Control.Applicative import Control.Monad.Writer import Control.Monad.State import Data.Map ( Map ) import qualified Data.Map as M import System.IO ( hPutStrLn, stderr ) type Varname = String type Assignment = Map Varname Integer data AExpr = Con Integer | Var Varname | Add AExpr AExpr | Mul AExpr AExpr deriving ( Eq, Show, Read ) data BExpr = Equal AExpr AExpr | LEQ AExpr AExpr | And BExpr BExpr | Not BExpr deriving ( Eq, Show, Read ) data Command = Def Varname AExpr | Assign Varname AExpr | Print Varname | If BExpr Command Command | While BExpr Command | Seq [Command] deriving ( Eq, Show, Read ) val :: (MonadState Assignment m, MonadIO m) => String -> m Integer val v = gets (M.lookup v) >>= \case Nothing -> liftIO (hPutStrLn stderr $ "ERROR: use of undefined variable " ++ v) >> pure 0 Just x -> pure x aeval :: (MonadState Assignment m, MonadIO m) => AExpr -> m Integer aeval = undefined beval :: (MonadState Assignment m, MonadIO m) => BExpr -> m Bool beval = undefined ceval :: (MonadState Assignment m, MonadWriter [Integer] m, MonadIO m) => Command -> m () ceval = undefined eval :: Command -> IO () eval cmd = do (_, prints) <- runWriterT $ evalStateT (ceval cmd) M.empty putStrLn . unlines $ map show prints