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