fez-lisp 1.2.62 → 1.3.0
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.
- package/lib/baked/std.js +1 -1
- package/package.json +1 -1
- package/src/compiler.js +350 -350
- package/src/interpreter.js +783 -743
- package/src/utils.js +832 -630
package/src/interpreter.js
CHANGED
@@ -1,743 +1,783 @@
|
|
1
|
-
import { TYPE, VALUE, WORD, KEYWORDS, FALSE, TRUE, TYPES } from './keywords.js'
|
2
|
-
import { evaluate } from './evaluator.js'
|
3
|
-
import { isForbiddenVariableName, stringifyArgs } from './utils.js'
|
4
|
-
export const keywords = {
|
5
|
-
[KEYWORDS.REMAINDER_OF_DIVISION]: (args, env) => {
|
6
|
-
if (args.length < 2)
|
7
|
-
throw new RangeError(
|
8
|
-
`Invalid number of arguments for (${
|
9
|
-
KEYWORDS.REMAINDER_OF_DIVISION
|
10
|
-
}), expected > 1 but got ${args.length}. (${
|
11
|
-
KEYWORDS.REMAINDER_OF_DIVISION
|
12
|
-
} ${stringifyArgs(args)})`
|
13
|
-
)
|
14
|
-
const a = evaluate(args[0], env)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if (b
|
23
|
-
throw new TypeError(
|
24
|
-
`Second argument of (${
|
25
|
-
KEYWORDS.
|
26
|
-
})
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
if (number
|
43
|
-
throw new TypeError(
|
44
|
-
`
|
45
|
-
KEYWORDS.
|
46
|
-
})
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
if (
|
60
|
-
throw new TypeError(
|
61
|
-
`
|
62
|
-
KEYWORDS.
|
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
|
-
if (
|
155
|
-
throw new
|
156
|
-
`
|
157
|
-
KEYWORDS.
|
158
|
-
})
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
if (
|
164
|
-
throw new
|
165
|
-
`
|
166
|
-
KEYWORDS.
|
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
|
-
if (!
|
222
|
-
throw new
|
223
|
-
`
|
224
|
-
KEYWORDS.
|
225
|
-
} ${stringifyArgs(args)})`
|
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
|
-
[KEYWORDS.
|
256
|
-
if (args.length
|
257
|
-
throw new RangeError(
|
258
|
-
`Invalid number of arguments
|
259
|
-
KEYWORDS.
|
260
|
-
} ${stringifyArgs(args)})`
|
261
|
-
)
|
262
|
-
return
|
263
|
-
},
|
264
|
-
[KEYWORDS.
|
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
|
-
if (
|
347
|
-
throw new
|
348
|
-
`Invalid
|
349
|
-
KEYWORDS.
|
350
|
-
})
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
if (typeof
|
355
|
-
throw new TypeError(
|
356
|
-
`Invalid use of (${
|
357
|
-
KEYWORDS.
|
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
|
-
KEYWORDS.
|
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
|
-
if (
|
460
|
-
throw new
|
461
|
-
`
|
462
|
-
KEYWORDS.
|
463
|
-
}
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
if (
|
479
|
-
throw new
|
480
|
-
`
|
481
|
-
KEYWORDS.
|
482
|
-
}
|
483
|
-
)
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
if (
|
488
|
-
throw new
|
489
|
-
`
|
490
|
-
|
491
|
-
} (${KEYWORDS.
|
492
|
-
)
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
if (
|
514
|
-
throw new
|
515
|
-
`
|
516
|
-
KEYWORDS.
|
517
|
-
} (${KEYWORDS.
|
518
|
-
)
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
if (
|
523
|
-
throw new
|
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
|
-
const
|
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
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
KEYWORDS.
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
1
|
+
import { TYPE, VALUE, WORD, KEYWORDS, FALSE, TRUE, TYPES } from './keywords.js'
|
2
|
+
import { evaluate } from './evaluator.js'
|
3
|
+
import { isForbiddenVariableName, stringifyArgs } from './utils.js'
|
4
|
+
export const keywords = {
|
5
|
+
[KEYWORDS.REMAINDER_OF_DIVISION]: (args, env) => {
|
6
|
+
if (args.length < 2)
|
7
|
+
throw new RangeError(
|
8
|
+
`Invalid number of arguments for (${
|
9
|
+
KEYWORDS.REMAINDER_OF_DIVISION
|
10
|
+
}), expected > 1 but got ${args.length}. (${
|
11
|
+
KEYWORDS.REMAINDER_OF_DIVISION
|
12
|
+
} ${stringifyArgs(args)})`
|
13
|
+
)
|
14
|
+
const a = evaluate(args[0], env)
|
15
|
+
if (typeof a !== 'number')
|
16
|
+
throw new TypeError(
|
17
|
+
`First argument of (${KEYWORDS.REMAINDER_OF_DIVISION}) is not (${
|
18
|
+
KEYWORDS.NUMBER_TYPE
|
19
|
+
}) (${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)})`
|
20
|
+
)
|
21
|
+
const b = evaluate(args[1], env)
|
22
|
+
if (typeof b !== 'number')
|
23
|
+
throw new TypeError(
|
24
|
+
`Second argument of (${KEYWORDS.REMAINDER_OF_DIVISION}) is not (${
|
25
|
+
KEYWORDS.NUMBER_TYPE
|
26
|
+
}) (${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)})`
|
27
|
+
)
|
28
|
+
if (b === 0)
|
29
|
+
throw new TypeError(
|
30
|
+
`Second argument of (${
|
31
|
+
KEYWORDS.REMAINDER_OF_DIVISION
|
32
|
+
}) can't be a (0) (division by 0 is not allowed) (${
|
33
|
+
KEYWORDS.REMAINDER_OF_DIVISION
|
34
|
+
} ${stringifyArgs(args)})`
|
35
|
+
)
|
36
|
+
|
37
|
+
return a % b
|
38
|
+
},
|
39
|
+
[KEYWORDS.DIVISION]: (args, env) => {
|
40
|
+
if (args.length === 1) {
|
41
|
+
const number = evaluate(args[0], env)
|
42
|
+
if (typeof number !== 'number')
|
43
|
+
throw new TypeError(
|
44
|
+
`Arguments of (${KEYWORDS.DIVISION}) is not a (${
|
45
|
+
KEYWORDS.NUMBER_TYPE
|
46
|
+
}) (${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
|
47
|
+
)
|
48
|
+
if (number === 0)
|
49
|
+
throw new TypeError(
|
50
|
+
`Argument of (${
|
51
|
+
KEYWORDS.DIVISION
|
52
|
+
}) can't be a (0) (division by 0 is not allowed) (${
|
53
|
+
KEYWORDS.DIVISION
|
54
|
+
} ${stringifyArgs(args)})`
|
55
|
+
)
|
56
|
+
return 1 / number
|
57
|
+
}
|
58
|
+
const a = evaluate(args[0], env)
|
59
|
+
if (typeof a !== 'number')
|
60
|
+
throw new TypeError(
|
61
|
+
`First argument of (${KEYWORDS.DIVISION}) is not (${
|
62
|
+
KEYWORDS.NUMBER_TYPE
|
63
|
+
}) (${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
|
64
|
+
)
|
65
|
+
const b = evaluate(args[1], env)
|
66
|
+
if (typeof b !== 'number')
|
67
|
+
throw new TypeError(
|
68
|
+
`Second argument of (${KEYWORDS.DIVISION}) is not (${
|
69
|
+
KEYWORDS.NUMBER_TYPE
|
70
|
+
}) (${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
|
71
|
+
)
|
72
|
+
if (b === 0)
|
73
|
+
throw new TypeError(
|
74
|
+
`Second Argument of (${
|
75
|
+
KEYWORDS.DIVISION
|
76
|
+
}) can't be a (0) (division by 0 is not allowed) (${
|
77
|
+
KEYWORDS.DIVISION
|
78
|
+
} ${stringifyArgs(args)})`
|
79
|
+
)
|
80
|
+
return a / b
|
81
|
+
},
|
82
|
+
[KEYWORDS.ARRAY_LENGTH]: (args, env) => {
|
83
|
+
if (args.length !== 1)
|
84
|
+
throw new RangeError(
|
85
|
+
`Invalid number of arguments for (${
|
86
|
+
KEYWORDS.ARRAY_LENGTH
|
87
|
+
}) (= 1 required) (${KEYWORDS.ARRAY_LENGTH} ${stringifyArgs(args)})`
|
88
|
+
)
|
89
|
+
const array = evaluate(args[0], env)
|
90
|
+
if (!Array.isArray(array))
|
91
|
+
throw new TypeError(
|
92
|
+
`First argument of (${KEYWORDS.ARRAY_LENGTH}) must be an ${
|
93
|
+
KEYWORDS.ARRAY_TYPE
|
94
|
+
} (${KEYWORDS.ARRAY_LENGTH} ${stringifyArgs(args)})`
|
95
|
+
)
|
96
|
+
return array.length
|
97
|
+
},
|
98
|
+
[KEYWORDS.IS_ATOM]: (args, env) => {
|
99
|
+
if (args.length !== 1)
|
100
|
+
throw new RangeError(
|
101
|
+
`Invalid number of arguments for (${
|
102
|
+
KEYWORDS.IS_ATOM
|
103
|
+
}) (= 1 required) (${KEYWORDS.IS_ATOM} ${stringifyArgs(args)})`
|
104
|
+
)
|
105
|
+
return +(typeof evaluate(args[0], env) === 'number')
|
106
|
+
},
|
107
|
+
[KEYWORDS.IS_LAMBDA]: (args, env) => {
|
108
|
+
if (args.length !== 1)
|
109
|
+
throw new RangeError(
|
110
|
+
`Invalid number of arguments for (${
|
111
|
+
KEYWORDS.IS_LAMBDA
|
112
|
+
}) (= 1 required) (${KEYWORDS.IS_LAMBDA} ${stringifyArgs(args)})`
|
113
|
+
)
|
114
|
+
return +(typeof evaluate(args[0], env) === 'function')
|
115
|
+
},
|
116
|
+
[KEYWORDS.ADDITION]: (args, env) => {
|
117
|
+
if (args.length !== 0 && args.length !== 2)
|
118
|
+
throw new RangeError(
|
119
|
+
`Invalid number of arguments for (${
|
120
|
+
KEYWORDS.ADDITION
|
121
|
+
}), expected (or (= 2) (= 0)) but got ${args.length}. (${
|
122
|
+
KEYWORDS.ADDITION
|
123
|
+
} ${stringifyArgs(args)})`
|
124
|
+
)
|
125
|
+
const a = evaluate(args[0], env)
|
126
|
+
if (typeof a !== 'number')
|
127
|
+
throw new TypeError(
|
128
|
+
`First arguments of (${KEYWORDS.ADDITION}) is not a (${
|
129
|
+
KEYWORDS.NUMBER_TYPE
|
130
|
+
}) (${KEYWORDS.ADDITION} ${stringifyArgs(args)})`
|
131
|
+
)
|
132
|
+
const b = evaluate(args[1], env)
|
133
|
+
if (typeof b !== 'number')
|
134
|
+
throw new TypeError(
|
135
|
+
`Second arguments of (${KEYWORDS.ADDITION}) is not a (${
|
136
|
+
KEYWORDS.NUMBER_TYPE
|
137
|
+
}) (${KEYWORDS.ADDITION} ${stringifyArgs(args)})`
|
138
|
+
)
|
139
|
+
return a + b
|
140
|
+
},
|
141
|
+
[KEYWORDS.MULTIPLICATION]: (args, env) => {
|
142
|
+
if (args.length !== 0 && args.length !== 2)
|
143
|
+
throw new RangeError(
|
144
|
+
`Invalid number of arguments for (${KEYWORDS.MULTIPLICATION}), expected (or (= 2) (= 0)) but got ${args.length}.`
|
145
|
+
)
|
146
|
+
const a = evaluate(args[0], env)
|
147
|
+
if (typeof a !== 'number')
|
148
|
+
throw new TypeError(
|
149
|
+
`First arguments of (${KEYWORDS.MULTIPLICATION}) is not a (${
|
150
|
+
KEYWORDS.NUMBER_TYPE
|
151
|
+
}) (${KEYWORDS.MULTIPLICATION} ${stringifyArgs(args)})`
|
152
|
+
)
|
153
|
+
const b = evaluate(args[1], env)
|
154
|
+
if (typeof b !== 'number')
|
155
|
+
throw new TypeError(
|
156
|
+
`Second arguments of (${KEYWORDS.MULTIPLICATION}) is not a (${
|
157
|
+
KEYWORDS.NUMBER_TYPE
|
158
|
+
}) (${KEYWORDS.MULTIPLICATION} ${stringifyArgs(args)})`
|
159
|
+
)
|
160
|
+
return a * b
|
161
|
+
},
|
162
|
+
[KEYWORDS.SUBTRACTION]: (args, env) => {
|
163
|
+
if (args.length !== 1 && args.length !== 2)
|
164
|
+
throw new RangeError(
|
165
|
+
`Invalid number of arguments for (${
|
166
|
+
KEYWORDS.SUBTRACTION
|
167
|
+
}), expected (or (= 1)) (= 2) but got ${args.length}. (${
|
168
|
+
KEYWORDS.SUBTRACTION
|
169
|
+
} ${stringifyArgs(args)})`
|
170
|
+
)
|
171
|
+
const a = evaluate(args[0], env)
|
172
|
+
if (typeof a !== 'number')
|
173
|
+
throw new TypeError(
|
174
|
+
`First argument of (${KEYWORDS.SUBTRACTION}) is not a (${
|
175
|
+
KEYWORDS.NUMBER_TYPE
|
176
|
+
}) (${KEYWORDS.SUBTRACTION} ${stringifyArgs(args)})`
|
177
|
+
)
|
178
|
+
if (args.length === 1) return -a
|
179
|
+
const b = evaluate(args[1], env)
|
180
|
+
if (typeof b !== 'number')
|
181
|
+
throw new TypeError(
|
182
|
+
`Second argument of (${KEYWORDS.SUBTRACTION}) is not a (${
|
183
|
+
KEYWORDS.NUMBER_TYPE
|
184
|
+
}) (${KEYWORDS.SUBTRACTION} ${stringifyArgs(args)})`
|
185
|
+
)
|
186
|
+
return a - b
|
187
|
+
},
|
188
|
+
[KEYWORDS.IF]: (args, env) => {
|
189
|
+
if (args.length > 3 || args.length < 2)
|
190
|
+
throw new RangeError(
|
191
|
+
`Invalid number of arguments for (${
|
192
|
+
KEYWORDS.IF
|
193
|
+
}), expected (or (= 3) (= 2)) but got ${args.length} (${
|
194
|
+
KEYWORDS.IF
|
195
|
+
} ${stringifyArgs(args)})`
|
196
|
+
)
|
197
|
+
const condition = evaluate(args[0], env)
|
198
|
+
if (condition !== FALSE && condition !== TRUE)
|
199
|
+
throw new TypeError(
|
200
|
+
`Condition of (${KEYWORDS.IF}) must be ${TRUE} or ${FALSE} but got (${
|
201
|
+
KEYWORDS.IF
|
202
|
+
} ${stringifyArgs(args)})`
|
203
|
+
)
|
204
|
+
return condition
|
205
|
+
? evaluate(args[1], env)
|
206
|
+
: args.length === 3
|
207
|
+
? evaluate(args[2], env)
|
208
|
+
: 0
|
209
|
+
},
|
210
|
+
[KEYWORDS.ARRAY_TYPE]: (args, env) => {
|
211
|
+
return args.length ? args.map((x) => evaluate(x, env)) : []
|
212
|
+
},
|
213
|
+
[KEYWORDS.GET_ARRAY]: (args, env) => {
|
214
|
+
if (args.length !== 2)
|
215
|
+
throw new RangeError(
|
216
|
+
`Invalid number of arguments for (${
|
217
|
+
KEYWORDS.GET_ARRAY
|
218
|
+
}) (= 2 required) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
219
|
+
)
|
220
|
+
const array = evaluate(args[0], env)
|
221
|
+
if (!Array.isArray(array))
|
222
|
+
throw new TypeError(
|
223
|
+
`First argument of (${KEYWORDS.GET_ARRAY}) must be an (${
|
224
|
+
KEYWORDS.ARRAY_TYPE
|
225
|
+
})) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
226
|
+
)
|
227
|
+
if (array.length === 0)
|
228
|
+
throw new RangeError(
|
229
|
+
`First argument of (${KEYWORDS.GET_ARRAY}) is an empty (${
|
230
|
+
KEYWORDS.ARRAY_TYPE
|
231
|
+
})) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)}))`
|
232
|
+
)
|
233
|
+
const index = evaluate(args[1], env)
|
234
|
+
if (!Number.isInteger(index))
|
235
|
+
throw new TypeError(
|
236
|
+
`Second argument of (${KEYWORDS.GET_ARRAY}) must be an (32 bit ${
|
237
|
+
KEYWORDS.NUMBER_TYPE
|
238
|
+
}) (${index}) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
239
|
+
)
|
240
|
+
if (index > array.length - 1 || index * -1 > array.length)
|
241
|
+
throw new RangeError(
|
242
|
+
`Second argument of (${KEYWORDS.GET_ARRAY}) is outside of (${
|
243
|
+
KEYWORDS.ARRAY_TYPE
|
244
|
+
}) bounds (${index}) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
245
|
+
)
|
246
|
+
const value = array.at(index)
|
247
|
+
if (value == undefined)
|
248
|
+
throw new RangeError(
|
249
|
+
`Trying to get a null value in (${KEYWORDS.ARRAY_TYPE}) at (${
|
250
|
+
KEYWORDS.GET_ARRAY
|
251
|
+
}) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
252
|
+
)
|
253
|
+
return value
|
254
|
+
},
|
255
|
+
[KEYWORDS.BLOCK]: (args, env) => {
|
256
|
+
if (!args.length)
|
257
|
+
throw new RangeError(
|
258
|
+
`Invalid number of arguments to (${KEYWORDS.BLOCK}) (>= 1 required) (${
|
259
|
+
KEYWORDS.BLOCK
|
260
|
+
} ${stringifyArgs(args)})`
|
261
|
+
)
|
262
|
+
return args.reduce((_, x) => evaluate(x, env), 0)
|
263
|
+
},
|
264
|
+
[KEYWORDS.ANONYMOUS_FUNCTION]: (args, env) => {
|
265
|
+
const params = args.slice(0, -1)
|
266
|
+
const body = args.at(-1)
|
267
|
+
return (props = [], scope) => {
|
268
|
+
if (props.length !== params.length)
|
269
|
+
throw new RangeError(
|
270
|
+
`Incorrect number of arguments for (${
|
271
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
272
|
+
} ${stringifyArgs(params)}) are provided. (expects ${
|
273
|
+
params.length
|
274
|
+
} but got ${props.length}) (${
|
275
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
276
|
+
} ${stringifyArgs(args)})`
|
277
|
+
)
|
278
|
+
const localEnv = Object.create(env)
|
279
|
+
// localEnv[KEYWORDS.BLOCK] = block[KEYWORDS.BLOCK]
|
280
|
+
for (let i = 0; i < props.length; ++i) {
|
281
|
+
const value = evaluate(props[i], scope)
|
282
|
+
Object.defineProperty(localEnv, params[i][VALUE], {
|
283
|
+
value,
|
284
|
+
writable: true
|
285
|
+
})
|
286
|
+
}
|
287
|
+
return evaluate(body, localEnv)
|
288
|
+
}
|
289
|
+
},
|
290
|
+
[KEYWORDS.NOT]: (args, env) => {
|
291
|
+
if (args.length !== 1)
|
292
|
+
throw new RangeError(
|
293
|
+
`Invalid number of arguments for (${KEYWORDS.NOT}) (= 1 required) (${
|
294
|
+
KEYWORDS.NOT
|
295
|
+
} ${stringifyArgs(args)})`
|
296
|
+
)
|
297
|
+
return +!evaluate(args[0], env)
|
298
|
+
},
|
299
|
+
[KEYWORDS.EQUAL]: (args, env) => {
|
300
|
+
if (args.length !== 2)
|
301
|
+
throw new RangeError(
|
302
|
+
`Invalid number of arguments for (${KEYWORDS.EQUAL}) (= 2 required) (${
|
303
|
+
KEYWORDS.EQUAL
|
304
|
+
} ${stringifyArgs(args)})`
|
305
|
+
)
|
306
|
+
const a = evaluate(args[0], env)
|
307
|
+
const b = evaluate(args[1], env)
|
308
|
+
if (typeof a !== 'number')
|
309
|
+
throw new TypeError(
|
310
|
+
`Invalid use of (${KEYWORDS.EQUAL}), first argument is not an ${
|
311
|
+
KEYWORDS.NUMBER_TYPE
|
312
|
+
} (${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
|
313
|
+
)
|
314
|
+
if (typeof b !== 'number')
|
315
|
+
throw new TypeError(
|
316
|
+
`Invalid use of (${KEYWORDS.EQUAL}), second argument are not an ${
|
317
|
+
KEYWORDS.NUMBER_TYPE
|
318
|
+
} (${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
|
319
|
+
)
|
320
|
+
return +(a === b)
|
321
|
+
},
|
322
|
+
[KEYWORDS.LESS_THAN]: (args, env) => {
|
323
|
+
if (args.length !== 2)
|
324
|
+
throw new RangeError(
|
325
|
+
`Invalid number of arguments for (${
|
326
|
+
KEYWORDS.LESS_THAN
|
327
|
+
}) (= 2 required) (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
|
328
|
+
)
|
329
|
+
const a = evaluate(args[0], env)
|
330
|
+
const b = evaluate(args[1], env)
|
331
|
+
if (typeof a !== 'number')
|
332
|
+
throw new TypeError(
|
333
|
+
`Invalid use of (${KEYWORDS.LESS_THAN}), first argument is not an ${
|
334
|
+
KEYWORDS.NUMBER_TYPE
|
335
|
+
} (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
|
336
|
+
)
|
337
|
+
if (typeof b !== 'number')
|
338
|
+
throw new TypeError(
|
339
|
+
`Invalid use of (${KEYWORDS.LESS_THAN}), second argument are not an ${
|
340
|
+
KEYWORDS.NUMBER_TYPE
|
341
|
+
} (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
|
342
|
+
)
|
343
|
+
return +(a < b)
|
344
|
+
},
|
345
|
+
[KEYWORDS.GREATHER_THAN]: (args, env) => {
|
346
|
+
if (args.length !== 2)
|
347
|
+
throw new RangeError(
|
348
|
+
`Invalid number of arguments for (${
|
349
|
+
KEYWORDS.GREATHER_THAN
|
350
|
+
}) (= 2 required) (${KEYWORDS.GREATHER_THAN} ${stringifyArgs(args)})`
|
351
|
+
)
|
352
|
+
const a = evaluate(args[0], env)
|
353
|
+
const b = evaluate(args[1], env)
|
354
|
+
if (typeof a !== 'number')
|
355
|
+
throw new TypeError(
|
356
|
+
`Invalid use of (${KEYWORDS.GREATHER_THAN}), first argument is not an ${
|
357
|
+
KEYWORDS.NUMBER_TYPE
|
358
|
+
} (${KEYWORDS.GREATHER_THAN} ${stringifyArgs(args)})`
|
359
|
+
)
|
360
|
+
if (typeof b !== 'number')
|
361
|
+
throw new TypeError(
|
362
|
+
`Invalid use of (${
|
363
|
+
KEYWORDS.GREATHER_THAN
|
364
|
+
}), second argument are not an ${KEYWORDS.NUMBER_TYPE} (${
|
365
|
+
KEYWORDS.GREATHER_THAN
|
366
|
+
} ${stringifyArgs(args)})`
|
367
|
+
)
|
368
|
+
return +(a > b)
|
369
|
+
},
|
370
|
+
[KEYWORDS.GREATHER_THAN_OR_EQUAL]: (args, env) => {
|
371
|
+
if (args.length !== 2)
|
372
|
+
throw new RangeError(
|
373
|
+
`Invalid number of arguments for (${
|
374
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL
|
375
|
+
}) (= 2 required) (${KEYWORDS.GREATHER_THAN_OR_EQUAL} ${stringifyArgs(
|
376
|
+
args
|
377
|
+
)})`
|
378
|
+
)
|
379
|
+
const a = evaluate(args[0], env)
|
380
|
+
const b = evaluate(args[1], env)
|
381
|
+
if (typeof a !== 'number')
|
382
|
+
throw new TypeError(
|
383
|
+
`Invalid use of (${
|
384
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL
|
385
|
+
}), first argument is not an ${KEYWORDS.NUMBER_TYPE} (${
|
386
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL
|
387
|
+
} ${stringifyArgs(args)})`
|
388
|
+
)
|
389
|
+
if (typeof b !== 'number')
|
390
|
+
throw new TypeError(
|
391
|
+
`Invalid use of (${
|
392
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL
|
393
|
+
}), second argument are not an ${KEYWORDS.NUMBER_TYPE} (${
|
394
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL
|
395
|
+
} ${stringifyArgs(args)})`
|
396
|
+
)
|
397
|
+
return +(a >= b)
|
398
|
+
},
|
399
|
+
[KEYWORDS.LESS_THAN_OR_EQUAL]: (args, env) => {
|
400
|
+
if (args.length !== 2)
|
401
|
+
throw new RangeError(
|
402
|
+
`Invalid number of arguments for (${
|
403
|
+
KEYWORDS.LESS_THAN_OR_EQUAL
|
404
|
+
}) (= 2 required) (${KEYWORDS.LESS_THAN_OR_EQUAL} ${stringifyArgs(
|
405
|
+
args
|
406
|
+
)})`
|
407
|
+
)
|
408
|
+
const a = evaluate(args[0], env)
|
409
|
+
const b = evaluate(args[1], env)
|
410
|
+
if (typeof a !== 'number')
|
411
|
+
throw new TypeError(
|
412
|
+
`Invalid use of (${
|
413
|
+
KEYWORDS.LESS_THAN_OR_EQUAL
|
414
|
+
}), first argument is not an ${KEYWORDS.NUMBER_TYPE} (${
|
415
|
+
KEYWORDS.LESS_THAN_OR_EQUAL
|
416
|
+
} ${stringifyArgs(args)})`
|
417
|
+
)
|
418
|
+
if (typeof b !== 'number')
|
419
|
+
throw new TypeError(
|
420
|
+
`Invalid use of (${
|
421
|
+
KEYWORDS.LESS_THAN_OR_EQUAL
|
422
|
+
}), second argument are not an ${KEYWORDS.NUMBER_TYPE} (${
|
423
|
+
KEYWORDS.LESS_THAN_OR_EQUAL
|
424
|
+
} ${stringifyArgs(args)})`
|
425
|
+
)
|
426
|
+
return +(a <= b)
|
427
|
+
},
|
428
|
+
[KEYWORDS.AND]: (args, env) => {
|
429
|
+
if (args.length !== 2)
|
430
|
+
throw new RangeError(
|
431
|
+
`Invalid number of arguments for (${KEYWORDS.AND}) (= 2 required) (${
|
432
|
+
KEYWORDS.AND
|
433
|
+
} ${stringifyArgs(args)})`
|
434
|
+
)
|
435
|
+
let circuit
|
436
|
+
for (let i = 0; i < args.length - 1; ++i) {
|
437
|
+
circuit = evaluate(args[i], env)
|
438
|
+
if (circuit !== FALSE && circuit !== TRUE)
|
439
|
+
throw new TypeError(
|
440
|
+
`Condition of (${
|
441
|
+
KEYWORDS.AND
|
442
|
+
}) must be ${TRUE} or ${FALSE} but got (${
|
443
|
+
KEYWORDS.AND
|
444
|
+
} ${stringifyArgs(args)})`
|
445
|
+
)
|
446
|
+
if (circuit) continue
|
447
|
+
else return 0
|
448
|
+
}
|
449
|
+
const end = evaluate(args.at(-1), env)
|
450
|
+
if (end !== FALSE && end !== TRUE)
|
451
|
+
throw new TypeError(
|
452
|
+
`Condition of (${KEYWORDS.AND}) must be ${TRUE} or ${FALSE} but got (${
|
453
|
+
KEYWORDS.AND
|
454
|
+
} ${stringifyArgs(args)})`
|
455
|
+
)
|
456
|
+
return end
|
457
|
+
},
|
458
|
+
[KEYWORDS.OR]: (args, env) => {
|
459
|
+
if (args.length !== 2)
|
460
|
+
throw new RangeError(
|
461
|
+
`Invalid number of arguments for (${KEYWORDS.OR}) (= 2 required) (${
|
462
|
+
KEYWORDS.OR
|
463
|
+
} ${stringifyArgs(args)})`
|
464
|
+
)
|
465
|
+
let circuit
|
466
|
+
for (let i = 0; i < args.length - 1; ++i) {
|
467
|
+
circuit = evaluate(args[i], env)
|
468
|
+
if (circuit !== FALSE && circuit !== TRUE)
|
469
|
+
throw new TypeError(
|
470
|
+
`Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got (${
|
471
|
+
KEYWORDS.OR
|
472
|
+
} ${stringifyArgs(args)})`
|
473
|
+
)
|
474
|
+
if (circuit) return 1
|
475
|
+
else continue
|
476
|
+
}
|
477
|
+
const end = evaluate(args.at(-1), env)
|
478
|
+
if (end !== FALSE && end !== TRUE)
|
479
|
+
throw new TypeError(
|
480
|
+
`Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got (${
|
481
|
+
KEYWORDS.OR
|
482
|
+
} ${stringifyArgs(args)})`
|
483
|
+
)
|
484
|
+
return end
|
485
|
+
},
|
486
|
+
[KEYWORDS.CALL_FUNCTION]: (args, env) => {
|
487
|
+
if (!args.length)
|
488
|
+
throw new RangeError(
|
489
|
+
`Invalid number of arguments to (${
|
490
|
+
KEYWORDS.CALL_FUNCTION
|
491
|
+
}) (>= 1 required) (${KEYWORDS.CALL_FUNCTION} ${stringifyArgs(args)})`
|
492
|
+
)
|
493
|
+
const [first, ...rest] = args
|
494
|
+
if (first[TYPE] === WORD && first[VALUE] in keywords)
|
495
|
+
throw new TypeError(
|
496
|
+
`Following argument of (${
|
497
|
+
KEYWORDS.CALL_FUNCTION
|
498
|
+
}) must not be an reserved word (${
|
499
|
+
KEYWORDS.CALL_FUNCTION
|
500
|
+
} ${stringifyArgs(args)})`
|
501
|
+
)
|
502
|
+
const apply = evaluate(first, env)
|
503
|
+
if (typeof apply !== 'function')
|
504
|
+
throw new TypeError(
|
505
|
+
`First argument of (${KEYWORDS.CALL_FUNCTION}) must be a (${
|
506
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
507
|
+
}) (${KEYWORDS.CALL_FUNCTION} ${stringifyArgs(args)})`
|
508
|
+
)
|
509
|
+
|
510
|
+
return apply(rest, env)
|
511
|
+
},
|
512
|
+
[KEYWORDS.DEFINE_VARIABLE]: (args, env) => {
|
513
|
+
if (args.length !== 2)
|
514
|
+
throw new RangeError(
|
515
|
+
`Invalid number of arguments to (${
|
516
|
+
KEYWORDS.DEFINE_VARIABLE
|
517
|
+
}) (= 2 required) (${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(args)})`
|
518
|
+
)
|
519
|
+
const word = args[0]
|
520
|
+
const type = word[TYPE]
|
521
|
+
const name = word[VALUE]
|
522
|
+
if (type !== WORD)
|
523
|
+
throw new SyntaxError(
|
524
|
+
`First argument of (${KEYWORDS.DEFINE_VARIABLE}) must be word but got ${
|
525
|
+
TYPES[type]
|
526
|
+
} (${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(args)})`
|
527
|
+
)
|
528
|
+
else if (isForbiddenVariableName(name))
|
529
|
+
throw new ReferenceError(
|
530
|
+
`Variable name ${name} is forbidden at (${
|
531
|
+
KEYWORDS.DEFINE_VARIABLE
|
532
|
+
} ${stringifyArgs(args)})`
|
533
|
+
)
|
534
|
+
Object.defineProperty(env, name, {
|
535
|
+
value: evaluate(args[1], env),
|
536
|
+
writable: false
|
537
|
+
})
|
538
|
+
return env[name]
|
539
|
+
},
|
540
|
+
[KEYWORDS.BITWISE_AND]: (args, env) => {
|
541
|
+
if (args.length < 2)
|
542
|
+
throw new RangeError(
|
543
|
+
`Invalid number of arguments to (${
|
544
|
+
KEYWORDS.BITWISE_AND
|
545
|
+
}) (= 2 required). (${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
|
546
|
+
)
|
547
|
+
const operands = args.map((a) => evaluate(a, env))
|
548
|
+
if (operands.some((x) => typeof x !== 'number'))
|
549
|
+
throw new TypeError(
|
550
|
+
`Not all arguments of (${KEYWORDS.BITWISE_AND}) are ${
|
551
|
+
KEYWORDS.NUMBER_TYPE
|
552
|
+
} (${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
|
553
|
+
)
|
554
|
+
return operands.reduce((acc, x) => acc & x)
|
555
|
+
},
|
556
|
+
[KEYWORDS.BITWISE_NOT]: (args, env) => {
|
557
|
+
if (args.length !== 1)
|
558
|
+
throw new RangeError(
|
559
|
+
`Invalid number of arguments to (${
|
560
|
+
KEYWORDS.BITWISE_NOT
|
561
|
+
}) (= 1 required). (${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)})`
|
562
|
+
)
|
563
|
+
const operand = evaluate(args[0], env)
|
564
|
+
if (typeof operand !== 'number')
|
565
|
+
throw new TypeError(
|
566
|
+
`Argument of (${KEYWORDS.BITWISE_NOT}) is not a (${
|
567
|
+
KEYWORDS.NUMBER_TYPE
|
568
|
+
}) (${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)})`
|
569
|
+
)
|
570
|
+
return ~operand
|
571
|
+
},
|
572
|
+
[KEYWORDS.BITWISE_OR]: (args, env) => {
|
573
|
+
if (args.length !== 2)
|
574
|
+
throw new RangeError(
|
575
|
+
`Invalid number of arguments to (${
|
576
|
+
KEYWORDS.BITWISE_OR
|
577
|
+
}) (= 2 required). (${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)})`
|
578
|
+
)
|
579
|
+
const a = evaluate(args[0], env)
|
580
|
+
const b = evaluate(args[1], env)
|
581
|
+
if (typeof a !== 'number' || typeof b !== 'number')
|
582
|
+
throw new TypeError(
|
583
|
+
`Not all arguments of (${KEYWORDS.BITWISE_OR}) are (${
|
584
|
+
KEYWORDS.NUMBER_TYPE
|
585
|
+
}) (${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)})`
|
586
|
+
)
|
587
|
+
return a | b
|
588
|
+
},
|
589
|
+
[KEYWORDS.BITWISE_XOR]: (args, env) => {
|
590
|
+
if (args.length !== 2)
|
591
|
+
throw new RangeError(
|
592
|
+
`Invalid number of arguments to (${
|
593
|
+
KEYWORDS.BITWISE_XOR
|
594
|
+
}) (= 2 required). (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
|
595
|
+
)
|
596
|
+
const a = evaluate(args[0], env)
|
597
|
+
const b = evaluate(args[1], env)
|
598
|
+
if (typeof a !== 'number' || typeof b !== 'number')
|
599
|
+
throw new TypeError(
|
600
|
+
`Not all arguments of (${KEYWORDS.BITWISE_XOR}) are (${
|
601
|
+
KEYWORDS.NUMBER_TYPE
|
602
|
+
}) (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
|
603
|
+
)
|
604
|
+
return a ^ b
|
605
|
+
},
|
606
|
+
[KEYWORDS.BITWISE_LEFT_SHIFT]: (args, env) => {
|
607
|
+
if (args.length !== 2)
|
608
|
+
throw new RangeError(
|
609
|
+
`Invalid number of arguments to (${
|
610
|
+
KEYWORDS.BITWISE_LEFT_SHIFT
|
611
|
+
}) (= 2 required). (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(
|
612
|
+
args
|
613
|
+
)})`
|
614
|
+
)
|
615
|
+
const a = evaluate(args[0], env)
|
616
|
+
const b = evaluate(args[1], env)
|
617
|
+
if (typeof a !== 'number' || typeof b !== 'number')
|
618
|
+
throw new TypeError(
|
619
|
+
`Not all arguments of (${KEYWORDS.BITWISE_LEFT_SHIFT}) are (${
|
620
|
+
KEYWORDS.NUMBER_TYPE
|
621
|
+
}) (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(args)})`
|
622
|
+
)
|
623
|
+
return a << b
|
624
|
+
},
|
625
|
+
[KEYWORDS.BITWISE_RIGHT_SHIFT]: (args, env) => {
|
626
|
+
if (args.length !== 2)
|
627
|
+
throw new RangeError(
|
628
|
+
`Invalid number of arguments to (${
|
629
|
+
KEYWORDS.BITWISE_RIGHT_SHIFT
|
630
|
+
}) (= 2 required). (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(
|
631
|
+
args
|
632
|
+
)})`
|
633
|
+
)
|
634
|
+
const a = evaluate(args[0], env)
|
635
|
+
const b = evaluate(args[1], env)
|
636
|
+
if (typeof a !== 'number' || typeof b !== 'number')
|
637
|
+
throw new TypeError(
|
638
|
+
`Not all arguments of (${KEYWORDS.BITWISE_RIGHT_SHIFT}) are (${
|
639
|
+
KEYWORDS.NUMBER_TYPE
|
640
|
+
}) (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(args)})`
|
641
|
+
)
|
642
|
+
return a >> b
|
643
|
+
},
|
644
|
+
[KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT]: (args, env) => {
|
645
|
+
if (args.length !== 2)
|
646
|
+
throw new RangeError(
|
647
|
+
`Invalid number of arguments to (${
|
648
|
+
KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT
|
649
|
+
}) (= 2 required). (${
|
650
|
+
KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT
|
651
|
+
} ${stringifyArgs(args)})`
|
652
|
+
)
|
653
|
+
const a = evaluate(args[0], env)
|
654
|
+
const b = evaluate(args[1], env)
|
655
|
+
if (typeof a !== 'number' || typeof b !== 'number')
|
656
|
+
throw new TypeError(
|
657
|
+
`Not all arguments of (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT}) are (${
|
658
|
+
KEYWORDS.NUMBER_TYPE
|
659
|
+
}) (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT} ${stringifyArgs(args)})`
|
660
|
+
)
|
661
|
+
return a >>> b
|
662
|
+
},
|
663
|
+
[KEYWORDS.SET_ARRAY]: (args, env) => {
|
664
|
+
if (args.length !== 1 && args.length !== 3)
|
665
|
+
throw new RangeError(
|
666
|
+
`Invalid number of arguments for (${
|
667
|
+
KEYWORDS.SET_ARRAY
|
668
|
+
}) (or 1 3) required (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
|
669
|
+
)
|
670
|
+
const array = evaluate(args[0], env)
|
671
|
+
if (!Array.isArray(array))
|
672
|
+
throw new TypeError(
|
673
|
+
`First argument of (${KEYWORDS.SET_ARRAY}) must be an (${
|
674
|
+
KEYWORDS.ARRAY_TYPE
|
675
|
+
}) but got (${array}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
|
676
|
+
)
|
677
|
+
if (args.length === 1) {
|
678
|
+
array.pop()
|
679
|
+
} else {
|
680
|
+
const index = evaluate(args[1], env)
|
681
|
+
if (!Number.isInteger(index) || index < 0)
|
682
|
+
throw new TypeError(
|
683
|
+
`Second argument of (${KEYWORDS.SET_ARRAY}) must be a positive (${
|
684
|
+
KEYWORDS.NUMBER_TYPE
|
685
|
+
} integer) (${index}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
|
686
|
+
)
|
687
|
+
if (index > array.length)
|
688
|
+
throw new RangeError(
|
689
|
+
`Second argument of (${KEYWORDS.SET_ARRAY}) is outside of the (${
|
690
|
+
KEYWORDS.ARRAY_TYPE
|
691
|
+
}) bounds (index ${index} bounds ${array.length}) (${
|
692
|
+
KEYWORDS.SET_ARRAY
|
693
|
+
} ${stringifyArgs(args)})`
|
694
|
+
)
|
695
|
+
const value = evaluate(args[2], env)
|
696
|
+
if (value == undefined)
|
697
|
+
throw new RangeError(
|
698
|
+
`Trying to set a null value in (${KEYWORDS.ARRAY_TYPE}) at (${
|
699
|
+
KEYWORDS.SET_ARRAY
|
700
|
+
}). (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
|
701
|
+
)
|
702
|
+
array[index] = value
|
703
|
+
}
|
704
|
+
return array
|
705
|
+
},
|
706
|
+
[KEYWORDS.LOG]: (args, env) => {
|
707
|
+
if (args.length !== 1)
|
708
|
+
throw new RangeError(
|
709
|
+
`Invalid number of arguments to (${KEYWORDS.LOG}) (= 1 required) (${
|
710
|
+
KEYWORDS.LOG
|
711
|
+
} ${stringifyArgs(args)})`
|
712
|
+
)
|
713
|
+
const expression = evaluate(args[0], env)
|
714
|
+
console.log(expression)
|
715
|
+
return expression
|
716
|
+
},
|
717
|
+
[KEYWORDS.LOG_STRING]: (args, env) => {
|
718
|
+
if (args.length !== 1)
|
719
|
+
throw new RangeError(
|
720
|
+
`Invalid number of arguments to (${
|
721
|
+
KEYWORDS.LOG_STRING
|
722
|
+
}) (= 1 required) (${KEYWORDS.LOG_STRING} ${stringifyArgs(args)})`
|
723
|
+
)
|
724
|
+
const expression = evaluate(args[0], env)
|
725
|
+
if (!Array.isArray(expression))
|
726
|
+
throw new TypeError(
|
727
|
+
`Argument of (${KEYWORDS.LOG_STRING}) must be an (${
|
728
|
+
KEYWORDS.ARRAY_TYPE
|
729
|
+
}) but got (${expression}) (${KEYWORDS.LOG_STRING} ${stringifyArgs(
|
730
|
+
args
|
731
|
+
)})`
|
732
|
+
)
|
733
|
+
console.log(expression.map((x) => String.fromCharCode(x)).join(''))
|
734
|
+
return expression
|
735
|
+
},
|
736
|
+
[KEYWORDS.LOG_CHAR]: (args, env) => {
|
737
|
+
if (args.length !== 1)
|
738
|
+
throw new RangeError(
|
739
|
+
`Invalid number of arguments to (${
|
740
|
+
KEYWORDS.LOG_CHAR
|
741
|
+
}) (= 1 required) (${KEYWORDS.LOG_CHAR} ${stringifyArgs(args)})`
|
742
|
+
)
|
743
|
+
const expression = evaluate(args[0], env)
|
744
|
+
if (typeof expression !== 'number')
|
745
|
+
throw new TypeError(
|
746
|
+
`Argument of (${KEYWORDS.LOG_CHAR}) must be a (${
|
747
|
+
KEYWORDS.NUMBER_TYPE
|
748
|
+
}) but got (${expression}) (${KEYWORDS.LOG_CHAR} ${stringifyArgs(
|
749
|
+
args
|
750
|
+
)})`
|
751
|
+
)
|
752
|
+
console.log(String.fromCharCode(expression))
|
753
|
+
return expression
|
754
|
+
},
|
755
|
+
[KEYWORDS.CLEAR_CONSOLE]: (args) => {
|
756
|
+
if (args.length)
|
757
|
+
throw new RangeError(
|
758
|
+
`Invalid number of arguments to (${
|
759
|
+
KEYWORDS.CLEAR_CONSOLE
|
760
|
+
}) (= 0 required) (${KEYWORDS.CLEAR_CONSOLE} ${stringifyArgs(args)})`
|
761
|
+
)
|
762
|
+
console.clear()
|
763
|
+
return 0
|
764
|
+
},
|
765
|
+
|
766
|
+
// Not sure about these
|
767
|
+
[KEYWORDS.THROW]: (args, env) => {
|
768
|
+
if (args.length !== 1)
|
769
|
+
throw new RangeError(
|
770
|
+
`Invalid number of arguments to (${KEYWORDS.THROW}) (= 1 required) (${
|
771
|
+
KEYWORDS.THROW
|
772
|
+
} ${stringifyArgs(args)})`
|
773
|
+
)
|
774
|
+
const expression = evaluate(args[0], env)
|
775
|
+
if (!Array.isArray(expression))
|
776
|
+
throw new TypeError(
|
777
|
+
`Argument of (${KEYWORDS.THROW}) must be an (${
|
778
|
+
KEYWORDS.ARRAY_TYPE
|
779
|
+
}) but got (${expression}) (${KEYWORDS.THROW} ${stringifyArgs(args)})`
|
780
|
+
)
|
781
|
+
throw new Error(expression.map((x) => String.fromCharCode(x)).join(''))
|
782
|
+
}
|
783
|
+
}
|