forked from kanaka/mal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
core.vhdl
661 lines (594 loc) · 24.4 KB
/
core.vhdl
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
library STD;
use STD.textio.all;
library WORK;
use WORK.types.all;
use WORK.env.all;
use WORK.reader.all;
use WORK.printer.all;
use WORK.pkg_readline.all;
package core is
procedure eval_native_func(func_sym: inout mal_val_ptr; args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr);
procedure define_core_functions(e: inout env_ptr);
end package core;
package body core is
procedure fn_equal(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable is_equal: boolean;
begin
equal_q(args.seq_val(0), args.seq_val(1), is_equal);
new_boolean(is_equal, result);
end procedure fn_equal;
procedure fn_throw(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
err := args.seq_val(0);
end procedure fn_throw;
procedure fn_nil_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).val_type = mal_nil, result);
end procedure fn_nil_q;
procedure fn_true_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).val_type = mal_true, result);
end procedure fn_true_q;
procedure fn_false_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).val_type = mal_false, result);
end procedure fn_false_q;
procedure fn_string_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).val_type = mal_string, result);
end procedure fn_string_q;
procedure fn_symbol(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_symbol(args.seq_val(0).string_val, result);
end procedure fn_symbol;
procedure fn_symbol_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).val_type = mal_symbol, result);
end procedure fn_symbol_q;
procedure fn_keyword(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_keyword(args.seq_val(0).string_val, result);
end procedure fn_keyword;
procedure fn_keyword_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).val_type = mal_keyword, result);
end procedure fn_keyword_q;
procedure fn_pr_str(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable s: line;
begin
pr_seq("", "", " ", args.seq_val, true, s);
new_string(s, result);
end procedure fn_pr_str;
procedure fn_str(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable s: line;
begin
pr_seq("", "", "", args.seq_val, false, s);
new_string(s, result);
end procedure fn_str;
procedure fn_prn(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable s: line;
begin
pr_seq("", "", " ", args.seq_val, true, s);
mal_printline(s.all);
new_nil(result);
end procedure fn_prn;
procedure fn_println(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable s: line;
begin
pr_seq("", "", " ", args.seq_val, false, s);
mal_printline(s.all);
new_nil(result);
end procedure fn_println;
procedure fn_read_string(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable ast: mal_val_ptr;
begin
read_str(args.seq_val(0).string_val.all, ast, err);
if ast = null then
new_nil(result);
else
result := ast;
end if;
end procedure fn_read_string;
procedure fn_readline(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable input_line: line;
variable is_eof: boolean;
begin
mal_readline(args.seq_val(0).string_val.all, is_eof, input_line);
if is_eof then
new_nil(result);
else
new_string(input_line, result);
end if;
end procedure fn_readline;
procedure fn_slurp(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
file f: text;
variable status: file_open_status;
variable save_content, content, one_line: line;
begin
file_open(status, f, external_name => args.seq_val(0).string_val.all, open_kind => read_mode);
if status = open_ok then
content := new string'("");
while not endfile(f) loop
readline(f, one_line);
save_content := content;
content := new string'(save_content.all & one_line.all & LF);
deallocate(save_content);
end loop;
file_close(f);
new_string(content, result);
else
new_string("Error opening file", err);
end if;
end procedure fn_slurp;
procedure fn_lt(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).number_val < args.seq_val(1).number_val, result);
end procedure fn_lt;
procedure fn_lte(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).number_val <= args.seq_val(1).number_val, result);
end procedure fn_lte;
procedure fn_gt(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).number_val > args.seq_val(1).number_val, result);
end procedure fn_gt;
procedure fn_gte(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).number_val >= args.seq_val(1).number_val, result);
end procedure fn_gte;
procedure fn_add(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_number(args.seq_val(0).number_val + args.seq_val(1).number_val, result);
end procedure fn_add;
procedure fn_sub(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_number(args.seq_val(0).number_val - args.seq_val(1).number_val, result);
end procedure fn_sub;
procedure fn_mul(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_number(args.seq_val(0).number_val * args.seq_val(1).number_val, result);
end procedure fn_mul;
procedure fn_div(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_number(args.seq_val(0).number_val / args.seq_val(1).number_val, result);
end procedure fn_div;
-- Define physical types (c_seconds64, c_microseconds64) because these are
-- represented as 64-bit words when passed to C functions
type c_seconds64 is range 0 to 1E16
units
c_sec;
end units c_seconds64;
type c_microseconds64 is range 0 to 1E6
units
c_usec;
end units c_microseconds64;
type c_timeval is record
tv_sec: c_seconds64;
tv_usec: c_microseconds64;
end record c_timeval;
-- Leave enough room for two 64-bit words
type c_timezone is record
dummy_1: c_seconds64;
dummy_2: c_seconds64;
end record c_timezone;
function gettimeofday(tv: c_timeval; tz: c_timezone) return integer;
attribute foreign of gettimeofday: function is "VHPIDIRECT gettimeofday";
function gettimeofday(tv: c_timeval; tz: c_timezone) return integer is
begin
assert false severity failure;
end function gettimeofday;
-- Returns the number of milliseconds since 2000-01-01 00:00:00 UTC because
-- a standard VHDL integer is 32-bit and therefore cannot hold the number of
-- milliseconds since 1970-01-01.
procedure fn_time_ms(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable tv: c_timeval;
variable dummy: c_timezone;
variable rc: integer;
constant utc_2000_01_01: c_seconds64 := 946684800 c_sec; -- UNIX time at 2000-01-01 00:00:00 UTC
begin
rc := gettimeofday(tv, dummy);
new_number(((tv.tv_sec - utc_2000_01_01) / 1 c_sec) * 1000 + (tv.tv_usec / 1000 c_usec), result);
end procedure fn_time_ms;
procedure fn_list(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
result := args;
end procedure fn_list;
procedure fn_list_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).val_type = mal_list, result);
end procedure fn_list_q;
procedure fn_vector(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
args.val_type := mal_vector;
result := args;
end procedure fn_vector;
procedure fn_vector_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).val_type = mal_vector, result);
end procedure fn_vector_q;
procedure fn_hash_map(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
args.val_type := mal_hashmap;
result := args;
end procedure fn_hash_map;
procedure fn_map_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(args.seq_val(0).val_type = mal_hashmap, result);
end procedure fn_map_q;
procedure fn_assoc(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable new_hashmap: mal_val_ptr;
variable i: integer;
begin
hashmap_copy(args.seq_val(0), new_hashmap);
i := 1;
while i < args.seq_val'length loop
hashmap_put(new_hashmap, args.seq_val(i), args.seq_val(i + 1));
i := i + 2;
end loop;
result := new_hashmap;
end procedure fn_assoc;
procedure fn_dissoc(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable new_hashmap: mal_val_ptr;
variable i: integer;
begin
hashmap_copy(args.seq_val(0), new_hashmap);
for i in 1 to args.seq_val'high loop
hashmap_delete(new_hashmap, args.seq_val(i));
end loop;
result := new_hashmap;
end procedure fn_dissoc;
procedure fn_get(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
variable a1: mal_val_ptr := args.seq_val(1);
variable val: mal_val_ptr;
begin
if a0.val_type = mal_nil then
new_nil(result);
else
hashmap_get(a0, a1, val);
if val = null then
new_nil(result);
else
result := val;
end if;
end if;
end procedure fn_get;
procedure fn_contains_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
variable a1: mal_val_ptr := args.seq_val(1);
variable found: boolean;
begin
hashmap_contains(a0, a1, found);
new_boolean(found, result);
end procedure fn_contains_q;
procedure fn_keys(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
variable seq: mal_seq_ptr;
begin
seq := new mal_seq(0 to a0.seq_val'length / 2 - 1);
for i in seq'range loop
seq(i) := a0.seq_val(i * 2);
end loop;
new_seq_obj(mal_list, seq, result);
end procedure fn_keys;
procedure fn_vals(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
variable seq: mal_seq_ptr;
begin
seq := new mal_seq(0 to a0.seq_val'length / 2 - 1);
for i in seq'range loop
seq(i) := a0.seq_val(i * 2 + 1);
end loop;
new_seq_obj(mal_list, seq, result);
end procedure fn_vals;
procedure cons_helper(a0: inout mal_val_ptr; a1: inout mal_val_ptr; result: out mal_val_ptr) is
variable seq: mal_seq_ptr;
begin
seq := new mal_seq(0 to a1.seq_val'length);
seq(0) := a0;
seq(1 to seq'length - 1) := a1.seq_val(0 to a1.seq_val'length - 1);
new_seq_obj(mal_list, seq, result);
end procedure cons_helper;
procedure fn_cons(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
variable a1: mal_val_ptr := args.seq_val(1);
variable seq: mal_seq_ptr;
begin
cons_helper(a0, a1, result);
end procedure fn_cons;
procedure fn_sequential_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_boolean(is_sequential_type(args.seq_val(0).val_type), result);
end procedure fn_sequential_q;
procedure fn_concat(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable seq: mal_seq_ptr;
variable i: integer;
begin
seq := new mal_seq(0 to -1);
for i in args.seq_val'range loop
seq := new mal_seq'(seq.all & args.seq_val(i).seq_val.all);
end loop;
new_seq_obj(mal_list, seq, result);
end procedure fn_concat;
procedure fn_nth(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable lst_seq: mal_seq_ptr := args.seq_val(0).seq_val;
variable index: integer := args.seq_val(1).number_val;
begin
if index >= lst_seq'length then
new_string("nth: index out of range", err);
else
result := lst_seq(index);
end if;
end procedure fn_nth;
procedure fn_first(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
begin
if a0.val_type = mal_nil or a0.seq_val'length = 0 then
new_nil(result);
else
result := a0.seq_val(0);
end if;
end procedure fn_first;
procedure fn_rest(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
variable seq: mal_seq_ptr;
variable new_list: mal_val_ptr;
begin
if a0.val_type = mal_nil or a0.seq_val'length = 0 then
seq := new mal_seq(0 to -1);
new_seq_obj(mal_list, seq, result);
else
seq_drop_prefix(a0, 1, new_list);
new_list.val_type := mal_list;
result := new_list;
end if;
end procedure fn_rest;
procedure fn_empty_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable is_empty: boolean;
begin
case args.seq_val(0).val_type is
when mal_nil => new_boolean(true, result);
when mal_list | mal_vector => new_boolean(args.seq_val(0).seq_val'length = 0, result);
when others => new_string("empty?: invalid argument type", err);
end case;
end procedure fn_empty_q;
procedure fn_count(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable count: integer;
begin
case args.seq_val(0).val_type is
when mal_nil => new_number(0, result);
when mal_list | mal_vector => new_number(args.seq_val(0).seq_val'length, result);
when others => new_string("count: invalid argument type", err);
end case;
end procedure fn_count;
procedure fn_conj(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
variable r: mal_val_ptr;
variable seq: mal_seq_ptr;
begin
case a0.val_type is
when mal_list =>
r := a0;
for i in 1 to args.seq_val'high loop
cons_helper(args.seq_val(i), r, r);
end loop;
result := r;
when mal_vector =>
seq := new mal_seq(0 to a0.seq_val'length + args.seq_val'length - 2);
seq(0 to a0.seq_val'high) := a0.seq_val(a0.seq_val'range);
seq(a0.seq_val'high + 1 to seq'high) := args.seq_val(1 to args.seq_val'high);
new_seq_obj(mal_vector, seq, result);
when others =>
new_string("conj requires list or vector", err);
end case;
end procedure fn_conj;
procedure fn_seq(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
variable new_seq: mal_seq_ptr;
begin
case a0.val_type is
when mal_string =>
if a0.string_val'length = 0 then
new_nil(result);
else
new_seq := new mal_seq(0 to a0.string_val'length - 1);
for i in new_seq'range loop
new_string("" & a0.string_val(i + 1), new_seq(i));
end loop;
new_seq_obj(mal_list, new_seq, result);
end if;
when mal_list =>
if a0.seq_val'length = 0 then
new_nil(result);
else
result := a0;
end if;
when mal_vector =>
if a0.seq_val'length = 0 then
new_nil(result);
else
new_seq_obj(mal_list, a0.seq_val, result);
end if;
when mal_nil =>
new_nil(result);
when others =>
new_string("seq requires string or list or vector or nil", err);
end case;
end procedure fn_seq;
procedure fn_meta(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable meta_val: mal_val_ptr;
begin
meta_val := args.seq_val(0).meta_val;
if meta_val = null then
new_nil(result);
else
result := meta_val;
end if;
end procedure fn_meta;
procedure fn_with_meta(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
begin
result := new mal_val'(val_type => a0.val_type, number_val => a0.number_val, string_val => a0.string_val, seq_val => a0.seq_val, func_val => a0.func_val, meta_val => args.seq_val(1));
end procedure fn_with_meta;
procedure fn_atom(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
begin
new_atom(args.seq_val(0), result);
end procedure fn_atom;
procedure fn_atom_q(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
begin
new_boolean(a0.val_type = mal_atom, result);
end procedure fn_atom_q;
procedure fn_deref(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
begin
result := a0.seq_val(0);
end procedure fn_deref;
procedure fn_reset(args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable a0: mal_val_ptr := args.seq_val(0);
variable a1: mal_val_ptr := args.seq_val(1);
begin
a0.seq_val(0) := a1;
result := a1;
end procedure fn_reset;
procedure eval_native_func(func_sym: inout mal_val_ptr; args: inout mal_val_ptr; result: out mal_val_ptr; err: out mal_val_ptr) is
variable f: line;
begin
if func_sym.val_type /= mal_nativefn then
new_string("not a native function!", err);
return;
end if;
f := func_sym.string_val;
if f.all = "=" then fn_equal(args, result, err);
elsif f.all = "throw" then fn_throw(args, result, err);
elsif f.all = "nil?" then fn_nil_q(args, result, err);
elsif f.all = "true?" then fn_true_q(args, result, err);
elsif f.all = "false?" then fn_false_q(args, result, err);
elsif f.all = "string?" then fn_string_q(args, result, err);
elsif f.all = "symbol" then fn_symbol(args, result, err);
elsif f.all = "symbol?" then fn_symbol_q(args, result, err);
elsif f.all = "keyword" then fn_keyword(args, result, err);
elsif f.all = "keyword?" then fn_keyword_q(args, result, err);
elsif f.all = "pr-str" then fn_pr_str(args, result, err);
elsif f.all = "str" then fn_str(args, result, err);
elsif f.all = "prn" then fn_prn(args, result, err);
elsif f.all = "println" then fn_println(args, result, err);
elsif f.all = "read-string" then fn_read_string(args, result, err);
elsif f.all = "readline" then fn_readline(args, result, err);
elsif f.all = "slurp" then fn_slurp(args, result, err);
elsif f.all = "<" then fn_lt(args, result, err);
elsif f.all = "<=" then fn_lte(args, result, err);
elsif f.all = ">" then fn_gt(args, result, err);
elsif f.all = ">=" then fn_gte(args, result, err);
elsif f.all = "+" then fn_add(args, result, err);
elsif f.all = "-" then fn_sub(args, result, err);
elsif f.all = "*" then fn_mul(args, result, err);
elsif f.all = "/" then fn_div(args, result, err);
elsif f.all = "time-ms" then fn_time_ms(args, result, err);
elsif f.all = "list" then fn_list(args, result, err);
elsif f.all = "list?" then fn_list_q(args, result, err);
elsif f.all = "vector" then fn_vector(args, result, err);
elsif f.all = "vector?" then fn_vector_q(args, result, err);
elsif f.all = "hash-map" then fn_hash_map(args, result, err);
elsif f.all = "map?" then fn_map_q(args, result, err);
elsif f.all = "assoc" then fn_assoc(args, result, err);
elsif f.all = "dissoc" then fn_dissoc(args, result, err);
elsif f.all = "get" then fn_get(args, result, err);
elsif f.all = "contains?" then fn_contains_q(args, result, err);
elsif f.all = "keys" then fn_keys(args, result, err);
elsif f.all = "vals" then fn_vals(args, result, err);
elsif f.all = "sequential?" then fn_sequential_q(args, result, err);
elsif f.all = "cons" then fn_cons(args, result, err);
elsif f.all = "concat" then fn_concat(args, result, err);
elsif f.all = "nth" then fn_nth(args, result, err);
elsif f.all = "first" then fn_first(args, result, err);
elsif f.all = "rest" then fn_rest(args, result, err);
elsif f.all = "empty?" then fn_empty_q(args, result, err);
elsif f.all = "count" then fn_count(args, result, err);
elsif f.all = "conj" then fn_conj(args, result, err);
elsif f.all = "seq" then fn_seq(args, result, err);
elsif f.all = "meta" then fn_meta(args, result, err);
elsif f.all = "with-meta" then fn_with_meta(args, result, err);
elsif f.all = "atom" then fn_atom(args, result, err);
elsif f.all = "atom?" then fn_atom_q(args, result, err);
elsif f.all = "deref" then fn_deref(args, result, err);
elsif f.all = "reset!" then fn_reset(args, result, err);
else
result := null;
end if;
end procedure eval_native_func;
procedure define_core_function(e: inout env_ptr; func_name: in string) is
variable sym: mal_val_ptr;
variable fn: mal_val_ptr;
begin
new_symbol(func_name, sym);
new_nativefn(func_name, fn);
env_set(e, sym, fn);
end procedure define_core_function;
procedure define_core_functions(e: inout env_ptr) is
variable is_eof: boolean;
variable input_line, result, err: line;
variable sym: mal_val_ptr;
variable fn: mal_val_ptr;
variable outer: env_ptr;
variable repl_env: env_ptr;
begin
define_core_function(e, "=");
define_core_function(e, "throw");
define_core_function(e, "nil?");
define_core_function(e, "true?");
define_core_function(e, "false?");
define_core_function(e, "string?");
define_core_function(e, "symbol");
define_core_function(e, "symbol?");
define_core_function(e, "keyword");
define_core_function(e, "keyword?");
define_core_function(e, "pr-str");
define_core_function(e, "str");
define_core_function(e, "prn");
define_core_function(e, "println");
define_core_function(e, "read-string");
define_core_function(e, "readline");
define_core_function(e, "slurp");
define_core_function(e, "<");
define_core_function(e, "<=");
define_core_function(e, ">");
define_core_function(e, ">=");
define_core_function(e, "+");
define_core_function(e, "-");
define_core_function(e, "*");
define_core_function(e, "/");
define_core_function(e, "time-ms");
define_core_function(e, "list");
define_core_function(e, "list?");
define_core_function(e, "vector");
define_core_function(e, "vector?");
define_core_function(e, "hash-map");
define_core_function(e, "map?");
define_core_function(e, "assoc");
define_core_function(e, "dissoc");
define_core_function(e, "get");
define_core_function(e, "contains?");
define_core_function(e, "keys");
define_core_function(e, "vals");
define_core_function(e, "sequential?");
define_core_function(e, "cons");
define_core_function(e, "concat");
define_core_function(e, "nth");
define_core_function(e, "first");
define_core_function(e, "rest");
define_core_function(e, "empty?");
define_core_function(e, "count");
define_core_function(e, "apply"); -- implemented in the stepN_XXX files
define_core_function(e, "map"); -- implemented in the stepN_XXX files
define_core_function(e, "conj");
define_core_function(e, "seq");
define_core_function(e, "meta");
define_core_function(e, "with-meta");
define_core_function(e, "atom");
define_core_function(e, "atom?");
define_core_function(e, "deref");
define_core_function(e, "reset!");
define_core_function(e, "swap!"); -- implemented in the stepN_XXX files
end procedure define_core_functions;
end package body core;