]> ruin.nu Git - proglang.git/commitdiff
more generic type declaration and evaluates input directly
authorMichael Andreen <harv@ruin.nu>
Wed, 15 Mar 2006 12:35:18 +0000 (12:35 +0000)
committerMichael Andreen <harv@ruin.nu>
Wed, 15 Mar 2006 12:35:18 +0000 (12:35 +0000)
Interpret.hs

index 948903ebd9416e6de394f62cc4c27772eacd96b0..5e18d88b07046182de7c51ed0866d1e18c82691d 100644 (file)
@@ -21,19 +21,21 @@ type Function = ([Decl],[Stm])
 
 data State = State {variables::Variables,functions::(Map Ident Function),ret::Value}
 
-type EvalM = ErrorT String (StateT State IO)
+type EvalM m = ErrorT String m
 
 interpret :: [Func] -> [Stm] -> IO ()
 interpret fun st = do
-       runStateT (runErrorT  (do mapM Interpret.addFunction fun; mapM_ execute st)) emptyState
+       runStateT (runErrorT  (do mapM addFunction fun; mapM_ execute st)) emptyState
        return ()
 
---eval :: (MonadState Variables m) => Exp -> m Value
-eval :: Exp -> EvalM Value
+--eval :: (MonadState State m, MonadError String m, MonadIO m) => Exp -> m Value
+eval :: (MonadState State m, MonadIO m) => Exp -> EvalM m 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 (EAss i e) = do 
+       v <- eval e
+       setVariableValue i v
 eval (BiOpExp e o e') = do
        v <- eval e
        v'<- eval e'
@@ -41,7 +43,7 @@ eval (BiOpExp e o e') = do
                else let (VInt n1) = v in let (VInt n2) = v' in return $ op o n1 n2
 eval (EPost i o) = do
        (VInt n) <- getVariableValue i
-       let (VInt n') = op o n 1 in setVariableValue i $ EInt n'
+       setVariableValue i $ op o n 1
        return $ VInt n
 eval (ENeg e) = do
        (VInt n) <- eval e
@@ -50,10 +52,10 @@ eval (ENot e) = do
        (VBool b) <- eval e
        return $ VBool $ not b
 eval EReadI = do
-       s <- liftIO $ getWord
+       s <- liftIO $ getNumber
        return $ VInt $ read s
 eval EReadB = do
-       s <- liftIO $ getWord
+       s <- liftIO $ getNumber
        return $ VBool $ if (read s == 0) then False else True
 eval (EFunc i as) = do
        vs <- mapM eval as
@@ -61,19 +63,30 @@ eval (EFunc i as) = do
        (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 `catchError` (\_ -> return ())
-       s <- get
+       (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
+       state' <- get
        put state
-       return $ ret s
+       return $ ret state'
+
+--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."
 
-getWord :: IO String
-getWord =  do
+getNumber2 :: IO String
+getNumber2 =  do
        c <- getChar
-       if elem c [' ', '\n', '\t', '\r']
-               then return ""
-               else do
-                       l <- getWord
+       if elem c ['0'..'9']
+               then do
+                       l <- getNumber2
                        return (c:l)
+               else return ""
 
 -- op :: Op -> (a -> a -> Value)
 opE Eq = \e e' -> VBool $ e == e'
@@ -92,15 +105,13 @@ getVariableValue i = do
        s <- get 
        findVariable i $ variables s
 
-findVariable :: (MonadState State m) => Ident -> Variables -> m Value
+findVariable :: (Monad 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
 
-setVariableValue :: Ident -> Exp -> EvalM Value
-setVariableValue i e = do
-       v <- eval e
-       state <- get
-       modify (\s -> s{variables= updateVariable i v $ variables state} )
+setVariableValue :: (MonadState State m) => Ident -> Value -> EvalM m Value
+setVariableValue i v = do
+       modify (\s -> s{variables= updateVariable i v $ variables s} )
        return v
 
 updateVariable :: Ident -> Value -> Variables -> Variables 
@@ -114,7 +125,7 @@ pushAndPop s = do
        modify (\s -> s { variables = tail $ variables s})
 
 -- execute :: (MonadState Variables m) => Stm -> m ()
-execute :: Stm -> EvalM ()
+execute :: (MonadState State m, MonadIO m) => Stm -> EvalM m ()
 execute (SNoop) = return ()
 execute (SExp e) = eval e >> return ()
 execute (SIf b s s') = do