fez-lisp 1.3.0 → 1.3.2
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/macros.js +169 -0
- package/lib/baked/std.js +1 -1
- package/package.json +2 -3
- package/src/compiler.js +27 -24
- package/src/interpreter.js +32 -56
- package/src/keywords.js +0 -13
- package/src/macros.js +408 -0
- package/src/utils.js +13 -515
package/src/utils.js
CHANGED
@@ -1,41 +1,17 @@
|
|
1
1
|
import std from '../lib/baked/std.js'
|
2
2
|
import { comp } from './compiler.js'
|
3
|
-
import {
|
4
|
-
APPLY,
|
5
|
-
ATOM,
|
6
|
-
FALSE,
|
7
|
-
KEYWORDS,
|
8
|
-
SUGGAR,
|
9
|
-
TRUE,
|
10
|
-
TYPE,
|
11
|
-
VALUE,
|
12
|
-
WORD
|
13
|
-
} from './keywords.js'
|
3
|
+
import { APPLY, ATOM, KEYWORDS, TYPE, VALUE, WORD } from './keywords.js'
|
14
4
|
import { evaluate, run } from './evaluator.js'
|
15
5
|
import { AST, isLeaf, LISP } from './parser.js'
|
6
|
+
import {
|
7
|
+
deSuggarAst,
|
8
|
+
deSuggarSource,
|
9
|
+
handleUnbalancedQuotes,
|
10
|
+
SUGGAR
|
11
|
+
} from './macros.js'
|
16
12
|
export const logError = (error) =>
|
17
13
|
console.log('\x1b[31m', `\n${error}\n`, '\x1b[0m')
|
18
14
|
export const logSuccess = (output) => console.log(output, '\x1b[0m')
|
19
|
-
export const replaceStrings = (source) => {
|
20
|
-
// const quotes = source.match(/"(.*?)"/g)
|
21
|
-
const quotes = source.match(/"(?:.*?(\n|\r))*?.*?"/g)
|
22
|
-
// TODO handle escaping
|
23
|
-
if (quotes)
|
24
|
-
for (const q of quotes)
|
25
|
-
source = source.replaceAll(
|
26
|
-
q,
|
27
|
-
`(array ${[...q.replaceAll('\r', '')]
|
28
|
-
.slice(1, -1)
|
29
|
-
.map((x) => x.charCodeAt(0))
|
30
|
-
.join(' ')})`
|
31
|
-
)
|
32
|
-
return source
|
33
|
-
}
|
34
|
-
export const replaceQuotes = (source) =>
|
35
|
-
source
|
36
|
-
.replaceAll(/\'\(/g, '(array ')
|
37
|
-
.replaceAll(/\`\(/g, '(list ')
|
38
|
-
.replaceAll(/\(\)/g, '(array)')
|
39
15
|
// export const replaceEmptyArrays = (source) =>
|
40
16
|
// source
|
41
17
|
export const removeNoCode = (source) =>
|
@@ -167,11 +143,6 @@ export const handleUnbalancedParens = (source) => {
|
|
167
143
|
)
|
168
144
|
return source
|
169
145
|
}
|
170
|
-
export const handleUnbalancedQuotes = (source) => {
|
171
|
-
const diff = (source.match(/\"/g) ?? []).length % 2
|
172
|
-
if (diff !== 0) throw new SyntaxError(`Quotes are unbalanced "`)
|
173
|
-
return source
|
174
|
-
}
|
175
146
|
export const removeMutation = (source) => source.replace(new RegExp(/!/g), 'ǃ')
|
176
147
|
const isDefinition = (x) =>
|
177
148
|
x[TYPE] === APPLY && x[VALUE] === KEYWORDS.DEFINE_VARIABLE
|
@@ -245,13 +216,13 @@ export const fez = (source, options = {}) => {
|
|
245
216
|
const env = Object.create(null)
|
246
217
|
try {
|
247
218
|
if (typeof source === 'string') {
|
248
|
-
source =
|
219
|
+
source = deSuggarSource(source)
|
249
220
|
const valid = handleUnbalancedQuotes(
|
250
221
|
handleUnbalancedParens(removeNoCode(source))
|
251
222
|
)
|
252
223
|
const code = !options.mutation ? removeMutation(valid) : valid
|
253
224
|
if (!code.length && options.throw) throw new Error('Nothing to parse!')
|
254
|
-
const parsed =
|
225
|
+
const parsed = deSuggarAst(LISP.parse(code))
|
255
226
|
const ast = [...treeShake(parsed, std), ...parsed]
|
256
227
|
// if (options.check) typeCheck(ast)
|
257
228
|
if (options.compile) return comp(ast)
|
@@ -309,17 +280,12 @@ export const decompress = (raw) => {
|
|
309
280
|
export const shake = (parsed, std) => [...treeShake(parsed, std), ...parsed]
|
310
281
|
export const tree = (source, std) =>
|
311
282
|
std
|
312
|
-
? shake(
|
313
|
-
|
314
|
-
std
|
315
|
-
)
|
316
|
-
: LISP.parse(replaceQuotes(replaceStrings(removeNoCode(source))))
|
283
|
+
? shake(LISP.parse(deSuggarSource(removeNoCode(source))), std)
|
284
|
+
: LISP.parse(deSuggarSource(removeNoCode(source)))
|
317
285
|
export const minify = (source) =>
|
318
|
-
LISP.source(
|
319
|
-
deSuggar(LISP.parse(replaceQuotes(replaceStrings(removeNoCode(source)))))
|
320
|
-
)
|
286
|
+
LISP.source(deSuggarAst(LISP.parse(deSuggarSource(removeNoCode(source)))))
|
321
287
|
export const prep = (source) =>
|
322
|
-
|
288
|
+
deSuggarAst(LISP.parse(removeNoCode(deSuggarSource(source))))
|
323
289
|
export const src = (source, deps) => {
|
324
290
|
source = prep(source)
|
325
291
|
return LISP.source([
|
@@ -362,471 +328,3 @@ export const js = (source, deps) => {
|
|
362
328
|
])
|
363
329
|
return `${top}${program}`
|
364
330
|
}
|
365
|
-
const EXPONENTIATION = [
|
366
|
-
[0, 'lambda'],
|
367
|
-
[1, 'base'],
|
368
|
-
[1, 'exp'],
|
369
|
-
[
|
370
|
-
[0, 'do'],
|
371
|
-
[
|
372
|
-
[0, 'let'],
|
373
|
-
[1, 'power'],
|
374
|
-
[
|
375
|
-
[0, 'lambda'],
|
376
|
-
[1, 'base'],
|
377
|
-
[1, 'exp'],
|
378
|
-
[
|
379
|
-
[0, 'if'],
|
380
|
-
[
|
381
|
-
[0, '<'],
|
382
|
-
[1, 'exp'],
|
383
|
-
[2, 0]
|
384
|
-
],
|
385
|
-
[
|
386
|
-
[0, 'if'],
|
387
|
-
[
|
388
|
-
[0, '='],
|
389
|
-
[1, 'base'],
|
390
|
-
[2, 0]
|
391
|
-
],
|
392
|
-
[
|
393
|
-
[0, 'throw'],
|
394
|
-
[
|
395
|
-
[0, 'array'],
|
396
|
-
[2, 66],
|
397
|
-
[2, 97],
|
398
|
-
[2, 115],
|
399
|
-
[2, 101],
|
400
|
-
[2, 32],
|
401
|
-
[2, 99],
|
402
|
-
[2, 97],
|
403
|
-
[2, 110],
|
404
|
-
[2, 39],
|
405
|
-
[2, 116],
|
406
|
-
[2, 32],
|
407
|
-
[2, 98],
|
408
|
-
[2, 101],
|
409
|
-
[2, 32],
|
410
|
-
[2, 48],
|
411
|
-
[2, 32],
|
412
|
-
[2, 105],
|
413
|
-
[2, 102],
|
414
|
-
[2, 32],
|
415
|
-
[2, 101],
|
416
|
-
[2, 120],
|
417
|
-
[2, 112],
|
418
|
-
[2, 111],
|
419
|
-
[2, 110],
|
420
|
-
[2, 101],
|
421
|
-
[2, 110],
|
422
|
-
[2, 116],
|
423
|
-
[2, 32],
|
424
|
-
[2, 105],
|
425
|
-
[2, 115],
|
426
|
-
[2, 32],
|
427
|
-
[2, 60],
|
428
|
-
[2, 32],
|
429
|
-
[2, 48]
|
430
|
-
]
|
431
|
-
],
|
432
|
-
[
|
433
|
-
[0, '/'],
|
434
|
-
[
|
435
|
-
[0, '*'],
|
436
|
-
[1, 'base'],
|
437
|
-
[
|
438
|
-
[0, 'power'],
|
439
|
-
[1, 'base'],
|
440
|
-
[
|
441
|
-
[0, '-'],
|
442
|
-
[
|
443
|
-
[0, '*'],
|
444
|
-
[1, 'exp'],
|
445
|
-
[2, -1]
|
446
|
-
],
|
447
|
-
[2, 1]
|
448
|
-
]
|
449
|
-
]
|
450
|
-
]
|
451
|
-
]
|
452
|
-
],
|
453
|
-
[
|
454
|
-
[0, 'if'],
|
455
|
-
[
|
456
|
-
[0, '='],
|
457
|
-
[1, 'exp'],
|
458
|
-
[2, 0]
|
459
|
-
],
|
460
|
-
[2, 1],
|
461
|
-
[
|
462
|
-
[0, 'if'],
|
463
|
-
[
|
464
|
-
[0, '='],
|
465
|
-
[1, 'exp'],
|
466
|
-
[2, 1]
|
467
|
-
],
|
468
|
-
[1, 'base'],
|
469
|
-
[
|
470
|
-
[0, 'if'],
|
471
|
-
[[2, 1]],
|
472
|
-
[
|
473
|
-
[0, '*'],
|
474
|
-
[1, 'base'],
|
475
|
-
[
|
476
|
-
[0, 'power'],
|
477
|
-
[1, 'base'],
|
478
|
-
[
|
479
|
-
[0, '-'],
|
480
|
-
[1, 'exp'],
|
481
|
-
[2, 1]
|
482
|
-
]
|
483
|
-
]
|
484
|
-
]
|
485
|
-
]
|
486
|
-
]
|
487
|
-
]
|
488
|
-
]
|
489
|
-
]
|
490
|
-
],
|
491
|
-
[
|
492
|
-
[0, 'power'],
|
493
|
-
[1, 'base'],
|
494
|
-
[1, 'exp']
|
495
|
-
]
|
496
|
-
]
|
497
|
-
]
|
498
|
-
export const deSuggar = (ast) => {
|
499
|
-
if (ast.length === 0) throw new SyntaxError(`No expressions to evaluate`)
|
500
|
-
// for (const node of ast)
|
501
|
-
// if (node[0] && node[0][TYPE] === APPLY && node[0][VALUE] === KEYWORDS.BLOCK)
|
502
|
-
// throw new SyntaxError(`Top level (${KEYWORDS.BLOCK}) is not allowed`)
|
503
|
-
let prev = undefined
|
504
|
-
const evaluate = (exp) => {
|
505
|
-
const [first, ...rest] = isLeaf(exp) ? [exp] : exp
|
506
|
-
if (first != undefined) {
|
507
|
-
switch (first[TYPE]) {
|
508
|
-
case WORD:
|
509
|
-
{
|
510
|
-
switch (first[VALUE]) {
|
511
|
-
case SUGGAR.POWER:
|
512
|
-
exp.length = 0
|
513
|
-
exp.push(...EXPONENTIATION)
|
514
|
-
break
|
515
|
-
case SUGGAR.INTEGER_DEVISION:
|
516
|
-
exp.length = 0
|
517
|
-
exp.push(
|
518
|
-
...[
|
519
|
-
[APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
|
520
|
-
[WORD, 'a'],
|
521
|
-
[WORD, 'b'],
|
522
|
-
[
|
523
|
-
[APPLY, KEYWORDS.BITWISE_OR],
|
524
|
-
[
|
525
|
-
[APPLY, KEYWORDS.DIVISION],
|
526
|
-
[WORD, 'a'],
|
527
|
-
[WORD, 'b']
|
528
|
-
],
|
529
|
-
[ATOM, 0]
|
530
|
-
]
|
531
|
-
]
|
532
|
-
)
|
533
|
-
break
|
534
|
-
}
|
535
|
-
}
|
536
|
-
break
|
537
|
-
case ATOM:
|
538
|
-
break
|
539
|
-
case APPLY:
|
540
|
-
{
|
541
|
-
switch (first[VALUE]) {
|
542
|
-
case KEYWORDS.BLOCK:
|
543
|
-
{
|
544
|
-
if (
|
545
|
-
prev == undefined ||
|
546
|
-
(prev &&
|
547
|
-
prev[TYPE] === APPLY &&
|
548
|
-
prev[VALUE] !== KEYWORDS.ANONYMOUS_FUNCTION)
|
549
|
-
) {
|
550
|
-
exp[0][VALUE] = KEYWORDS.CALL_FUNCTION
|
551
|
-
exp[0][TYPE] = APPLY
|
552
|
-
exp.length = 1
|
553
|
-
exp[1] = [
|
554
|
-
[APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
|
555
|
-
[[APPLY, KEYWORDS.BLOCK], ...rest]
|
556
|
-
]
|
557
|
-
deSuggar(exp)
|
558
|
-
}
|
559
|
-
}
|
560
|
-
break
|
561
|
-
case SUGGAR.PIPE:
|
562
|
-
{
|
563
|
-
if (rest.length < 1)
|
564
|
-
throw new RangeError(
|
565
|
-
`Invalid number of arguments to (${
|
566
|
-
SUGGAR.PIPE
|
567
|
-
}) (>= 1 required). (${SUGGAR.PIPE} ${stringifyArgs(
|
568
|
-
rest
|
569
|
-
)})`
|
570
|
-
)
|
571
|
-
let inp = rest[0]
|
572
|
-
exp.length = 0
|
573
|
-
for (let i = 1; i < rest.length; ++i) {
|
574
|
-
if (!rest[i].length || rest[i][0][TYPE] !== APPLY)
|
575
|
-
throw new TypeError(
|
576
|
-
`Argument at position (${i}) of (${
|
577
|
-
SUGGAR.PIPE
|
578
|
-
}) is not an invoked (${
|
579
|
-
KEYWORDS.ANONYMOUS_FUNCTION
|
580
|
-
}). (${SUGGAR.PIPE} ${stringifyArgs(rest)})`
|
581
|
-
)
|
582
|
-
inp = [rest[i].shift(), inp, ...rest[i]]
|
583
|
-
}
|
584
|
-
for (let i = 0; i < inp.length; ++i) exp[i] = inp[i]
|
585
|
-
deSuggar(exp)
|
586
|
-
}
|
587
|
-
break
|
588
|
-
case SUGGAR.CONDITION:
|
589
|
-
{
|
590
|
-
if (rest.length < 2)
|
591
|
-
throw new RangeError(
|
592
|
-
`Invalid number of arguments for (${
|
593
|
-
SUGGAR.CONDITION
|
594
|
-
}), expected (> 2 required) but got ${rest.length} (${
|
595
|
-
SUGGAR.CONDITION
|
596
|
-
} ${stringifyArgs(rest)})`
|
597
|
-
)
|
598
|
-
if (rest.length % 2 !== 0)
|
599
|
-
throw new RangeError(
|
600
|
-
`Invalid number of arguments for (${
|
601
|
-
SUGGAR.CONDITION
|
602
|
-
}), expected even number of arguments but got ${
|
603
|
-
rest.length
|
604
|
-
} (${SUGGAR.CONDITION} ${stringifyArgs(rest)})`
|
605
|
-
)
|
606
|
-
exp.length = 0
|
607
|
-
let temp = exp
|
608
|
-
for (let i = 0; i < rest.length; i += 2) {
|
609
|
-
if (i === rest.length - 2) {
|
610
|
-
temp.push([APPLY, KEYWORDS.IF], rest[i], rest.at(-1))
|
611
|
-
} else {
|
612
|
-
temp.push([APPLY, KEYWORDS.IF], rest[i], rest[i + 1], [])
|
613
|
-
temp = temp.at(-1)
|
614
|
-
}
|
615
|
-
}
|
616
|
-
deSuggar(exp)
|
617
|
-
}
|
618
|
-
break
|
619
|
-
case SUGGAR.LIST_TYPE:
|
620
|
-
{
|
621
|
-
exp.length = 0
|
622
|
-
let temp = exp
|
623
|
-
for (const item of rest) {
|
624
|
-
temp.push([APPLY, KEYWORDS.ARRAY_TYPE], item, [])
|
625
|
-
temp = temp.at(-1)
|
626
|
-
}
|
627
|
-
temp.push([APPLY, KEYWORDS.ARRAY_TYPE])
|
628
|
-
}
|
629
|
-
deSuggar(exp)
|
630
|
-
break
|
631
|
-
case SUGGAR.INTEGER_DEVISION:
|
632
|
-
{
|
633
|
-
if (rest.length !== 2)
|
634
|
-
throw new RangeError(
|
635
|
-
`Invalid number of arguments for (${
|
636
|
-
SUGGAR.INTEGER_DEVISION
|
637
|
-
}), expected (= 2) but got ${rest.length} (${
|
638
|
-
SUGGAR.INTEGER_DEVISION
|
639
|
-
} ${stringifyArgs(rest)})`
|
640
|
-
)
|
641
|
-
else if (rest.some((x) => x[TYPE] === APPLY))
|
642
|
-
throw new TypeError(
|
643
|
-
`Arguments of (${
|
644
|
-
SUGGAR.INTEGER_DEVISION
|
645
|
-
}), must be (or atom word) (hint use (math:floor (${
|
646
|
-
KEYWORDS.DIVISION
|
647
|
-
} a b)) instead) (${
|
648
|
-
SUGGAR.INTEGER_DEVISION
|
649
|
-
} ${stringifyArgs(rest)})`
|
650
|
-
)
|
651
|
-
else {
|
652
|
-
exp.length = 1
|
653
|
-
exp[0] = [APPLY, KEYWORDS.BITWISE_OR]
|
654
|
-
exp.push([[APPLY, KEYWORDS.DIVISION], ...rest])
|
655
|
-
exp.push([ATOM, 0])
|
656
|
-
}
|
657
|
-
}
|
658
|
-
break
|
659
|
-
case SUGGAR.POWER:
|
660
|
-
{
|
661
|
-
if (rest.length !== 2)
|
662
|
-
throw new RangeError(
|
663
|
-
`Invalid number of arguments for (${
|
664
|
-
SUGGAR.POWER
|
665
|
-
}), expected (= 2) but got ${rest.length} (${
|
666
|
-
SUGGAR.POWER
|
667
|
-
} ${stringifyArgs(rest)})`
|
668
|
-
)
|
669
|
-
const isExponentAtom = exp[1][TYPE] === ATOM
|
670
|
-
const isPowerAtom = exp[2][TYPE] === ATOM
|
671
|
-
const isExponentWord = exp[1][TYPE] === WORD
|
672
|
-
if ((isExponentWord || isExponentAtom) && isPowerAtom) {
|
673
|
-
if (isExponentAtom) {
|
674
|
-
exp[0][VALUE] = KEYWORDS.MULTIPLICATION
|
675
|
-
const exponent = exp[1]
|
676
|
-
const power = exp[2][VALUE]
|
677
|
-
exp.length = 1
|
678
|
-
exp.push(exponent, [ATOM, exponent[VALUE] ** (power - 1)])
|
679
|
-
} else if (isExponentWord) {
|
680
|
-
const exponent = exp[1]
|
681
|
-
const power = exp[2]
|
682
|
-
exp.length = 0
|
683
|
-
exp.push([0, 'apply'], EXPONENTIATION, exponent, power)
|
684
|
-
}
|
685
|
-
} else {
|
686
|
-
const exponent = exp[1]
|
687
|
-
const power = exp[2]
|
688
|
-
exp.length = 0
|
689
|
-
exp.push([0, 'apply'], EXPONENTIATION, exponent, power)
|
690
|
-
}
|
691
|
-
deSuggar(exp)
|
692
|
-
}
|
693
|
-
break
|
694
|
-
case KEYWORDS.MULTIPLICATION:
|
695
|
-
if (!rest.length) {
|
696
|
-
exp[0][TYPE] = ATOM
|
697
|
-
exp[0][VALUE] = TRUE
|
698
|
-
} else if (rest.length > 2) {
|
699
|
-
exp.length = 0
|
700
|
-
let temp = exp
|
701
|
-
for (let i = 0; i < rest.length; i += 1) {
|
702
|
-
if (i < rest.length - 1) {
|
703
|
-
temp.push([APPLY, KEYWORDS.MULTIPLICATION], rest[i], [])
|
704
|
-
temp = temp.at(-1)
|
705
|
-
} else {
|
706
|
-
temp.push(...rest[i])
|
707
|
-
}
|
708
|
-
}
|
709
|
-
deSuggar(exp)
|
710
|
-
}
|
711
|
-
break
|
712
|
-
case KEYWORDS.ADDITION:
|
713
|
-
if (!rest.length) {
|
714
|
-
exp[0][TYPE] = ATOM
|
715
|
-
exp[0][VALUE] = FALSE
|
716
|
-
} else if (rest.length > 2) {
|
717
|
-
exp.length = 0
|
718
|
-
let temp = exp
|
719
|
-
for (let i = 0; i < rest.length; i += 1) {
|
720
|
-
if (i < rest.length - 1) {
|
721
|
-
temp.push([APPLY, KEYWORDS.ADDITION], rest[i], [])
|
722
|
-
temp = temp.at(-1)
|
723
|
-
} else {
|
724
|
-
temp.push(...rest[i])
|
725
|
-
}
|
726
|
-
}
|
727
|
-
deSuggar(exp)
|
728
|
-
}
|
729
|
-
break
|
730
|
-
case KEYWORDS.DIVISION:
|
731
|
-
if (!rest.length) {
|
732
|
-
exp[0][TYPE] = ATOM
|
733
|
-
exp[0][VALUE] = FALSE
|
734
|
-
} else if (rest.length > 2) {
|
735
|
-
exp.length = 0
|
736
|
-
let temp = exp
|
737
|
-
for (let i = 0; i < rest.length; i += 1) {
|
738
|
-
if (i < rest.length - 1) {
|
739
|
-
temp.push([APPLY, KEYWORDS.DIVISION], rest[i], [])
|
740
|
-
temp = temp.at(-1)
|
741
|
-
} else {
|
742
|
-
temp.push(...rest[i])
|
743
|
-
}
|
744
|
-
}
|
745
|
-
deSuggar(exp)
|
746
|
-
}
|
747
|
-
break
|
748
|
-
case KEYWORDS.AND:
|
749
|
-
if (!rest.length) {
|
750
|
-
exp[0][TYPE] = ATOM
|
751
|
-
exp[0][VALUE] = FALSE
|
752
|
-
} else if (rest.length > 2) {
|
753
|
-
exp.length = 0
|
754
|
-
let temp = exp
|
755
|
-
for (let i = 0; i < rest.length; i += 1) {
|
756
|
-
if (i < rest.length - 1) {
|
757
|
-
temp.push([APPLY, KEYWORDS.AND], rest[i], [])
|
758
|
-
temp = temp.at(-1)
|
759
|
-
} else {
|
760
|
-
temp.push(...rest[i])
|
761
|
-
}
|
762
|
-
}
|
763
|
-
deSuggar(exp)
|
764
|
-
}
|
765
|
-
break
|
766
|
-
case KEYWORDS.OR:
|
767
|
-
if (!rest.length) {
|
768
|
-
exp[0][TYPE] = ATOM
|
769
|
-
exp[0][VALUE] = FALSE
|
770
|
-
} else if (rest.length > 2) {
|
771
|
-
exp.length = 0
|
772
|
-
let temp = exp
|
773
|
-
for (let i = 0; i < rest.length; i += 1) {
|
774
|
-
if (i < rest.length - 1) {
|
775
|
-
temp.push([APPLY, KEYWORDS.OR], rest[i], [])
|
776
|
-
temp = temp.at(-1)
|
777
|
-
} else {
|
778
|
-
temp.push(...rest[i])
|
779
|
-
}
|
780
|
-
}
|
781
|
-
deSuggar(exp)
|
782
|
-
}
|
783
|
-
break
|
784
|
-
case SUGGAR.UNLESS:
|
785
|
-
{
|
786
|
-
if (rest.length > 3 || rest.length < 2)
|
787
|
-
throw new RangeError(
|
788
|
-
`Invalid number of arguments for (${
|
789
|
-
SUGGAR.UNLESS
|
790
|
-
}), expected (or (= 3) (= 2)) but got ${rest.length} (${
|
791
|
-
SUGGAR.UNLESS
|
792
|
-
} ${stringifyArgs(rest)})`
|
793
|
-
)
|
794
|
-
exp[0][VALUE] = KEYWORDS.IF
|
795
|
-
const temp = exp[2]
|
796
|
-
exp[2] = exp[3] ?? [ATOM, FALSE]
|
797
|
-
exp[3] = temp
|
798
|
-
}
|
799
|
-
deSuggar(exp)
|
800
|
-
break
|
801
|
-
|
802
|
-
case SUGGAR.NOT_EQUAL_1:
|
803
|
-
case SUGGAR.NOT_EQUAL_2:
|
804
|
-
{
|
805
|
-
if (rest.length > 3 || rest.length < 2)
|
806
|
-
throw new RangeError(
|
807
|
-
`Invalid number of arguments for (${
|
808
|
-
exp[0][1]
|
809
|
-
}), expected (or (= 3) (= 2)) but got ${rest.length} (${
|
810
|
-
exp[0][1]
|
811
|
-
} ${stringifyArgs(rest)})`
|
812
|
-
)
|
813
|
-
exp[0][VALUE] = KEYWORDS.NOT
|
814
|
-
exp[1] = [[APPLY, KEYWORDS.EQUAL], exp[1], exp[2]]
|
815
|
-
exp.length = 2
|
816
|
-
deSuggar(exp)
|
817
|
-
}
|
818
|
-
break
|
819
|
-
}
|
820
|
-
prev = first
|
821
|
-
}
|
822
|
-
break
|
823
|
-
default:
|
824
|
-
for (const e of exp) evaluate(e)
|
825
|
-
break
|
826
|
-
}
|
827
|
-
for (const r of rest) evaluate(r)
|
828
|
-
}
|
829
|
-
}
|
830
|
-
evaluate(ast)
|
831
|
-
return ast
|
832
|
-
}
|