DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / pike / Types.pmod
1 enum MalType {
2 MALTYPE_UNDEFINED,
3 MALTYPE_NIL,
4 MALTYPE_TRUE,
5 MALTYPE_FALSE,
6 MALTYPE_NUMBER,
7 MALTYPE_SYMBOL,
8 MALTYPE_STRING,
9 MALTYPE_KEYWORD,
10 MALTYPE_LIST,
11 MALTYPE_VECTOR,
12 MALTYPE_MAP,
13 MALTYPE_FN,
14 MALTYPE_BUILTINFN,
15 MALTYPE_ATOM,
16 };
17
18 class Val
19 {
20 constant mal_type = MALTYPE_UNDEFINED;
21 Val meta;
22 string to_string(bool print_readably);
23 Val clone();
24
25 bool `==(mixed other)
26 {
27 return objectp(other) && other.mal_type == mal_type;
28 }
29 }
30
31 class Nil
32 {
33 inherit Val;
34 constant mal_type = MALTYPE_NIL;
35
36 string to_string(bool print_readably)
37 {
38 return "nil";
39 }
40
41 int count()
42 {
43 return 0;
44 }
45
46 Val first()
47 {
48 return MAL_NIL;
49 }
50
51 Val rest()
52 {
53 return List(({ }));
54 }
55
56 Val clone()
57 {
58 return this_object();
59 }
60
61 Val seq()
62 {
63 return MAL_NIL;
64 }
65 }
66
67 Nil MAL_NIL = Nil();
68
69 class True
70 {
71 inherit Val;
72 constant mal_type = MALTYPE_TRUE;
73 string to_string(bool print_readably)
74 {
75 return "true";
76 }
77
78 Val clone()
79 {
80 return this_object();
81 }
82 }
83
84 True MAL_TRUE = True();
85
86 class False
87 {
88 inherit Val;
89 constant mal_type = MALTYPE_FALSE;
90 string to_string(bool print_readably)
91 {
92 return "false";
93 }
94
95 Val clone()
96 {
97 return this_object();
98 }
99 }
100
101 False MAL_FALSE = False();
102
103 Val to_bool(bool b)
104 {
105 if(b) return MAL_TRUE;
106 return MAL_FALSE;
107 }
108
109 class Number(int value)
110 {
111 constant mal_type = MALTYPE_NUMBER;
112 inherit Val;
113
114 string to_string(bool print_readably)
115 {
116 return (string)value;
117 }
118
119 bool `==(mixed other)
120 {
121 return ::`==(other) && other.value == value;
122 }
123
124 Val clone()
125 {
126 return this_object();
127 }
128 }
129
130 class Symbol(string value)
131 {
132 constant mal_type = MALTYPE_SYMBOL;
133 inherit Val;
134
135 string to_string(bool print_readably)
136 {
137 return value;
138 }
139
140 bool `==(mixed other)
141 {
142 return ::`==(other) && other.value == value;
143 }
144
145 int __hash()
146 {
147 return hash((string)mal_type) ^ hash(value);
148 }
149
150 Val clone()
151 {
152 return Symbol(value);
153 }
154 }
155
156 class String(string value)
157 {
158 constant mal_type = MALTYPE_STRING;
159 inherit Val;
160
161 string to_string(bool print_readably)
162 {
163 if(print_readably) {
164 string s = replace(value, "\\", "\\\\");
165 s = replace(s, "\"", "\\\"");
166 s = replace(s, "\n", "\\n");
167 return "\"" + s + "\"";
168 }
169 return value;
170 }
171
172 bool `==(mixed other)
173 {
174 return ::`==(other) && other.value == value;
175 }
176
177 int __hash()
178 {
179 return hash((string)mal_type) ^ hash(value);
180 }
181
182 Val clone()
183 {
184 return String(value);
185 }
186
187 Val seq()
188 {
189 if(sizeof(value) == 0) return MAL_NIL;
190 array(Val) parts = ({ });
191 for(int i = 0; i < sizeof(value); i++)
192 {
193 parts += ({ String(value[i..i]) });
194 }
195 return List(parts);
196 }
197 }
198
199 class Keyword(string value)
200 {
201 constant mal_type = MALTYPE_KEYWORD;
202 inherit Val;
203
204 string to_string(bool print_readably)
205 {
206 return ":" + value;
207 }
208
209 bool `==(mixed other)
210 {
211 return ::`==(other) && other.value == value;
212 }
213
214 int __hash()
215 {
216 return hash((string)mal_type) ^ hash(value);
217 }
218
219 Val clone()
220 {
221 return Keyword(value);
222 }
223 }
224
225 class Sequence(array(Val) data)
226 {
227 inherit Val;
228 constant is_sequence = true;
229
230 string to_string(bool print_readably)
231 {
232 return map(data, lambda(Val e) { return e.to_string(print_readably); }) * " ";
233 }
234
235 bool emptyp()
236 {
237 return sizeof(data) == 0;
238 }
239
240 int count()
241 {
242 return sizeof(data);
243 }
244
245 Val nth(int index)
246 {
247 if(index >= count()) throw("nth: index out of range");
248 return data[index];
249 }
250
251 Val first()
252 {
253 if(emptyp()) return MAL_NIL;
254 return data[0];
255 }
256
257 Val rest()
258 {
259 return List(data[1..]);
260 }
261
262 bool `==(mixed other)
263 {
264 if(!objectp(other)) return 0;
265 if(!other.is_sequence) return 0;
266 if(other.count() != count()) return 0;
267 for(int i = 0; i < count(); i++)
268 {
269 if(other.data[i] != data[i]) return 0;
270 }
271 return 1;
272 }
273
274 Val seq()
275 {
276 if(emptyp()) return MAL_NIL;
277 return List(data);
278 }
279 }
280
281 class List
282 {
283 inherit Sequence;
284 constant mal_type = MALTYPE_LIST;
285
286 string to_string(bool print_readably)
287 {
288 return "(" + ::to_string(print_readably) + ")";
289 }
290
291 Val clone()
292 {
293 return List(data);
294 }
295
296 Val conj(array(Val) other)
297 {
298 return List(reverse(other) + data);
299 }
300 }
301
302 class Vector
303 {
304 inherit Sequence;
305 constant mal_type = MALTYPE_VECTOR;
306
307 string to_string(bool print_readably)
308 {
309 return "[" + ::to_string(print_readably) + "]";
310 }
311
312 Val clone()
313 {
314 return Vector(data);
315 }
316
317 Val conj(array(Val) other)
318 {
319 return Vector(data + other);
320 }
321 }
322
323 class Map
324 {
325 inherit Val;
326 constant mal_type = MALTYPE_MAP;
327 mapping(Val:Val) data;
328
329 void create(array(Val) list)
330 {
331 array(Val) keys = Array.everynth(list, 2, 0);
332 array(Val) vals = Array.everynth(list, 2, 1);
333 data = mkmapping(keys, vals);
334 }
335
336 string to_string(bool print_readably)
337 {
338 array(string) strs = ({ });
339 foreach(data; Val k; Val v)
340 {
341 strs += ({ k.to_string(print_readably), v.to_string(print_readably) });
342 }
343 return "{" + (strs * " ") + "}";
344 }
345
346 int count()
347 {
348 return sizeof(data);
349 }
350
351 bool `==(mixed other)
352 {
353 if(!::`==(other)) return 0;
354 if(other.count() != count()) return 0;
355 foreach(data; Val k; Val v)
356 {
357 if(other.data[k] != v) return 0;
358 }
359 return 1;
360 }
361
362 Val assoc(array(Val) list)
363 {
364 array(Val) keys = Array.everynth(list, 2, 0);
365 array(Val) vals = Array.everynth(list, 2, 1);
366 Map result = Map(({ }));
367 result.data = copy_value(data);
368 for(int i = 0; i < sizeof(keys); i++)
369 {
370 result.data[keys[i]] = vals[i];
371 }
372 return result;
373 }
374
375 Val dissoc(array(Val) list)
376 {
377 Map result = Map(({ }));
378 result.data = copy_value(data);
379 foreach(list, Val key) m_delete(result.data, key);
380 return result;
381 }
382
383 Val clone()
384 {
385 Map m = Map(({ }));
386 m.data = data;
387 return m;
388 }
389 }
390
391 class Fn(Val ast, Val params, .Env.Env env, function func, void|bool macro)
392 {
393 inherit Val;
394 constant mal_type = MALTYPE_FN;
395 constant is_fn = true;
396
397 void set_macro()
398 {
399 macro = true;
400 }
401
402 string to_string(bool print_readably)
403 {
404 string tag = macro ? "Macro" : "Fn";
405 return "#<" + tag + " params=" + params.to_string(true) + ">";
406 }
407
408 mixed `()(mixed ... args)
409 {
410 return func(@args);
411 }
412
413 Val clone()
414 {
415 return Fn(ast, params, env, func);
416 }
417
418 Val clone_as_macro()
419 {
420 return Fn(ast, params, env, func, true);
421 }
422 }
423
424 class BuiltinFn(string name, function func)
425 {
426 inherit Val;
427 constant mal_type = MALTYPE_BUILTINFN;
428 constant is_fn = true;
429
430 string to_string(bool print_readably)
431 {
432 return "#<BuiltinFn " + name + ">";
433 }
434
435 mixed `()(mixed ... args)
436 {
437 return func(@args);
438 }
439
440 Val clone()
441 {
442 return BuiltinFn(name, func);
443 }
444 }
445
446 class Atom(Val data)
447 {
448 inherit Val;
449 constant mal_type = MALTYPE_ATOM;
450
451 string to_string(bool print_readably)
452 {
453 return "(atom " + data.to_string(print_readably) + ")";
454 }
455
456 Val clone()
457 {
458 return Atom(data);
459 }
460 }