+eval (ENeg e) = do
+ (VInt n) <- eval e
+ return $ VInt $ -n
+eval (ENot e) = do
+ (VBool b) <- eval e
+ return $ VBool $ not b
+eval EReadI = do
+ s <- liftIO $ getNumber
+ return $ VInt $ read s
+eval EReadB = do
+ s <- liftIO $ getNumber
+ return $ VBool $ if (read s == 0) then False else True
+eval (EFunc i as) = do
+ vs <- mapM eval as
+ state <- get
+ (ds,ss) <- lookup i $ functions state
+ let m = foldr (\((Decl t i),v) m -> insert i v m) empty $ zip ds vs
+ in modify (\s -> s{variables=[m]})
+ (mapM_ execute ss >> (fail $ "Function "++show i++" didn't return anything."))
+ `catchError` (\_ ->return ()) --Only errors thrown in ErrorT can be caught here, runtime errors pass through, so no need to check the error
+ v <- liftM ret get
+ put state
+ return v
+
+--Stricter evaluation of the input
+getNumber :: IO String
+getNumber = do
+ c <- getChar
+ if elem c $ '-':['0'..'9']
+ then do
+ l <- getNumber2
+ return (c:l)
+ else fail "Non integer input."
+
+getNumber2 :: IO String
+getNumber2 = do
+ c <- getChar
+ if elem c ['0'..'9']
+ then do
+ l <- getNumber2
+ return (c:l)
+ else return ""