This repository has been archived by the owner on Feb 3, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArith.hs
106 lines (98 loc) · 2.96 KB
/
Arith.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
data Type = TInt
| TBool
deriving (Eq, Show)
data Value = IntV Int
| BoolV Bool
deriving (Eq)
type TEnv = [(String, Type)]
type Env = [(String, Value)]
-- AST
data Exp = Num Int
| Add Exp Exp
| Sub Exp Exp
| Mult Exp Exp
| Div Exp Exp
| B Bool
| If Exp Exp Exp
| Eq Exp Exp
| Lt Exp Exp
-- Evaluator
evaluate :: Exp -> Env -> Maybe Value
evaluate (Num n) _ = Just (IntV n)
evaluate (Add a b) env = do
(IntV av) <- evaluate a env
(IntV bv) <- evaluate b env
return (IntV (av + bv))
evaluate (Sub a b) env = do
(IntV av) <- evaluate a env
(IntV bv) <- evaluate b env
return (IntV (av - bv))
evaluate (Mult a b) env = do
(IntV av) <- evaluate a env
(IntV bv) <- evaluate b env
return ((IntV (av * bv)))
evaluate (Div a b) env = do
(IntV av) <- evaluate a env
(IntV bv) <- evaluate b env
return (IntV (av `div` bv))
evaluate (B b) _ = Just (BoolV b)
evaluate (If e1 e2 e3) env = do
(BoolV f) <- evaluate e1 env
a <- evaluate e2 env
b <- evaluate e3 env
return (if f then a else b)
evaluate (Eq a b) env = do
(IntV av) <- evaluate a env
(IntV bv) <- evaluate b env
return (BoolV (av == bv))
evaluate (Lt a b) env = do
(IntV av) <- evaluate a env
(IntV bv) <- evaluate b env
return (BoolV (av < bv))
-- Type checker
tcheck :: Exp -> TEnv -> Maybe Type
tcheck (Num _) _ = Just TInt
tcheck (Add a b) env =
case (tcheck a env, tcheck b env) of
(Just TInt, Just TInt) -> Just TInt
_ -> Nothing
tcheck (Sub a b) env =
case (tcheck a env, tcheck b env) of
(Just TInt, Just TInt) -> Just TInt
_ -> Nothing
tcheck (Mult a b) env =
case (tcheck a env, tcheck b env) of
(Just TInt, Just TInt) -> Just TInt
_ -> Nothing
tcheck (Div a b) env =
case (tcheck a env, tcheck b env) of
(Just TInt, Just TInt) -> Just TInt
_ -> Nothing
tcheck (B _) _ = Just TBool
tcheck (If e1 e2 e3) env =
case (tcheck e1 env) of
Just TBool ->
case (tcheck e2 env, tcheck e3 env) of
(Just t1, Just t2)
| t1 == t2 -> Just t1
_ -> Nothing
_ -> Nothing
tcheck (Eq a b) env =
case (tcheck a env, tcheck b env) of
(Just TInt, Just TInt) -> Just TBool
_ -> Nothing
tcheck (Lt a b) env =
case (tcheck a env, tcheck b env) of
(Just TInt, Just TInt) -> Just TBool
_ -> Nothing
-- Pretty printer
pretty :: Exp -> String
pretty (Num n) = show n
pretty (Add exp1 exp2) = "(" ++ pretty exp1 ++ " + " ++ pretty exp2 ++ ")"
pretty (Sub exp1 exp2) = "(" ++ pretty exp1 ++ " - " ++ pretty exp2 ++ ")"
pretty (Mult exp1 exp2) = "(" ++ pretty exp1 ++ " * " ++ pretty exp2 ++ ")"
pretty (Div exp1 exp2) = "(" ++ pretty exp1 ++ " / " ++ pretty exp2 ++ ")"
pretty (B b) = show b
pretty (If e1 e2 e3) = "(if " ++ pretty e1 ++ " then " ++ pretty e2 ++ " else " ++ pretty e3 ++ ")"
pretty (Eq exp1 exp2) = "(" ++ pretty exp1 ++ " == " ++ pretty exp2 ++ ")"
pretty (Lt exp1 exp2) = "(" ++ pretty exp1 ++ " == " ++ pretty exp2 ++ ")"