forked from kanaka/mal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Types.hs
141 lines (104 loc) · 3.85 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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
module Types
(MalVal (..), MalError (..), IOThrows (..), Fn (..), EnvData (..), Env,
throwStr, throwMalVal, _get_call, _to_list,
_func, _malfunc,
_nil_Q, _true_Q, _false_Q, _string_Q, _symbol_Q, _keyword_Q,
_list_Q, _vector_Q, _hash_map_Q, _atom_Q)
where
import Data.IORef (IORef)
import qualified Data.Map as Map
import Control.Exception as CE
import Control.Monad.Error (ErrorT, Error, noMsg, strMsg, throwError)
-- Base Mal types --
newtype Fn = Fn ([MalVal] -> IOThrows MalVal)
data MalVal = Nil
| MalFalse
| MalTrue
| MalNumber Int
| MalString String
| MalSymbol String
| MalList [MalVal] MalVal
| MalVector [MalVal] MalVal
| MalHashMap (Map.Map String MalVal) MalVal
| MalAtom (IORef MalVal) MalVal
| Func Fn MalVal
| MalFunc {fn :: Fn,
ast :: MalVal,
env :: Env,
params :: MalVal,
macro :: Bool,
meta :: MalVal}
_equal_Q Nil Nil = True
_equal_Q MalFalse MalFalse = True
_equal_Q MalTrue MalTrue = True
_equal_Q (MalNumber a) (MalNumber b) = a == b
_equal_Q (MalString a) (MalString b) = a == b
_equal_Q (MalSymbol a) (MalSymbol b) = a == b
_equal_Q (MalList a _) (MalList b _) = a == b
_equal_Q (MalList a _) (MalVector b _) = a == b
_equal_Q (MalVector a _) (MalList b _) = a == b
_equal_Q (MalVector a _) (MalVector b _) = a == b
_equal_Q (MalHashMap a _) (MalHashMap b _) = a == b
_equal_Q (MalAtom a _) (MalAtom b _) = a == b
_equal_Q _ _ = False
instance Eq MalVal where
x == y = _equal_Q x y
--- Errors/Exceptions ---
data MalError = StringError String
| MalValError MalVal
type IOThrows = ErrorT MalError IO
instance Error MalError where
noMsg = StringError "An error has occurred"
strMsg = StringError
throwStr str = throwError $ StringError str
throwMalVal mv = throwError $ MalValError mv
-- Env types --
-- Note: Env functions are in Env module
data EnvData = EnvPair (Maybe Env, (Map.Map String MalVal))
type Env = IORef EnvData
----------------------------------------------------------
-- General functions --
_get_call ((Func (Fn f) _) : _) = return f
_get_call (MalFunc {fn=(Fn f)} : _) = return f
_get_call _ = throwStr "_get_call first parameter is not a function "
_to_list (MalList lst _) = return lst
_to_list (MalVector lst _) = return lst
_to_list _ = throwStr "_to_list expected a MalList or MalVector"
-- Errors
--catchAny :: IO a -> (CE.SomeException -> IO a) -> IO a
--catchAny = CE.catch
-- Functions
_func fn = Func (Fn fn) Nil
_func_meta fn meta = Func (Fn fn) meta
_malfunc ast env params fn = MalFunc {fn=(Fn fn), ast=ast,
env=env, params=params,
macro=False, meta=Nil}
_malfunc_meta ast env params fn meta = MalFunc {fn=(Fn fn), ast=ast,
env=env, params=params,
macro=False, meta=meta}
-- Scalars
_nil_Q Nil = MalTrue
_nil_Q _ = MalFalse
_true_Q MalTrue = MalTrue
_true_Q _ = MalFalse
_false_Q MalFalse = MalTrue
_false_Q _ = MalFalse
_symbol_Q (MalSymbol _) = MalTrue
_symbol_Q _ = MalFalse
_string_Q (MalString ('\x029e':_)) = MalFalse
_string_Q (MalString _) = MalTrue
_string_Q _ = MalFalse
_keyword_Q (MalString ('\x029e':_)) = MalTrue
_keyword_Q _ = MalFalse
-- Lists
_list_Q (MalList _ _) = MalTrue
_list_Q _ = MalFalse
-- Vectors
_vector_Q (MalVector _ _) = MalTrue
_vector_Q _ = MalFalse
-- Hash Maps
_hash_map_Q (MalHashMap _ _) = MalTrue
_hash_map_Q _ = MalFalse
-- Atoms
_atom_Q (MalAtom _ _) = MalTrue
_atom_Q _ = MalFalse