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