+module Interpret (eval, execute, Value(VInt, VBool)) where
+
+import Abssyntax
+import Control.Monad.State
+import Data.Map as Map
+import Prelude hiding (lookup)
+
+data Value = VInt Integer | VBool Bool deriving Eq
+
+instance Show Value where
+ show (VInt n) = show n
+ show (VBool b) = show b
+
+type Variables = [Map Ident Value]
+
+inList :: Eq a => a -> [a] -> Bool
+inList _ [] = False
+inList a (x:xs) = if a == x then True else inList a xs
+
+--eval :: (MonadState Variables m) => Exp -> m Value
+eval :: Exp -> StateT Variables IO Value
+eval (EBool b) = return (VBool b)
+eval (EInt n) = return (VInt n)
+eval (EVar i) = getVariableValue i
+eval (EAss i e) = setVariableValue i e
+eval EDefault = return (VInt 0) --FIXME!!!
+eval (BiOpExp e o e') = do
+ v <- eval e
+ v'<- eval e'
+ if inList o [Eq,NEq] then return $ opE o v v'
+ else let (VInt n1) = v in let (VInt n2) = v' in return $ op o n1 n2
+typeCheckExp (EPost i op) = do
+ (VInt n) <- getVariableValue i
+ setVariableValue i $ EInt $ n+1
+ return $ VInt n
+
+-- op :: Op -> (a -> a -> Value)
+opE Eq = \e e' -> VBool $ e == e'
+opE NEq = \e e' -> VBool $ not (e == e')
+op Plus = \e e' -> VInt $ e + e'
+op Minus = \e e' -> VInt $ e - e'
+op Times = \e e' -> VInt $ e * e'
+op Div = \e e' -> VInt $ e `div` e'
+
+getVariableValue :: (MonadState Variables m) => Ident -> m Value
+getVariableValue i = do
+ ms <- get
+ findVariable i ms
+
+--setVariableValue :: (MonadState Variables m) => Ident -> Exp -> m Value
+setVariableValue :: Ident -> Exp -> StateT Variables IO Value
+setVariableValue i e = do
+ e' <- eval e
+ (m:ms) <- get
+ put $ (insert i e' m):ms
+ return e'
+
+findVariable :: (MonadState Variables m) => Ident -> Variables -> m Value
+findVariable i [] = fail $ "Variable "++show i++" not found in any scope."
+findVariable i (m:ms) = if member i m then lookup i m else findVariable i ms
+
+-- execute :: (MonadState Variables m) => Stm -> m ()
+execute :: Stm -> StateT Variables IO ()
+execute (SIf b s s') = do
+ (VBool b') <- eval b
+ if b' then execute s else execute s'
+execute (SPrint e) = do
+ e' <- eval e
+ lift $ print e'
+execute (SNoop) = return ()
+execute (SBlock ss) = do
+ modify (empty:)
+ mapM execute ss
+ modify tail
+execute (SWhile e s) = do
+ (VBool b) <- eval e
+ if b then execute (SWhile e s) else return ()
+execute (SDecl t i EDefault) = do
+ case t of
+ TInt -> setVariableValue i (EInt 0)
+ TBool -> setVariableValue i (EBool False)
+ return ()
+execute (SDecl t i e) = setVariableValue i e >> return ()