1 module Typecheck (typeCheckExp, typeCheckStm, typeCheckVar) where
5 import Control.Monad.State
7 import Prelude hiding (lookup)
9 type Types = [Map Ident Type]
11 inList :: Eq a => a -> [a] -> Bool
13 inList a (x:xs) = if a == x then True else inList a xs
15 assert :: Monad m => Bool -> String -> m ()
16 assert True _ = return ()
17 assert False s = fail s
19 typeCheckExp :: (MonadState Types m) => Exp -> m Type
20 typeCheckExp (BiOpExp e o e') = do
23 assert (t1 == t2) "The parameters for the binary operator aren't equal"
24 if inList o [Eq,NEq] then return TBool
26 assert (t1 == TInt) "The parameters need to be of type int"
27 if inList o [Plus,Minus,Times,Div]
30 typeCheckExp (EVar i) = typeCheckVar i
31 typeCheckExp (EAss i e) = do
34 assert (t == t2) $ "Illegal to assign an expression of type "++show t2++" to variable "++show i++" of type "++show t
36 typeCheckExp (EInt i) = return TInt
37 typeCheckExp (EBool b) = return TBool
38 typeCheckExp EReadI = return TInt
39 typeCheckExp EReadB = return TBool
40 typeCheckExp (EPost i op) = do
41 TInt <- typeCheckVar i
43 typeCheckExp (ENeg e) = do
44 TInt <- typeCheckExp e
46 typeCheckExp (ENot e) = do
47 TBool <- typeCheckExp e
50 typeCheckVar :: (MonadState Types m) => Ident -> m Type
55 findVariable :: (MonadState Types m) => Ident -> Types -> m Type
56 findVariable i [] = fail $ "Variable "++show i++" not found in any scope."
57 findVariable i (m:ms) = if member i m then lookup i m else findVariable i ms
59 pushAndPop :: (MonadState Types m) => m a -> m ()
65 typeCheckStm :: (MonadState Types m) => Stm -> m ()
66 typeCheckStm SNoop = return ()
67 typeCheckStm (SExp e) = do
70 typeCheckStm (SBlock ss) = pushAndPop $ mapM typeCheckStm ss
71 typeCheckStm (SIf e s s') = do
72 TBool <- typeCheckExp e
73 pushAndPop $ typeCheckStm s
74 pushAndPop $ typeCheckStm s'
75 typeCheckStm (SWhile e s) = do
76 TBool <- typeCheckExp e
77 pushAndPop $ typeCheckStm s
78 typeCheckStm (SDeclD t i) = addVariable i t
79 typeCheckStm (SDecl t i e) = do
81 assert (t == t2) $ "Illegal to assign an expression of type "++show t2++" to variable "++show i++" of type "++show t
83 typeCheckStm (SPrint e) = do
87 addVariable :: (MonadState Types m) => Ident -> Type -> m ()
90 case insertLookupWithKey (\k a1 a2 -> a1) i t m of
91 (Nothing,m') -> put (m':ms)
92 _ -> fail $ "Duplicate variable declaration: "++show i