fez-lisp 1.6.27 → 1.6.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1191 @@
1
+ import stdT from '../lib/baked/std-T.js'
2
+ import std from '../lib/baked/std.js'
3
+ import { typeCheck } from './check.js'
4
+ import { enhance } from './enhance.js'
5
+ import {
6
+ APPLY,
7
+ ATOM,
8
+ KEYWORDS,
9
+ TYPE,
10
+ VALUE,
11
+ WORD,
12
+ TRUE,
13
+ FALSE,
14
+ STATIC_TYPES,
15
+ DEBUG,
16
+ SPECIAL_FORMS_SET
17
+ } from './keywords.js'
18
+ import { isLeaf, LISP } from './parser.js'
19
+ import { definedTypes, filteredDefinedTypes, withCtxTypes } from './types.js'
20
+ import { isForbiddenVariableName } from './utils.js'
21
+ const keywords = {
22
+ [KEYWORDS.LOOP]: (args, env) => {
23
+ if (args.length != 2)
24
+ throw new RangeError(`Wrong number of args to ${KEYWORDS.LOOP}`)
25
+ while (evaluate(args[0], env) === TRUE) evaluate(args[1], env)
26
+ return -1
27
+ },
28
+ [KEYWORDS.ADDITION]: (args, env) => {
29
+ if (args.length !== 2)
30
+ throw new RangeError(
31
+ `Invalid number of arguments for (${
32
+ KEYWORDS.ADDITION
33
+ }), expected (= 2) but got ${args.length}\n\n(${
34
+ KEYWORDS.ADDITION
35
+ } ${stringifyArgs(args)})`
36
+ )
37
+ const a = evaluate(args[0], env)
38
+ if (typeof a !== 'number')
39
+ throw new TypeError(
40
+ `First arguments of (${KEYWORDS.ADDITION}) must be a (${
41
+ RUNTIME_TYPES.NUMBER
42
+ }) but ${LISP.source(args[0])} is not\n\n(${
43
+ KEYWORDS.ADDITION
44
+ } ${stringifyArgs(args)})`
45
+ )
46
+ const b = evaluate(args[1], env)
47
+ if (typeof b !== 'number')
48
+ throw new TypeError(
49
+ `Second arguments of (${KEYWORDS.ADDITION}) must be a (${
50
+ RUNTIME_TYPES.NUMBER
51
+ }) but ${LISP.source(args[1])} is not\n\n(${
52
+ KEYWORDS.ADDITION
53
+ } ${stringifyArgs(args)})`
54
+ )
55
+ return a + b
56
+ },
57
+ [KEYWORDS.MULTIPLICATION]: (args, env) => {
58
+ if (args.length !== 2)
59
+ throw new RangeError(
60
+ `Invalid number of arguments for (${
61
+ KEYWORDS.MULTIPLICATION
62
+ }), expected (= 2) but got ${args.length}\n\n(${
63
+ KEYWORDS.MULTIPLICATION
64
+ } ${stringifyArgs(args)})`
65
+ )
66
+ const a = evaluate(args[0], env)
67
+ if (typeof a !== 'number')
68
+ throw new TypeError(
69
+ `First arguments of (${KEYWORDS.MULTIPLICATION}) must be a (${
70
+ RUNTIME_TYPES.NUMBER
71
+ }) but ${LISP.source(args[0])} is not\n\n(${
72
+ KEYWORDS.MULTIPLICATION
73
+ } ${stringifyArgs(args)})`
74
+ )
75
+ const b = evaluate(args[1], env)
76
+ if (typeof b !== 'number')
77
+ throw new TypeError(
78
+ `Second arguments of (${KEYWORDS.MULTIPLICATION}) must be a (${
79
+ RUNTIME_TYPES.NUMBER
80
+ }) but ${LISP.source(args[1])} is not\n\n(${
81
+ KEYWORDS.MULTIPLICATION
82
+ } ${stringifyArgs(args)})`
83
+ )
84
+ return a * b
85
+ },
86
+ [KEYWORDS.SUBTRACTION]: (args, env) => {
87
+ if (args.length !== 2)
88
+ throw new RangeError(
89
+ `Invalid number of arguments for (${
90
+ KEYWORDS.SUBTRACTION
91
+ }), expected (= 2) but got ${args.length}\n\n(${
92
+ KEYWORDS.SUBTRACTION
93
+ } ${stringifyArgs(args)})`
94
+ )
95
+ const a = evaluate(args[0], env)
96
+ if (typeof a !== 'number')
97
+ throw new TypeError(
98
+ `First argument of (${KEYWORDS.SUBTRACTION}) must be a (${
99
+ RUNTIME_TYPES.NUMBER
100
+ }) but ${LISP.source(args[0])} is not\n\n(${
101
+ KEYWORDS.SUBTRACTION
102
+ } ${stringifyArgs(args)})`
103
+ )
104
+ const b = evaluate(args[1], env)
105
+ if (typeof b !== 'number')
106
+ throw new TypeError(
107
+ `Second argument of (${KEYWORDS.SUBTRACTION}) must be a (${
108
+ RUNTIME_TYPES.NUMBER
109
+ }) but ${LISP.source(args[1])} is not\n\n(${
110
+ KEYWORDS.SUBTRACTION
111
+ } ${stringifyArgs(args)})`
112
+ )
113
+ return a - b
114
+ },
115
+ [KEYWORDS.DIVISION]: (args, env) => {
116
+ if (args.length !== 2)
117
+ throw new RangeError(
118
+ `Invalid number of arguments for (${
119
+ KEYWORDS.DIVISION
120
+ }), expected (= 2) but got ${args.length}\n\n(${
121
+ KEYWORDS.DIVISION
122
+ } ${stringifyArgs(args)})`
123
+ )
124
+ const a = evaluate(args[0], env)
125
+ if (typeof a !== 'number')
126
+ throw new TypeError(
127
+ `First argument of (${KEYWORDS.DIVISION}) is not (${
128
+ RUNTIME_TYPES.NUMBER
129
+ }) but ${LISP.source(args[0])} is not\n\n(${
130
+ KEYWORDS.DIVISION
131
+ } ${stringifyArgs(args)})`
132
+ )
133
+ const b = evaluate(args[1], env)
134
+ if (typeof b !== 'number')
135
+ throw new TypeError(
136
+ `Second argument of (${KEYWORDS.DIVISION}) is not (${
137
+ RUNTIME_TYPES.NUMBER
138
+ }) but ${LISP.source(args[1])} is not\n\n(${
139
+ KEYWORDS.DIVISION
140
+ } ${stringifyArgs(args)})`
141
+ )
142
+ if (b === 0)
143
+ throw new TypeError(
144
+ `Second Argument of (${
145
+ KEYWORDS.DIVISION
146
+ }) can't be a 0 (division by 0 is not allowed) but ${LISP.source(
147
+ args[1]
148
+ )} is 0\n\n(${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
149
+ )
150
+ return a / b
151
+ },
152
+ [KEYWORDS.REMAINDER_OF_DIVISION]: (args, env) => {
153
+ if (args.length !== 2)
154
+ throw new RangeError(
155
+ `Invalid number of arguments for (${
156
+ KEYWORDS.REMAINDER_OF_DIVISION
157
+ }), expected (= 2) but got ${args.length}\n\n(${
158
+ KEYWORDS.REMAINDER_OF_DIVISION
159
+ } ${stringifyArgs(args)})`
160
+ )
161
+ const a = evaluate(args[0], env)
162
+ if (typeof a !== 'number')
163
+ throw new TypeError(
164
+ `First argument of (${KEYWORDS.REMAINDER_OF_DIVISION}) is not (${
165
+ RUNTIME_TYPES.NUMBER
166
+ }) but ${LISP.source(args[0])} is not\n\n(${
167
+ KEYWORDS.REMAINDER_OF_DIVISION
168
+ } ${stringifyArgs(args)})`
169
+ )
170
+ const b = evaluate(args[1], env)
171
+ if (typeof b !== 'number')
172
+ throw new TypeError(
173
+ `Second argument of (${KEYWORDS.REMAINDER_OF_DIVISION}) is not (${
174
+ RUNTIME_TYPES.NUMBER
175
+ }) but ${LISP.source(args[1])} is not\n\n(${
176
+ KEYWORDS.REMAINDER_OF_DIVISION
177
+ } ${stringifyArgs(args)})`
178
+ )
179
+ if (b === 0)
180
+ throw new TypeError(
181
+ `Second argument of (${
182
+ KEYWORDS.REMAINDER_OF_DIVISION
183
+ }) can't be a 0 (division by 0 is not allowed) but ${LISP.source(
184
+ args[1]
185
+ )} is 0\n\n(${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)})`
186
+ )
187
+
188
+ return a % b
189
+ },
190
+ [KEYWORDS.BITWISE_AND]: (args, env) => {
191
+ if (args.length !== 2)
192
+ throw new RangeError(
193
+ `Invalid number of arguments to (${
194
+ KEYWORDS.BITWISE_AND
195
+ }) (= 2 required)\n\n(${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
196
+ )
197
+ const a = evaluate(args[0], env)
198
+ if (typeof a !== 'number')
199
+ throw new TypeError(
200
+ `First arguments of (${KEYWORDS.BITWISE_AND}) must be a (${
201
+ RUNTIME_TYPES.NUMBER
202
+ }) but ${LISP.source(args[0])} is not\n\n(${
203
+ KEYWORDS.BITWISE_AND
204
+ } ${stringifyArgs(args)})`
205
+ )
206
+ const b = evaluate(args[1], env)
207
+ if (typeof b !== 'number')
208
+ throw new TypeError(
209
+ `Second arguments of (${KEYWORDS.BITWISE_AND}) must be a (${
210
+ RUNTIME_TYPES.NUMBER
211
+ }) but ${LISP.source(args[1])} is not\n\n(${
212
+ KEYWORDS.BITWISE_AND
213
+ } ${stringifyArgs(args)})`
214
+ )
215
+ return a & b
216
+ },
217
+ [KEYWORDS.BITWISE_NOT]: (args, env) => {
218
+ if (args.length !== 1)
219
+ throw new RangeError(
220
+ `Invalid number of arguments to (${
221
+ KEYWORDS.BITWISE_NOT
222
+ }) (= 1 required)\n\n(${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)})`
223
+ )
224
+ const operand = evaluate(args[0], env)
225
+ if (typeof operand !== 'number')
226
+ throw new TypeError(
227
+ `Argument of (${KEYWORDS.BITWISE_NOT}) must be a (${
228
+ RUNTIME_TYPES.NUMBER
229
+ }) but ${LISP.source(args[0])} is not\n\n(${
230
+ KEYWORDS.BITWISE_NOT
231
+ } ${stringifyArgs(args)})`
232
+ )
233
+ return ~operand
234
+ },
235
+ [KEYWORDS.BITWISE_OR]: (args, env) => {
236
+ if (args.length !== 2)
237
+ throw new RangeError(
238
+ `Invalid number of arguments to (${
239
+ KEYWORDS.BITWISE_OR
240
+ }) (= 2 required)\n\n(${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)})`
241
+ )
242
+ const a = evaluate(args[0], env)
243
+ if (typeof a !== 'number')
244
+ throw new TypeError(
245
+ `First arguments of (${KEYWORDS.BITWISE_OR}) must be a (${
246
+ RUNTIME_TYPES.NUMBER
247
+ }) but ${LISP.source(args[0])} is not\n\n(${
248
+ KEYWORDS.BITWISE_OR
249
+ } ${stringifyArgs(args)})`
250
+ )
251
+ const b = evaluate(args[1], env)
252
+ if (typeof b !== 'number')
253
+ throw new TypeError(
254
+ `Second arguments of (${KEYWORDS.BITWISE_OR}) must be a (${
255
+ RUNTIME_TYPES.NUMBER
256
+ }) but ${LISP.source(args[1])} is not\n\n(${
257
+ KEYWORDS.BITWISE_OR
258
+ } ${stringifyArgs(args)})`
259
+ )
260
+ return a | b
261
+ },
262
+ [KEYWORDS.BITWISE_XOR]: (args, env) => {
263
+ if (args.length !== 2)
264
+ throw new RangeError(
265
+ `Invalid number of arguments to (${
266
+ KEYWORDS.BITWISE_XOR
267
+ }) (= 2 required)\n\n(${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
268
+ )
269
+ const a = evaluate(args[0], env)
270
+ if (typeof a !== 'number')
271
+ throw new TypeError(
272
+ `First arguments of (${KEYWORDS.BITWISE_XOR}) must be a (${
273
+ RUNTIME_TYPES.NUMBER
274
+ }) but ${LISP.source(args[0])} is not\n\n(${
275
+ KEYWORDS.BITWISE_XOR
276
+ } ${stringifyArgs(args)})`
277
+ )
278
+ const b = evaluate(args[1], env)
279
+ if (typeof b !== 'number')
280
+ throw new TypeError(
281
+ `Second arguments of (${KEYWORDS.BITWISE_XOR}) must be a (${
282
+ RUNTIME_TYPES.NUMBER
283
+ }) but ${LISP.source(args[1])} is not\n\n(${
284
+ KEYWORDS.BITWISE_XOR
285
+ } ${stringifyArgs(args)})`
286
+ )
287
+ return a ^ b
288
+ },
289
+ [KEYWORDS.BITWISE_LEFT_SHIFT]: (args, env) => {
290
+ if (args.length !== 2)
291
+ throw new RangeError(
292
+ `Invalid number of arguments to (${
293
+ KEYWORDS.BITWISE_LEFT_SHIFT
294
+ }) (= 2 required)\n\n(${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(
295
+ args
296
+ )})`
297
+ )
298
+ const a = evaluate(args[0], env)
299
+ if (typeof a !== 'number')
300
+ throw new TypeError(
301
+ `First arguments of (${KEYWORDS.BITWISE_LEFT_SHIFT}) must be a (${
302
+ RUNTIME_TYPES.NUMBER
303
+ }) but ${LISP.source(args[0])} is not\n\n(${
304
+ KEYWORDS.BITWISE_LEFT_SHIFT
305
+ } ${stringifyArgs(args)})`
306
+ )
307
+ const b = evaluate(args[1], env)
308
+ if (typeof b !== 'number')
309
+ throw new TypeError(
310
+ `Second arguments of (${KEYWORDS.BITWISE_LEFT_SHIFT}) must be a (${
311
+ RUNTIME_TYPES.NUMBER
312
+ }) but ${LISP.source(args[1])} is not\n\n(${
313
+ KEYWORDS.BITWISE_LEFT_SHIFT
314
+ } ${stringifyArgs(args)})`
315
+ )
316
+ return a << b
317
+ },
318
+ [KEYWORDS.BITWISE_RIGHT_SHIFT]: (args, env) => {
319
+ if (args.length !== 2)
320
+ throw new RangeError(
321
+ `Invalid number of arguments to (${
322
+ KEYWORDS.BITWISE_RIGHT_SHIFT
323
+ }) (= 2 required)\n\n(${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(
324
+ args
325
+ )})`
326
+ )
327
+ const a = evaluate(args[0], env)
328
+ if (typeof a !== 'number')
329
+ throw new TypeError(
330
+ `First arguments of (${KEYWORDS.BITWISE_RIGHT_SHIFT}) must be a (${
331
+ RUNTIME_TYPES.NUMBER
332
+ }) but ${LISP.source(args[0])} is not\n\n(${
333
+ KEYWORDS.BITWISE_RIGHT_SHIFT
334
+ } ${stringifyArgs(args)})`
335
+ )
336
+ const b = evaluate(args[1], env)
337
+ if (typeof b !== 'number')
338
+ throw new TypeError(
339
+ `Second arguments of (${KEYWORDS.BITWISE_RIGHT_SHIFT}) must be a (${
340
+ RUNTIME_TYPES.NUMBER
341
+ }) but ${LISP.source(args[1])} is not\n\n(${
342
+ KEYWORDS.BITWISE_RIGHT_SHIFT
343
+ } ${stringifyArgs(args)})`
344
+ )
345
+ return a >> b
346
+ },
347
+ [KEYWORDS.CREATE_ARRAY]: (args, env) => {
348
+ return args.length ? args.map((x) => evaluate(x, env)) : []
349
+ },
350
+ [KEYWORDS.GET_ARRAY]: (args, env) => {
351
+ if (args.length !== 2)
352
+ throw new RangeError(
353
+ `Invalid number of arguments for (${
354
+ KEYWORDS.GET_ARRAY
355
+ }) (= 2 required)\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
356
+ )
357
+ const array = evaluate(args[0], env)
358
+ if (!Array.isArray(array))
359
+ throw new TypeError(
360
+ `First argument of (${KEYWORDS.GET_ARRAY}) must be an (${
361
+ RUNTIME_TYPES.ARRAY
362
+ })\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
363
+ )
364
+ if (array.length === 0)
365
+ throw new RangeError(
366
+ `First argument of (${KEYWORDS.GET_ARRAY}) is an empty (${
367
+ RUNTIME_TYPES.ARRAY
368
+ })\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
369
+ )
370
+ const index = evaluate(args[1], env)
371
+ if (!Number.isInteger(index) || index < 0)
372
+ throw new TypeError(
373
+ `Second argument of (${
374
+ KEYWORDS.GET_ARRAY
375
+ }) must be a positive (interger ${
376
+ RUNTIME_TYPES.NUMBER
377
+ }) (= i ${index})\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
378
+ )
379
+ if (index > array.length - 1)
380
+ throw new RangeError(
381
+ `Second argument of (${KEYWORDS.GET_ARRAY}) is outside of (${
382
+ RUNTIME_TYPES.ARRAY
383
+ }) bounds (= i ${index}) expected (and (>= i 0) (< i ${
384
+ array.length
385
+ }))\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
386
+ )
387
+ const value = array.at(index)
388
+ if (value == undefined)
389
+ throw new RangeError(
390
+ `Trying to get a null value in (${RUNTIME_TYPES.ARRAY}) at (${
391
+ KEYWORDS.GET_ARRAY
392
+ })\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
393
+ )
394
+ return value
395
+ },
396
+ [KEYWORDS.SET_ARRAY]: (args, env) => {
397
+ if (args.length !== 3)
398
+ throw new RangeError(
399
+ `Invalid number of arguments for (${
400
+ KEYWORDS.SET_ARRAY
401
+ }) (= 3) required\n\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
402
+ )
403
+ const array = evaluate(args[0], env)
404
+ if (!Array.isArray(array))
405
+ throw new TypeError(
406
+ `First argument of (${KEYWORDS.SET_ARRAY}) must be an (${
407
+ RUNTIME_TYPES.ARRAY
408
+ }) but ${LISP.source(args[0])} is not\n\n(${
409
+ KEYWORDS.SET_ARRAY
410
+ } ${stringifyArgs(args)})`
411
+ )
412
+ const index = evaluate(args[1], env)
413
+ if (!Number.isInteger(index) || index < 0)
414
+ throw new TypeError(
415
+ `Second argument of (${KEYWORDS.SET_ARRAY}) must be a positive (${
416
+ RUNTIME_TYPES.NUMBER
417
+ } integer) (= i ${index}) but ${LISP.source(args[1])} is not\n\n(${
418
+ KEYWORDS.SET_ARRAY
419
+ } ${stringifyArgs(args)})`
420
+ )
421
+ if (index > array.length)
422
+ throw new RangeError(
423
+ `Second argument of (${KEYWORDS.SET_ARRAY}) is outside of the (${
424
+ RUNTIME_TYPES.ARRAY
425
+ }) bounds (${index}) expected (and (>= i 0) (< i ${
426
+ array.length
427
+ })) but ${LISP.source(args[1])} is not\n\n(${
428
+ KEYWORDS.SET_ARRAY
429
+ } ${stringifyArgs(args)})`
430
+ )
431
+ const value = evaluate(args[2], env)
432
+ if (value == undefined)
433
+ throw new RangeError(
434
+ `Trying to set a null value in (${RUNTIME_TYPES.ARRAY}) at (${
435
+ KEYWORDS.SET_ARRAY
436
+ })\n\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
437
+ )
438
+ array[index] = value
439
+ return array
440
+ },
441
+ [KEYWORDS.POP_ARRAY]: (args, env) => {
442
+ if (args.length !== 1)
443
+ throw new RangeError(
444
+ `Invalid number of arguments for (${
445
+ KEYWORDS.POP_ARRAY
446
+ }) (= 1) required\n\n(${KEYWORDS.POP_ARRAY} ${stringifyArgs(args)})`
447
+ )
448
+ const array = evaluate(args[0], env)
449
+ if (!Array.isArray(array))
450
+ throw new TypeError(
451
+ `First argument of (${KEYWORDS.POP_ARRAY}) must be an (${
452
+ RUNTIME_TYPES.ARRAY
453
+ }) but ${LISP.source(args[0])} is not\n\n(${
454
+ KEYWORDS.POP_ARRAY
455
+ } ${stringifyArgs(args)})`
456
+ )
457
+ array.pop()
458
+ return array
459
+ },
460
+ [KEYWORDS.ARRAY_LENGTH]: (args, env) => {
461
+ if (args.length !== 1)
462
+ throw new RangeError(
463
+ `Invalid number of arguments for (${
464
+ KEYWORDS.ARRAY_LENGTH
465
+ }) (= 1 required)\n\n(${KEYWORDS.ARRAY_LENGTH} ${stringifyArgs(args)})`
466
+ )
467
+ const array = evaluate(args[0], env)
468
+ if (!Array.isArray(array))
469
+ throw new TypeError(
470
+ `First argument of (${KEYWORDS.ARRAY_LENGTH}) must be an ${
471
+ RUNTIME_TYPES.ARRAY
472
+ } but ${LISP.source(args[0])} is not\n\n(${
473
+ KEYWORDS.ARRAY_LENGTH
474
+ } ${stringifyArgs(args)})`
475
+ )
476
+ return array.length
477
+ },
478
+ [KEYWORDS.IF]: (args, env) => {
479
+ if (args.length !== 3)
480
+ throw new RangeError(
481
+ `Invalid number of arguments for (${
482
+ KEYWORDS.IF
483
+ }), expected (= 3) but got ${args.length}\n\n(${
484
+ KEYWORDS.IF
485
+ } ${stringifyArgs(args)})`
486
+ )
487
+ const condition = evaluate(args[0], env)
488
+ if (condition !== FALSE && condition !== TRUE)
489
+ throw new TypeError(
490
+ `Condition of (${
491
+ KEYWORDS.IF
492
+ }) must be ${TRUE} or ${FALSE} but ${LISP.source(args[0])} is not\n\n(${
493
+ KEYWORDS.IF
494
+ } ${stringifyArgs(args)})`
495
+ )
496
+ return condition ? evaluate(args[1], env) : evaluate(args[2], env)
497
+ },
498
+ [KEYWORDS.NOT]: (args, env) => {
499
+ if (args.length !== 1)
500
+ throw new RangeError(
501
+ `Invalid number of arguments for (${KEYWORDS.NOT}) (= 1 required)\n\n(${
502
+ KEYWORDS.NOT
503
+ } ${stringifyArgs(args)})`
504
+ )
505
+ const operand = evaluate(args[0], env)
506
+ if (operand !== FALSE && operand !== TRUE)
507
+ throw new TypeError(
508
+ `Condition of (${
509
+ KEYWORDS.NOT
510
+ }) must be ${TRUE} or ${FALSE} but ${LISP.source(args[0])} is not\n\n(${
511
+ KEYWORDS.NOT
512
+ } ${stringifyArgs(args)})`
513
+ )
514
+ return +!operand
515
+ },
516
+ [KEYWORDS.EQUAL]: (args, env) => {
517
+ if (args.length !== 2)
518
+ throw new RangeError(
519
+ `Invalid number of arguments for (${
520
+ KEYWORDS.EQUAL
521
+ }) (= 2 required)\n\n(${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
522
+ )
523
+ const a = evaluate(args[0], env)
524
+ const b = evaluate(args[1], env)
525
+ if (typeof a !== 'number')
526
+ throw new TypeError(
527
+ `First argument of (${KEYWORDS.EQUAL}) must be a ${
528
+ RUNTIME_TYPES.NUMBER
529
+ } but ${LISP.source(args[0])} is not\n\n(${
530
+ KEYWORDS.EQUAL
531
+ } ${stringifyArgs(args)})`
532
+ )
533
+ if (typeof b !== 'number')
534
+ throw new TypeError(
535
+ `Second argument of (${KEYWORDS.EQUAL}) must be a ${
536
+ RUNTIME_TYPES.NUMBER
537
+ } but ${LISP.source(args[1])} is not\n\n(${
538
+ KEYWORDS.EQUAL
539
+ } ${stringifyArgs(args)})`
540
+ )
541
+ return +(a === b)
542
+ },
543
+ [KEYWORDS.LESS_THAN]: (args, env) => {
544
+ if (args.length !== 2)
545
+ throw new RangeError(
546
+ `Invalid number of arguments for (${
547
+ KEYWORDS.LESS_THAN
548
+ }) (= 2 required)\n\n(${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
549
+ )
550
+ const a = evaluate(args[0], env)
551
+ const b = evaluate(args[1], env)
552
+ if (typeof a !== 'number')
553
+ throw new TypeError(
554
+ `First argument of (${KEYWORDS.LESS_THAN}) must be a ${
555
+ RUNTIME_TYPES.NUMBER
556
+ } but ${LISP.source(args[0])} is not\n\n(${
557
+ KEYWORDS.LESS_THAN
558
+ } ${stringifyArgs(args)})`
559
+ )
560
+ if (typeof b !== 'number')
561
+ throw new TypeError(
562
+ `Second argument of (${KEYWORDS.LESS_THAN}) must be a ${
563
+ RUNTIME_TYPES.NUMBER
564
+ } but ${LISP.source(args[1])} is not\n\n(${
565
+ KEYWORDS.LESS_THAN
566
+ } ${stringifyArgs(args)})`
567
+ )
568
+ return +(a < b)
569
+ },
570
+ [KEYWORDS.GREATHER_THAN]: (args, env) => {
571
+ if (args.length !== 2)
572
+ throw new RangeError(
573
+ `Invalid number of arguments for (${
574
+ KEYWORDS.GREATHER_THAN
575
+ }) (= 2 required)\n\n(${KEYWORDS.GREATHER_THAN} ${stringifyArgs(args)})`
576
+ )
577
+ const a = evaluate(args[0], env)
578
+ const b = evaluate(args[1], env)
579
+ if (typeof a !== 'number')
580
+ throw new TypeError(
581
+ `First argument of (${KEYWORDS.GREATHER_THAN}) must be a ${
582
+ RUNTIME_TYPES.NUMBER
583
+ } but ${LISP.source(args[0])} is not\n\n(${
584
+ KEYWORDS.GREATHER_THAN
585
+ } ${stringifyArgs(args)})`
586
+ )
587
+ if (typeof b !== 'number')
588
+ throw new TypeError(
589
+ `Second argument of (${KEYWORDS.GREATHER_THAN}) must be a ${
590
+ RUNTIME_TYPES.NUMBER
591
+ } but ${LISP.source(args[1])} is not\n\n(${
592
+ KEYWORDS.GREATHER_THAN
593
+ } ${stringifyArgs(args)})`
594
+ )
595
+ return +(a > b)
596
+ },
597
+ [KEYWORDS.GREATHER_THAN_OR_EQUAL]: (args, env) => {
598
+ if (args.length !== 2)
599
+ throw new RangeError(
600
+ `Invalid number of arguments for (${
601
+ KEYWORDS.GREATHER_THAN_OR_EQUAL
602
+ }) (= 2 required)\n\n(${
603
+ KEYWORDS.GREATHER_THAN_OR_EQUAL
604
+ } ${stringifyArgs(args)})`
605
+ )
606
+ const a = evaluate(args[0], env)
607
+ const b = evaluate(args[1], env)
608
+ if (typeof a !== 'number')
609
+ throw new TypeError(
610
+ `First argument of (${KEYWORDS.GREATHER_THAN_OR_EQUAL}) must be a ${
611
+ RUNTIME_TYPES.NUMBER
612
+ } but ${LISP.source(args[0])} is not\n\n(${
613
+ KEYWORDS.GREATHER_THAN_OR_EQUAL
614
+ } ${stringifyArgs(args)})`
615
+ )
616
+ if (typeof b !== 'number')
617
+ throw new TypeError(
618
+ `Second argument of (${KEYWORDS.GREATHER_THAN_OR_EQUAL}) must be a ${
619
+ RUNTIME_TYPES.NUMBER
620
+ } but ${LISP.source(args[1])} is not\n\n(${
621
+ KEYWORDS.GREATHER_THAN_OR_EQUAL
622
+ } ${stringifyArgs(args)})`
623
+ )
624
+ return +(a >= b)
625
+ },
626
+ [KEYWORDS.LESS_THAN_OR_EQUAL]: (args, env) => {
627
+ if (args.length !== 2)
628
+ throw new RangeError(
629
+ `Invalid number of arguments for (${
630
+ KEYWORDS.LESS_THAN_OR_EQUAL
631
+ }) (= 2 required)\n\n(${KEYWORDS.LESS_THAN_OR_EQUAL} ${stringifyArgs(
632
+ args
633
+ )})`
634
+ )
635
+ const a = evaluate(args[0], env)
636
+ const b = evaluate(args[1], env)
637
+ if (typeof a !== 'number')
638
+ throw new TypeError(
639
+ `First argument of (${KEYWORDS.LESS_THAN_OR_EQUAL}) must be a ${
640
+ RUNTIME_TYPES.NUMBER
641
+ } but ${LISP.source(args[0])} is not\n\n(${
642
+ KEYWORDS.LESS_THAN_OR_EQUAL
643
+ } ${stringifyArgs(args)})`
644
+ )
645
+ if (typeof b !== 'number')
646
+ throw new TypeError(
647
+ `Second argument of (${KEYWORDS.LESS_THAN_OR_EQUAL}) must be a ${
648
+ RUNTIME_TYPES.NUMBER
649
+ } but ${LISP.source(args[1])} is not\n\n(${
650
+ KEYWORDS.LESS_THAN_OR_EQUAL
651
+ } ${stringifyArgs(args)})`
652
+ )
653
+ return +(a <= b)
654
+ },
655
+ [KEYWORDS.AND]: (args, env) => {
656
+ if (args.length !== 2)
657
+ throw new RangeError(
658
+ `Invalid number of arguments for (${KEYWORDS.AND}) (= 2 required)\n\n(${
659
+ KEYWORDS.AND
660
+ } ${stringifyArgs(args)})`
661
+ )
662
+ const a = evaluate(args[0], env)
663
+ if (a !== FALSE && a !== TRUE)
664
+ throw new TypeError(
665
+ `Condition of (${
666
+ KEYWORDS.AND
667
+ }) must be ${TRUE} or ${FALSE} but got\n\n(${
668
+ KEYWORDS.AND
669
+ } ${stringifyArgs(args)})`
670
+ )
671
+ if (!a) return FALSE
672
+ const b = evaluate(args[1], env)
673
+ if (b !== FALSE && b !== TRUE)
674
+ throw new TypeError(
675
+ `Condition of (${
676
+ KEYWORDS.AND
677
+ }) must be ${TRUE} or ${FALSE} but got\n\n(${
678
+ KEYWORDS.AND
679
+ } ${stringifyArgs(args)})`
680
+ )
681
+ return b
682
+ },
683
+ [KEYWORDS.OR]: (args, env) => {
684
+ if (args.length !== 2)
685
+ throw new RangeError(
686
+ `Invalid number of arguments for (${KEYWORDS.OR}) (= 2 required)\n\n(${
687
+ KEYWORDS.OR
688
+ } ${stringifyArgs(args)})`
689
+ )
690
+ const a = evaluate(args[0], env)
691
+ if (a !== FALSE && a !== TRUE)
692
+ throw new TypeError(
693
+ `Condition of (${
694
+ KEYWORDS.OR
695
+ }) must be ${TRUE} or ${FALSE} but got\n\n(${
696
+ KEYWORDS.OR
697
+ } ${stringifyArgs(args)})`
698
+ )
699
+ if (a) return TRUE
700
+ const b = evaluate(args[1], env)
701
+ if (b !== FALSE && b !== TRUE)
702
+ throw new TypeError(
703
+ `Condition of (${
704
+ KEYWORDS.OR
705
+ }) must be ${TRUE} or ${FALSE} but got\n\n(${
706
+ KEYWORDS.OR
707
+ } ${stringifyArgs(args)})`
708
+ )
709
+ return b
710
+ },
711
+ [KEYWORDS.DEFINE_VARIABLE]: (args, env) => {
712
+ if (args.length !== 2)
713
+ throw new RangeError(
714
+ `Invalid number of arguments to (${
715
+ KEYWORDS.DEFINE_VARIABLE
716
+ }) (= 2 required)\n\n(${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(
717
+ args
718
+ )})`
719
+ )
720
+ const word = args[0]
721
+ const type = word[TYPE]
722
+ const name = word[VALUE]
723
+ if (type !== WORD)
724
+ throw new SyntaxError(
725
+ `First argument of (${KEYWORDS.DEFINE_VARIABLE}) must be word but got ${
726
+ TYPES[type]
727
+ }\n\n(${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(args)})`
728
+ )
729
+ else if (isForbiddenVariableName(name))
730
+ throw new ReferenceError(
731
+ `Variable name ${name} is forbidden \n\n(${
732
+ KEYWORDS.DEFINE_VARIABLE
733
+ } ${stringifyArgs(args)})`
734
+ )
735
+ env[name] = evaluate(args[1], env)
736
+ return env[name]
737
+ },
738
+ [KEYWORDS.ANONYMOUS_FUNCTION]: (args, env) => {
739
+ if (!args.length)
740
+ throw new RangeError(
741
+ `At lest one argument (the body) is required for (${KEYWORDS.ANONYMOUS_FUNCTION})`
742
+ )
743
+ const params = args.slice(0, -1)
744
+ const body = args.at(-1)
745
+ return (props = [], scope, name) => {
746
+ if (props.length !== params.length)
747
+ throw new RangeError(
748
+ `Incorrect number of arguments for (${KEYWORDS.ANONYMOUS_FUNCTION}${
749
+ name ? ` ${name}` : ''
750
+ }) are provided (expects ${params.length} but got ${
751
+ props.length
752
+ })\n\n${
753
+ name
754
+ ? `(${name} ${stringifyArgs(params)})`
755
+ : `(${KEYWORDS.ANONYMOUS_FUNCTION} ${stringifyArgs(params)})`
756
+ }`
757
+ )
758
+ const localEnv = Object.create(env)
759
+ for (let i = 0; i < props.length; ++i) {
760
+ const value = evaluate(props[i], scope)
761
+ localEnv[params[i][VALUE]] = value
762
+ }
763
+ return evaluate(body, localEnv)
764
+ }
765
+ },
766
+ [KEYWORDS.CALL_FUNCTION]: (args, env) => {
767
+ if (!args.length)
768
+ throw new RangeError(
769
+ `Invalid number of arguments to (${
770
+ KEYWORDS.CALL_FUNCTION
771
+ }) (>= 1 required)\n\n(${KEYWORDS.CALL_FUNCTION} ${stringifyArgs(
772
+ args
773
+ )})`
774
+ )
775
+ const first = args.at(-1)
776
+ if (first[TYPE] === WORD && first[VALUE] in keywords)
777
+ throw new TypeError(
778
+ `Preceeding arguments of (${
779
+ KEYWORDS.CALL_FUNCTION
780
+ }) must not be an reserved word\n\n(${
781
+ KEYWORDS.CALL_FUNCTION
782
+ } ${stringifyArgs(args)})`
783
+ )
784
+ const apply = evaluate(first, env)
785
+ if (typeof apply !== 'function')
786
+ throw new TypeError(
787
+ `Last argument of (${KEYWORDS.CALL_FUNCTION}) must be a (${
788
+ KEYWORDS.ANONYMOUS_FUNCTION
789
+ }) but got ${LISP.stringify(apply)}\n\n(${
790
+ KEYWORDS.CALL_FUNCTION
791
+ } ${stringifyArgs(args)})`
792
+ )
793
+
794
+ return apply(args.slice(0, -1), env)
795
+ },
796
+ [KEYWORDS.BLOCK]: (args, env) => {
797
+ if (!args.length)
798
+ throw new RangeError(
799
+ `Invalid number of arguments to (${
800
+ KEYWORDS.BLOCK
801
+ }) (>= 1 required)\n\n(${KEYWORDS.BLOCK} ${stringifyArgs(args)})`
802
+ )
803
+ let out = FALSE
804
+ for (const exp of args) out = evaluate(exp, env)
805
+ return out
806
+ },
807
+ [KEYWORDS.IS_ATOM]: (args, env) => {
808
+ if (args.length !== 1)
809
+ throw new RangeError(
810
+ `Invalid number of arguments for (${
811
+ KEYWORDS.IS_ATOM
812
+ }) (= 1 required)\n\n(${KEYWORDS.IS_ATOM} ${stringifyArgs(args)})`
813
+ )
814
+ return +(typeof evaluate(args[0], env) === 'number')
815
+ },
816
+ [KEYWORDS.IS_LAMBDA]: (args, env) => {
817
+ if (args.length !== 1)
818
+ throw new RangeError(
819
+ `Invalid number of arguments for (${
820
+ KEYWORDS.IS_LAMBDA
821
+ }) (= 1 required)\n\n(${KEYWORDS.IS_LAMBDA} ${stringifyArgs(args)})`
822
+ )
823
+ return +(typeof evaluate(args[0], env) === 'function')
824
+ },
825
+ // Only for type checking
826
+ [STATIC_TYPES.UNKNOWN]: (args, env) => evaluate(args[0], env),
827
+ [STATIC_TYPES.ANY]: (args, env) => evaluate(args[0], env),
828
+
829
+ [STATIC_TYPES.ATOM]: (args, env) => evaluate(args[0], env),
830
+ [STATIC_TYPES.ABSTRACTION]: (args, env) => evaluate(args[0], env),
831
+ [STATIC_TYPES.COLLECTION]: (args, env) => evaluate(args[0], env),
832
+
833
+ [STATIC_TYPES.BOOLEAN]: (args, env) => evaluate(args[0], env),
834
+ [STATIC_TYPES.NUMBER]: (args, env) => evaluate(args[0], env),
835
+ [STATIC_TYPES.NUMBERS]: (args, env) => evaluate(args[0], env),
836
+ [STATIC_TYPES.COLLECTIONS]: (args, env) => evaluate(args[0], env),
837
+ [STATIC_TYPES.ABSTRACTIONS]: (args, env) => evaluate(args[0], env),
838
+ [STATIC_TYPES.BOOLEANS]: (args, env) => evaluate(args[0], env)
839
+ }
840
+ const debugStack = []
841
+ const evaluate = (exp, env = keywords) => {
842
+ const [head, ...tail] = isLeaf(exp) ? [exp] : exp
843
+ if (head == undefined) return []
844
+ const type = head[TYPE]
845
+ const value = head[VALUE]
846
+ let res
847
+ switch (type) {
848
+ case WORD:
849
+ res = env[value]
850
+ return res
851
+ case APPLY:
852
+ res = env[value](tail, env)
853
+ if (
854
+ value !== KEYWORDS.BLOCK &&
855
+ value !== KEYWORDS.CALL_FUNCTION &&
856
+ value !== KEYWORDS.ANONYMOUS_FUNCTION &&
857
+ value !== KEYWORDS.DEFINE_VARIABLE
858
+ ) {
859
+ // debugStack.push(
860
+ // `\x1b[31m${LISP.source(exp)}\x1b[32m\n${
861
+ // typeof res === 'function' ? '(lambda)' : serialise(res)
862
+ // }\x1b[0m`
863
+ // )
864
+ const out = typeof res === 'function' ? '(lambda)' : LISP.serialise(res)
865
+ if (debugStack.at(-1)?.result !== out)
866
+ debugStack.push({
867
+ function: value,
868
+ source: LISP.source(exp),
869
+ result: out
870
+ })
871
+ // else debugStack[debugStack.length - 1].src += LISP.source(exp)
872
+ }
873
+ return res
874
+ case ATOM:
875
+ res = value
876
+ return res
877
+ }
878
+ }
879
+ export const debugStackToString = (stack) =>
880
+ stack.map(({ source, result }) => `${source}\n${result}`).join('\n')
881
+ export const startDebug = (ast, speed = 250, start, end) => {
882
+ debugStack.length = 0
883
+ evaluate(ast)
884
+ start = start ? debugStack.findIndex(start) : 0
885
+ end = end ? debugStack.findIndex(end) : debugStack.length
886
+ const stack = debugStack.slice(start, end).reverse()
887
+ if (speed !== 0) {
888
+ const rec = () => {
889
+ setTimeout(() => {
890
+ if (stack.length) {
891
+ const { source, result } = stack.pop()
892
+ console.log(`\x1b[31m${source}\x1b[32m\n${result}\x1b[0m`)
893
+ rec()
894
+ }
895
+ }, speed)
896
+ }
897
+ rec()
898
+ }
899
+ return stack
900
+ }
901
+
902
+ // const types = typeCheck(std[0], withCtxTypes(definedTypes(stdT)))[1]
903
+ const __debugStack__ = []
904
+ export const debug = (ast, checkTypes = true, userDefinedTypes) => {
905
+ let types = new Map()
906
+ const debugEnv = {
907
+ ...keywords,
908
+ [STATIC_TYPES.ABSTRACTION]: (args, env) => {
909
+ const T = evaluate(args[0], env)
910
+ const t = typeof T
911
+ if (t !== 'function')
912
+ throw new TypeError(
913
+ `Argument of (${STATIC_TYPES.ABSTRACTION}) must be an (${
914
+ RUNTIME_TYPES.LAMBDA
915
+ }) but got something else (${
916
+ STATIC_TYPES.ABSTRACTION
917
+ } ${stringifyArgs(args)})`
918
+ )
919
+ return T
920
+ },
921
+ [STATIC_TYPES.ATOM]: (args, env) => {
922
+ const T = evaluate(args[0], env)
923
+ const t = typeof T
924
+ if (t !== 'number')
925
+ throw new TypeError(
926
+ `Argument of (${STATIC_TYPES.ATOM}) must be an (${
927
+ RUNTIME_TYPES.NUMBER
928
+ }) but got something else (${STATIC_TYPES.ATOM} ${stringifyArgs(
929
+ args
930
+ )})`
931
+ )
932
+ return T
933
+ },
934
+ [STATIC_TYPES.COLLECTION]: (args, env) => {
935
+ const T = evaluate(args[0], env)
936
+ if (!Array.isArray(T))
937
+ throw new TypeError(
938
+ `Argument of (${STATIC_TYPES.COLLECTION}) must be an (${
939
+ RUNTIME_TYPES.ARRAY
940
+ }) but got something else (${STATIC_TYPES.COLLECTION} ${stringifyArgs(
941
+ args
942
+ )})`
943
+ )
944
+ return T
945
+ },
946
+ [DEBUG.TYPE_SIGNATURE]: (args, env) => {
947
+ if (args.length !== 2)
948
+ throw new RangeError(
949
+ `Invalid number of arguments to (${DEBUG.TYPE_SIGNATURE}) (= 1) (${
950
+ DEBUG.TYPE_SIGNATURE
951
+ } ${stringifyArgs(args)})`
952
+ )
953
+ const name =
954
+ Array.isArray(args[0]) && args[0][0][VALUE] === DEBUG.STRING
955
+ ? args[0][1]
956
+ .slice(1)
957
+ .map((x) => String.fromCharCode(x[VALUE]))
958
+ .join('')
959
+ : args[0][VALUE]
960
+ const option = args[1][VALUE]
961
+ const wildcard = name === '*'
962
+ if (option === 'Scope') {
963
+ if (wildcard) {
964
+ return [...types.entries()]
965
+ .sort((a, b) => a[0].localeCompare(b[0]))
966
+ .map(([k, v]) => `${k}\n${v()}`)
967
+ .join('\n\n')
968
+ }
969
+ const t = types.get(`; 1 ${name}`)
970
+ return t ? t() : ''
971
+ } else if (option === 'Search') {
972
+ return [...types.entries()]
973
+ .filter((x) => x[0].includes(name))
974
+ .sort((a, b) => a[0].localeCompare(b[0]))
975
+ .map(([k, v]) => `${k}\n${v()}`)
976
+ .join('\n\n')
977
+ } else if (option === 'Special') {
978
+ return formatType(name, SPECIAL_FORM_TYPES)
979
+ } else if (option === 'Type') {
980
+ const [from, to] = name.split(KEYWORDS.BLOCK).map((x) => x.trim())
981
+ return [...types.entries()]
982
+ .filter(([k, v]) => {
983
+ const T = v()
984
+ if (T && T.includes(KEYWORDS.BLOCK)) {
985
+ const [left, right] = T.split(KEYWORDS.BLOCK).map((x) => x.trim())
986
+ return left.includes(from) && right.includes(to)
987
+ }
988
+ })
989
+ .sort((a, b) => a[0].length - b[0].length)
990
+ .map(([k, v]) => `${k}\n${v()}`)
991
+ .join('\n\n')
992
+ } else if (option === 'Library') {
993
+ types = typeCheck(std[0], withCtxTypes(definedTypes(stdT)))[1]
994
+ const matches = wildcard
995
+ ? [...types.entries()]
996
+ : [...types.entries()].filter(([k, v]) => v().includes(name))
997
+ return matches
998
+ .sort((a, b) => a[0].length - b[0].length)
999
+ .map(([k, v]) => `${k}\n${v()}`)
1000
+ .join('\n\n')
1001
+ } else {
1002
+ return ''
1003
+ }
1004
+ },
1005
+ [DEBUG.SIGNATURE]: (args, env) => {
1006
+ const name =
1007
+ Array.isArray(args[0]) && args[0][0][VALUE] === DEBUG.STRING
1008
+ ? args[0][1]
1009
+ .slice(1)
1010
+ .map((x) => String.fromCharCode(x[VALUE]))
1011
+ .join('')
1012
+ : args[0][VALUE]
1013
+ const signatures =
1014
+ args.length === 0
1015
+ ? std[0][1][1].slice(1)
1016
+ : std[0][1][1].filter(
1017
+ (x) =>
1018
+ x[0][TYPE] === APPLY &&
1019
+ x[0][VALUE] === KEYWORDS.DEFINE_VARIABLE &&
1020
+ x[1][TYPE] === WORD &&
1021
+ x[1][VALUE].toString().includes(name)
1022
+ )
1023
+ return signatures.length === 0
1024
+ ? 'Not defined in library'
1025
+ : signatures.map(LISP.source).join('\n\n')
1026
+ },
1027
+ [DEBUG.STRING]: (args, env) => {
1028
+ if (args.length !== 1)
1029
+ throw new RangeError(
1030
+ `Invalid number of arguments to (${DEBUG.STRING}) (= 1) (${
1031
+ DEBUG.STRING
1032
+ } but got (${args.length}) ${stringifyArgs(args)})`
1033
+ )
1034
+ const expression = evaluate(args[0], env)
1035
+ if (!Array.isArray(expression))
1036
+ throw new TypeError(
1037
+ `Argument of (${DEBUG.STRING}) must be an (${
1038
+ RUNTIME_TYPES.ARRAY
1039
+ }) but got (${expression}) (${DEBUG.STRING} ${stringifyArgs(args)})`
1040
+ )
1041
+ return `"${expression.map((x) => String.fromCharCode(x)).join('')}"`
1042
+ },
1043
+ [DEBUG.UNQUOTED_STRING]: (args, env) => {
1044
+ if (args.length !== 1)
1045
+ throw new RangeError(
1046
+ `Invalid number of arguments to (${DEBUG.UNQUOTED_STRING}) (= 1) (${
1047
+ DEBUG.UNQUOTED_STRING
1048
+ } but got (${args.length}) ${stringifyArgs(args)})`
1049
+ )
1050
+ const expression = evaluate(args[0], env)
1051
+ if (!Array.isArray(expression))
1052
+ throw new TypeError(
1053
+ `Argument of (${DEBUG.UNQUOTED_STRING}) must be an (${
1054
+ RUNTIME_TYPES.ARRAY
1055
+ }) but got (${expression}) (${DEBUG.UNQUOTED_STRING} ${stringifyArgs(
1056
+ args
1057
+ )})`
1058
+ )
1059
+ return `${expression.map((x) => String.fromCharCode(x)).join('')}`
1060
+ },
1061
+ [DEBUG.LOG]: (args, env) => {
1062
+ if (args.length !== 1 && args.length !== 2)
1063
+ throw new RangeError(
1064
+ `Invalid number of arguments to (${DEBUG.LOG}) (or (= 1) (= 2)) (${
1065
+ DEBUG.LOG
1066
+ } ${stringifyArgs(args)})`
1067
+ )
1068
+ const expression = evaluate(args[0], env)
1069
+ if (args.length === 2) {
1070
+ const option = evaluate(args[1], env)
1071
+ if (!Array.isArray(option)) {
1072
+ throw new TypeError(
1073
+ `Second argument of (${DEBUG.LOG}) must be an (${
1074
+ RUNTIME_TYPES.ARRAY
1075
+ }) but got (${expression}) (${DEBUG.LOG} ${stringifyArgs(args)})`
1076
+ )
1077
+ }
1078
+ const type = option.map((x) => String.fromCharCode(x)).join('')
1079
+ switch (type) {
1080
+ case 'string':
1081
+ case 'str':
1082
+ {
1083
+ if (!Array.isArray(expression))
1084
+ throw new TypeError(
1085
+ `Argument of (${DEBUG.LOG}) must be an (${
1086
+ RUNTIME_TYPES.ARRAY
1087
+ }) in the case ${type} but got (${expression}) (${
1088
+ DEBUG.LOG
1089
+ } ${stringifyArgs(args)})`
1090
+ )
1091
+ console.log(
1092
+ expression.map((x) => String.fromCharCode(x)).join('')
1093
+ )
1094
+ }
1095
+ break
1096
+ case 'char':
1097
+ case 'ch':
1098
+ {
1099
+ if (typeof expression !== 'number')
1100
+ throw new TypeError(
1101
+ `Argument argument of (${DEBUG.LOG}) must be a (${
1102
+ RUNTIME_TYPES.NUMBER
1103
+ }) in the case ${type} but got (${expression}) (${
1104
+ DEBUG.LOG
1105
+ } ${stringifyArgs(args)})`
1106
+ )
1107
+ console.log(String.fromCharCode(expression))
1108
+ }
1109
+
1110
+ break
1111
+ case '*':
1112
+ console.log(expression)
1113
+ break
1114
+ case '!':
1115
+ __debugStack__.push(structuredClone(expression))
1116
+ break
1117
+ default:
1118
+ throw new TypeError(
1119
+ `Invalid option to (${DEBUG.LOG}) got ${option} ${stringifyArgs(
1120
+ args
1121
+ )})`
1122
+ )
1123
+ }
1124
+ } else console.log(expression)
1125
+ return expression
1126
+ }
1127
+ }
1128
+ try {
1129
+ types = checkTypes
1130
+ ? typeCheck(
1131
+ ast,
1132
+ withCtxTypes(
1133
+ userDefinedTypes
1134
+ ? {
1135
+ ...definedTypes(filteredDefinedTypes(ast, std, stdT)),
1136
+ ...definedTypes(LISP.parse(removeNoCode(userDefinedTypes)))
1137
+ }
1138
+ : definedTypes(filteredDefinedTypes(ast, std, stdT))
1139
+ )
1140
+ )[1]
1141
+ : new Map()
1142
+ const evaluated = evaluate(enhance(ast), debugEnv)
1143
+ const exp = ast.at(-1).at(-1).at(-1)
1144
+ const [head, ...rest] = isLeaf(exp) ? [exp] : exp
1145
+ let type = ''
1146
+ switch (head[TYPE]) {
1147
+ case ATOM:
1148
+ type = STATIC_TYPES.ATOM
1149
+ break
1150
+ case WORD:
1151
+ case APPLY:
1152
+ switch (head[VALUE]) {
1153
+ case DEBUG.TYPE_SIGNATURE:
1154
+ break
1155
+ case KEYWORDS.DEFINE_VARIABLE:
1156
+ type = debugEnv[DEBUG.TYPE_SIGNATURE]([rest[0], [WORD, 'Scope']])
1157
+ break
1158
+ default:
1159
+ if (SPECIAL_FORMS_SET.has(head[VALUE])) {
1160
+ // type = debugEnv[DEBUG.TYPE_SIGNATURE]([head, [WORD, 'Special']])
1161
+ type = `${debugEnv[DEBUG.TYPE_SIGNATURE]([
1162
+ head,
1163
+ [WORD, 'Special']
1164
+ ])}`
1165
+ } else
1166
+ type = `${debugEnv[DEBUG.TYPE_SIGNATURE]([
1167
+ head,
1168
+ [WORD, 'Scope']
1169
+ ])}`
1170
+ break
1171
+ }
1172
+
1173
+ break
1174
+ }
1175
+ type = type.split('\n').pop()
1176
+ return {
1177
+ type,
1178
+ evaluated,
1179
+ error: null
1180
+ }
1181
+ } catch (error) {
1182
+ // console.log(error)
1183
+ return {
1184
+ type: null,
1185
+ evaluated: null,
1186
+ error: {
1187
+ message: error.message
1188
+ }
1189
+ }
1190
+ }
1191
+ }