1 module Typecheck where -- (typeCheckExp, typeCheckStm, typeCheckVar, State) where
5 import Control.Monad.State hiding (State)
7 import Prelude hiding (lookup)
9 type Types = [Map Ident Type]
10 type Function = (Type, [Type])
12 data State = State {variables::Types,functions::[Map Ident Function],function::Ident}
15 inList :: Eq a => a -> [a] -> Bool
17 inList a (x:xs) = if a == x then True else inList a xs
19 assert :: Monad m => Bool -> String -> m ()
20 assert True _ = return ()
21 assert False s = fail s
23 typeCheckExp :: (MonadState State m) => Exp -> m Type
24 typeCheckExp (BiOpExp e o e') = do
27 assert (t1 == t2) "The parameters for the binary operator aren't equal"
28 if inList o [Eq,NEq] then return TBool
30 assert (t1 == TInt) "The parameters need to be of type int"
31 if inList o [Plus,Minus,Times,Div]
34 typeCheckExp (EVar i) = typeCheckVar i
35 typeCheckExp (EAss i e) = do
38 assert (t == t2) $ "Illegal to assign an expression of type "++show t2++" to variable "++show i++" of type "++show t
40 typeCheckExp (EInt i) = return TInt
41 typeCheckExp (EBool b) = return TBool
42 typeCheckExp EReadI = return TInt
43 typeCheckExp EReadB = return TBool
44 typeCheckExp (EPost i op) = do
45 TInt <- typeCheckVar i
47 typeCheckExp (ENeg e) = do
48 TInt <- typeCheckExp e
50 typeCheckExp (ENot e) = do
51 TBool <- typeCheckExp e
54 typeCheckVar :: (MonadState State m) => Ident -> m Type
57 findVariable i $ variables s
59 findVariable :: (MonadState State m) => Ident -> Types -> m Type
60 findVariable i [] = fail $ "Variable "++show i++" not found in any scope."
61 findVariable i (m:ms) = if member i m then lookup i m else findVariable i ms
63 pushAndPop :: (MonadState State m) => m a -> m ()
65 modify (\s -> s { variables = empty:variables s})
67 modify (\s -> s { variables = tail $ variables s})
69 typeCheckStm :: (MonadState State m) => Stm -> m ()
70 typeCheckStm SNoop = return ()
71 typeCheckStm (SExp e) = do
74 typeCheckStm (SBlock ss) = pushAndPop $ mapM typeCheckStm ss
75 typeCheckStm (SIf e s s') = do
76 TBool <- typeCheckExp e
77 pushAndPop $ typeCheckStm s
78 pushAndPop $ typeCheckStm s'
79 typeCheckStm (SWhile e s) = do
80 TBool <- typeCheckExp e
81 pushAndPop $ typeCheckStm s
82 typeCheckStm (SDeclD t i) = addVariable i t
83 typeCheckStm (SDecl t i e) = do
85 assert (t == t2) $ "Illegal to assign an expression of type "++show t2++" to variable "++show i++" of type "++show t
87 typeCheckStm (SPrint e) = do
91 addVariable :: (MonadState State m) => Ident -> Type -> m ()
94 let (m:ms) = variables s in case insertLookupWithKey (\k a1 a2 -> a1) i t m of
95 (Nothing,m') -> modify (\s -> s{ variables = m':ms})
96 _ -> fail $ "Duplicate variable declaration: "++show i