-
Notifications
You must be signed in to change notification settings - Fork 0
/
Types.hs
82 lines (70 loc) · 2.84 KB
/
Types.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
module Types where
import qualified Data.Map as M
import Data.List
import Absmyjs
import Control.Monad.State
import Control.Monad.Trans.Except
type Loc = Int
type Var = String
type Env = M.Map Var Loc
data Val = UndefinedVal | StringVal String | IntVal Integer | BoolVal Bool | ObjectVal (M.Map String Val) | FunctionVal [String] CompoundStmt Env | BuiltinFunctionVal String
instance Show Val where
show (StringVal s) = s
show (IntVal i) = show i
show (BoolVal True) = "true"
show (BoolVal False) = "false"
show UndefinedVal = "undefined"
show (ObjectVal om) = "{" ++ (intercalate ", " list) ++ "}"
where list = M.foldWithKey (\key value result -> ("\"" ++ key ++ "\": " ++ (stringify value)):result) [] om
show (FunctionVal args _ _) = "[function(" ++ fargs ++ ")]"
where fargs = intercalate ", " args
show (BuiltinFunctionVal name) = "[built-in function: " ++ name ++ "]"
stringify :: Val -> String
stringify (StringVal s) = "\"" ++ s ++ "\""
stringify val = show val
iThrow text = lift $ throwE $ StringVal text
instance Num Val where
(+) (IntVal i1) (IntVal i2) = IntVal (i1 + i2)
(+) a1 a2 = StringVal $ (show a1) ++ (show a2)
(*) (IntVal i1) (IntVal i2) = IntVal (i1 * i2)
(*) a1 a2 = StringVal "NaN"
negate (IntVal i) = IntVal $ -i
negate _ = StringVal "NaN"
abs (IntVal i) = IntVal $ abs i
abs _ = StringVal "NaN"
fromInteger i = IntVal i
signum (IntVal i) = IntVal $ signum i
signum (StringVal s) = case s of
"" -> 0
_ -> 1
signum (BoolVal b) = case b of
False -> 0
True -> 1
signum (ObjectVal _) = 1
signum UndefinedVal = 0
signum (FunctionVal _ _ _) = 1
signum (BuiltinFunctionVal _) = 1
instance Fractional Val where
(/) (IntVal i1) (IntVal 0) = StringVal "NaN"
(/) (IntVal i1) (IntVal i2) = IntVal (i1 `div` i2)
(/) _ _ = StringVal "NaN"
fromRational _ = UndefinedVal
instance Ord Val where
(<) (IntVal i1) (IntVal i2) = i1 < i2
(<) (StringVal i1) (StringVal i2) = i1 < i2
(<) (BoolVal b1) (BoolVal b2) = b1 < b2
(<) _ _ = False
(<=) (IntVal i1) (IntVal i2) = i1 <= i2
(<=) (StringVal i1) (StringVal i2) = i1 <= i2
(<=) (BoolVal b1) (BoolVal b2) = b1 <= b2
(<=) _ _ = False
instance Eq Val where
(==) (IntVal i1) (IntVal i2) = i1 == i2
(==) (StringVal i1) (StringVal i2) = i1 == i2
(==) (BoolVal i1) (BoolVal i2) = i1 == i2
(==) UndefinedVal UndefinedVal = True
(==) (ObjectVal i1) (ObjectVal i2) = i1 == i2
(==) a1 a2 = False
isTruthy v = case signum v of
IntVal 0 -> False
_ -> True