fez-lisp 1.0.51 → 1.0.52

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