]> ruin.nu Git - proglang.git/blob - Typecheck.hs
a78f8f02c6a51d5d6d643d01ee8a4232f4223dab
[proglang.git] / Typecheck.hs
1 module Typecheck (typeCheckExp, typeCheckStm, typeCheckVar) where 
2
3
4 import Abssyntax
5 import Control.Monad.State
6 import Data.Map as Map
7 import Prelude hiding (lookup)
8
9 type Types = [Map Ident Type]
10
11 inList :: Eq a => a -> [a] -> Bool
12 inList _ [] = False
13 inList a (x:xs) = if a == x then True else inList a xs
14
15 assert :: Monad m => Bool -> String -> m ()
16 assert True _ = return ()
17 assert False s = fail s
18
19 typeCheckExp :: (MonadState Types m) => Exp -> m Type
20 typeCheckExp (BiOpExp e o e') = do
21         t1 <- typeCheckExp e
22         t2 <- typeCheckExp e'
23         assert (t1 == t2) "The parameters for the binary operator aren't equal"
24         if inList o [Eq,NEq] then return TBool
25                 else do 
26                         assert (t1 == TInt) "The parameters need to be of type int" 
27                         if inList o [Plus,Minus,Times,Div]
28                                 then return TInt
29                                 else return TBool
30 typeCheckExp (EVar i) = typeCheckVar i
31 typeCheckExp (EAss i e) = do
32         t <- typeCheckVar i
33         t2 <- typeCheckExp e
34         assert (t == t2) $ "Illegal to assign an expression of type "++show t2++" to variable "++show i++" of type "++show t 
35         return 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
42         return TInt
43 typeCheckExp (ENeg e) = do
44         TInt <- typeCheckExp e
45         return TInt
46 typeCheckExp (ENot e) = do
47         TBool <- typeCheckExp e
48         return TBool
49
50 typeCheckVar :: (MonadState Types m) => Ident -> m Type 
51 typeCheckVar i = do
52         ms <- get
53         findVariable i ms
54
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
58
59 typeCheckStm :: (MonadState Types m) => Stm -> m ()
60 typeCheckStm SNoop = return ()
61 typeCheckStm (SExp e) = do 
62         typeCheckExp e
63         return ()
64 typeCheckStm (SBlock ss) = do 
65         modify (empty:)
66         mapM typeCheckStm ss
67         modify tail
68 typeCheckStm (SIf e s s') = do
69         TBool <- typeCheckExp e
70         modify (empty:)
71         typeCheckStm s
72         modify (\s -> empty:tail s)
73         typeCheckStm s'
74         modify tail
75 typeCheckStm (SWhile e s) = do
76         TBool <- typeCheckExp e
77         modify (empty:)
78         typeCheckStm s
79         modify tail
80 typeCheckStm (SDecl t i e) = do
81         t2 <- typeCheckExp e
82         assert (t == t2) $ "Illegal to assign an expression of type "++show t2++" to variable "++show i++" of type "++show t
83         (m:ms) <- get
84         case insertLookupWithKey (\k a1 a2 -> a1) i t m of
85                 (Nothing,m') -> put (m':ms)
86                 _ -> fail $ "Duplicate variable declaration: "++show i
87 typeCheckStm (SPrint e) = do
88         typeCheckExp e
89         return ()