Haskell: add error handling and try*/catch*.
[jackhill/mal.git] / haskell / Types.hs
CommitLineData
b76aa73b 1module Types
5400d4bf
JM
2(MalVal (..), MalError (..), IOThrows (..), Fn (..), EnvData (..), Env,
3 throwStr, throwMalVal, _get_call, _to_list,
4 _func, _malfunc,
c150ec41
JM
5 _nil_Q, _true_Q, _false_Q, _symbol_Q, _keyword_Q,
6 _list_Q, _vector_Q, _hash_map_Q, _atom_Q)
b76aa73b
JM
7where
8
fa9a9758 9import Data.IORef (IORef)
b76aa73b 10import qualified Data.Map as Map
fa9a9758 11import Control.Exception as CE
5400d4bf 12import Control.Monad.Error (ErrorT, Error, noMsg, strMsg, throwError)
b76aa73b 13
fa9a9758
JM
14
15-- Base Mal types --
5400d4bf 16newtype Fn = Fn ([MalVal] -> IOThrows MalVal)
b76aa73b
JM
17data MalVal = Nil
18 | MalFalse
19 | MalTrue
20 | MalNumber Int
21 | MalString String
22 | MalSymbol String
c150ec41
JM
23 | MalList [MalVal] MalVal
24 | MalVector [MalVal] MalVal
25 | MalHashMap (Map.Map String MalVal) MalVal
26 | MalAtom (IORef MalVal) MalVal
27 | Func Fn MalVal
28 | MalFunc {fn :: Fn,
29 ast :: MalVal,
30 env :: Env,
31 params :: MalVal,
32 macro :: Bool,
33 meta :: MalVal}
fa9a9758
JM
34
35_equal_Q Nil Nil = True
36_equal_Q MalFalse MalFalse = True
37_equal_Q MalTrue MalTrue = True
38_equal_Q (MalNumber a) (MalNumber b) = a == b
39_equal_Q (MalString a) (MalString b) = a == b
40_equal_Q (MalSymbol a) (MalSymbol b) = a == b
c150ec41
JM
41_equal_Q (MalList a _) (MalList b _) = a == b
42_equal_Q (MalList a _) (MalVector b _) = a == b
43_equal_Q (MalVector a _) (MalList b _) = a == b
44_equal_Q (MalHashMap a _) (MalHashMap b _) = a == b
45_equal_Q (MalAtom a _) (MalAtom b _) = a == b
fa9a9758 46_equal_Q _ _ = False
b76aa73b 47
fa9a9758
JM
48instance Eq MalVal where
49 x == y = _equal_Q x y
b76aa73b 50
b76aa73b 51
5400d4bf
JM
52--- Errors/Exceptions ---
53
54data MalError = StringError String
55 | MalValError MalVal
56
57type IOThrows = ErrorT MalError IO
58
59instance Error MalError where
60 noMsg = StringError "An error has occurred"
61 strMsg = StringError
62
63throwStr str = throwError $ StringError str
64throwMalVal mv = throwError $ MalValError mv
65
fa9a9758
JM
66-- Env types --
67-- Note: Env functions are in Env module
68data EnvData = EnvPair (Maybe Env, (Map.Map String MalVal))
69type Env = IORef EnvData
b76aa73b 70
b76aa73b
JM
71
72
73----------------------------------------------------------
74
fa9a9758 75-- General functions --
b76aa73b 76
c150ec41
JM
77_get_call ((Func (Fn f) _) : _) = return f
78_get_call (MalFunc {fn=(Fn f)} : _) = return f
5400d4bf 79_get_call _ = throwStr "_get_call first parameter is not a function "
c150ec41
JM
80
81_to_list (MalList lst _) = return lst
82_to_list (MalVector lst _) = return lst
5400d4bf 83_to_list _ = throwStr "_to_list expected a MalList or MalVector"
fa9a9758
JM
84
85-- Errors
86
5400d4bf
JM
87--catchAny :: IO a -> (CE.SomeException -> IO a) -> IO a
88--catchAny = CE.catch
fa9a9758
JM
89
90-- Functions
91
c150ec41
JM
92_func fn = Func (Fn fn) Nil
93_func_meta fn meta = Func (Fn fn) meta
94
fa9a9758 95_malfunc ast env params fn = MalFunc {fn=(Fn fn), ast=ast,
2988d38e 96 env=env, params=params,
c150ec41
JM
97 macro=False, meta=Nil}
98_malfunc_meta ast env params fn meta = MalFunc {fn=(Fn fn), ast=ast,
99 env=env, params=params,
100 macro=False, meta=meta}
101
102-- Scalars
103_nil_Q Nil = MalTrue
104_nil_Q _ = MalFalse
105
106_true_Q MalTrue = MalTrue
107_true_Q _ = MalFalse
108
109_false_Q MalFalse = MalTrue
110_false_Q _ = MalFalse
111
112_symbol_Q (MalSymbol _) = MalTrue
113_symbol_Q _ = MalFalse
114
115_keyword_Q (MalString ('\x029e':_)) = MalTrue
116_keyword_Q _ = MalFalse
fa9a9758
JM
117
118-- Lists
119
c150ec41
JM
120_list_Q (MalList _ _) = MalTrue
121_list_Q _ = MalFalse
fa9a9758
JM
122
123-- Vectors
124
c150ec41
JM
125_vector_Q (MalVector _ _) = MalTrue
126_vector_Q _ = MalFalse
fa9a9758
JM
127
128-- Hash Maps
129
c150ec41
JM
130_hash_map_Q (MalHashMap _ _) = MalTrue
131_hash_map_Q _ = MalFalse
132
133-- Atoms
fa9a9758 134
c150ec41
JM
135_atom_Q (MalAtom _ _) = MalTrue
136_atom_Q _ = MalFalse