fez-lisp 1.3.1 → 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 +29 -4
- package/lib/baked/std.js +1 -1
- package/package.json +2 -3
- package/src/compiler.js +25 -6
- package/src/interpreter.js +8 -22
- package/src/keywords.js +0 -13
- package/src/macros.js +408 -0
- package/src/utils.js +13 -371
package/src/utils.js
CHANGED
@@ -1,42 +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'
|
16
|
-
import {
|
6
|
+
import {
|
7
|
+
deSuggarAst,
|
8
|
+
deSuggarSource,
|
9
|
+
handleUnbalancedQuotes,
|
10
|
+
SUGGAR
|
11
|
+
} from './macros.js'
|
17
12
|
export const logError = (error) =>
|
18
13
|
console.log('\x1b[31m', `\n${error}\n`, '\x1b[0m')
|
19
14
|
export const logSuccess = (output) => console.log(output, '\x1b[0m')
|
20
|
-
export const replaceStrings = (source) => {
|
21
|
-
// const quotes = source.match(/"(.*?)"/g)
|
22
|
-
const quotes = source.match(/"(?:.*?(\n|\r))*?.*?"/g)
|
23
|
-
// TODO handle escaping
|
24
|
-
if (quotes)
|
25
|
-
for (const q of quotes)
|
26
|
-
source = source.replaceAll(
|
27
|
-
q,
|
28
|
-
`(array ${[...q.replaceAll('\r', '')]
|
29
|
-
.slice(1, -1)
|
30
|
-
.map((x) => x.charCodeAt(0))
|
31
|
-
.join(' ')})`
|
32
|
-
)
|
33
|
-
return source
|
34
|
-
}
|
35
|
-
export const replaceQuotes = (source) =>
|
36
|
-
source
|
37
|
-
.replaceAll(/\'\(/g, '(array ')
|
38
|
-
.replaceAll(/\`\(/g, '(list ')
|
39
|
-
.replaceAll(/\(\)/g, '(array)')
|
40
15
|
// export const replaceEmptyArrays = (source) =>
|
41
16
|
// source
|
42
17
|
export const removeNoCode = (source) =>
|
@@ -168,11 +143,6 @@ export const handleUnbalancedParens = (source) => {
|
|
168
143
|
)
|
169
144
|
return source
|
170
145
|
}
|
171
|
-
export const handleUnbalancedQuotes = (source) => {
|
172
|
-
const diff = (source.match(/\"/g) ?? []).length % 2
|
173
|
-
if (diff !== 0) throw new SyntaxError(`Quotes are unbalanced "`)
|
174
|
-
return source
|
175
|
-
}
|
176
146
|
export const removeMutation = (source) => source.replace(new RegExp(/!/g), 'ǃ')
|
177
147
|
const isDefinition = (x) =>
|
178
148
|
x[TYPE] === APPLY && x[VALUE] === KEYWORDS.DEFINE_VARIABLE
|
@@ -246,13 +216,13 @@ export const fez = (source, options = {}) => {
|
|
246
216
|
const env = Object.create(null)
|
247
217
|
try {
|
248
218
|
if (typeof source === 'string') {
|
249
|
-
source =
|
219
|
+
source = deSuggarSource(source)
|
250
220
|
const valid = handleUnbalancedQuotes(
|
251
221
|
handleUnbalancedParens(removeNoCode(source))
|
252
222
|
)
|
253
223
|
const code = !options.mutation ? removeMutation(valid) : valid
|
254
224
|
if (!code.length && options.throw) throw new Error('Nothing to parse!')
|
255
|
-
const parsed =
|
225
|
+
const parsed = deSuggarAst(LISP.parse(code))
|
256
226
|
const ast = [...treeShake(parsed, std), ...parsed]
|
257
227
|
// if (options.check) typeCheck(ast)
|
258
228
|
if (options.compile) return comp(ast)
|
@@ -310,17 +280,12 @@ export const decompress = (raw) => {
|
|
310
280
|
export const shake = (parsed, std) => [...treeShake(parsed, std), ...parsed]
|
311
281
|
export const tree = (source, std) =>
|
312
282
|
std
|
313
|
-
? shake(
|
314
|
-
|
315
|
-
std
|
316
|
-
)
|
317
|
-
: LISP.parse(replaceQuotes(replaceStrings(removeNoCode(source))))
|
283
|
+
? shake(LISP.parse(deSuggarSource(removeNoCode(source))), std)
|
284
|
+
: LISP.parse(deSuggarSource(removeNoCode(source)))
|
318
285
|
export const minify = (source) =>
|
319
|
-
LISP.source(
|
320
|
-
deSuggar(LISP.parse(replaceQuotes(replaceStrings(removeNoCode(source)))))
|
321
|
-
)
|
286
|
+
LISP.source(deSuggarAst(LISP.parse(deSuggarSource(removeNoCode(source)))))
|
322
287
|
export const prep = (source) =>
|
323
|
-
|
288
|
+
deSuggarAst(LISP.parse(removeNoCode(deSuggarSource(source))))
|
324
289
|
export const src = (source, deps) => {
|
325
290
|
source = prep(source)
|
326
291
|
return LISP.source([
|
@@ -363,326 +328,3 @@ export const js = (source, deps) => {
|
|
363
328
|
])
|
364
329
|
return `${top}${program}`
|
365
330
|
}
|
366
|
-
|
367
|
-
export const deSuggar = (ast) => {
|
368
|
-
if (ast.length === 0) throw new SyntaxError(`No expressions to evaluate`)
|
369
|
-
// for (const node of ast)
|
370
|
-
// if (node[0] && node[0][TYPE] === APPLY && node[0][VALUE] === KEYWORDS.BLOCK)
|
371
|
-
// throw new SyntaxError(`Top level (${KEYWORDS.BLOCK}) is not allowed`)
|
372
|
-
let prev = undefined
|
373
|
-
const evaluate = (exp) => {
|
374
|
-
const [first, ...rest] = isLeaf(exp) ? [exp] : exp
|
375
|
-
if (first != undefined) {
|
376
|
-
switch (first[TYPE]) {
|
377
|
-
case WORD:
|
378
|
-
{
|
379
|
-
switch (first[VALUE]) {
|
380
|
-
case SUGGAR.POWER:
|
381
|
-
exp.length = 0
|
382
|
-
exp.push(...EXPONENTIATION)
|
383
|
-
break
|
384
|
-
case SUGGAR.INTEGER_DEVISION:
|
385
|
-
exp.length = 0
|
386
|
-
exp.push(...FLOOR)
|
387
|
-
break
|
388
|
-
}
|
389
|
-
}
|
390
|
-
break
|
391
|
-
case ATOM:
|
392
|
-
break
|
393
|
-
case APPLY:
|
394
|
-
{
|
395
|
-
switch (first[VALUE]) {
|
396
|
-
case KEYWORDS.BLOCK:
|
397
|
-
{
|
398
|
-
if (
|
399
|
-
prev == undefined ||
|
400
|
-
(prev &&
|
401
|
-
prev[TYPE] === APPLY &&
|
402
|
-
prev[VALUE] !== KEYWORDS.ANONYMOUS_FUNCTION)
|
403
|
-
) {
|
404
|
-
exp[0][VALUE] = KEYWORDS.CALL_FUNCTION
|
405
|
-
exp[0][TYPE] = APPLY
|
406
|
-
exp.length = 1
|
407
|
-
exp[1] = [
|
408
|
-
[APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
|
409
|
-
[[APPLY, KEYWORDS.BLOCK], ...rest]
|
410
|
-
]
|
411
|
-
deSuggar(exp)
|
412
|
-
}
|
413
|
-
}
|
414
|
-
break
|
415
|
-
case SUGGAR.PIPE:
|
416
|
-
{
|
417
|
-
if (rest.length < 1)
|
418
|
-
throw new RangeError(
|
419
|
-
`Invalid number of arguments to (${
|
420
|
-
SUGGAR.PIPE
|
421
|
-
}) (>= 1 required). (${SUGGAR.PIPE} ${stringifyArgs(
|
422
|
-
rest
|
423
|
-
)})`
|
424
|
-
)
|
425
|
-
let inp = rest[0]
|
426
|
-
exp.length = 0
|
427
|
-
for (let i = 1; i < rest.length; ++i) {
|
428
|
-
if (!rest[i].length || rest[i][0][TYPE] !== APPLY)
|
429
|
-
throw new TypeError(
|
430
|
-
`Argument at position (${i}) of (${
|
431
|
-
SUGGAR.PIPE
|
432
|
-
}) is not an invoked (${
|
433
|
-
KEYWORDS.ANONYMOUS_FUNCTION
|
434
|
-
}). (${SUGGAR.PIPE} ${stringifyArgs(rest)})`
|
435
|
-
)
|
436
|
-
inp = [rest[i].shift(), inp, ...rest[i]]
|
437
|
-
}
|
438
|
-
for (let i = 0; i < inp.length; ++i) exp[i] = inp[i]
|
439
|
-
deSuggar(exp)
|
440
|
-
}
|
441
|
-
break
|
442
|
-
case SUGGAR.CONDITION:
|
443
|
-
{
|
444
|
-
if (rest.length < 2)
|
445
|
-
throw new RangeError(
|
446
|
-
`Invalid number of arguments for (${
|
447
|
-
SUGGAR.CONDITION
|
448
|
-
}), expected (> 2 required) but got ${rest.length} (${
|
449
|
-
SUGGAR.CONDITION
|
450
|
-
} ${stringifyArgs(rest)})`
|
451
|
-
)
|
452
|
-
if (rest.length % 2 !== 0)
|
453
|
-
throw new RangeError(
|
454
|
-
`Invalid number of arguments for (${
|
455
|
-
SUGGAR.CONDITION
|
456
|
-
}), expected even number of arguments but got ${
|
457
|
-
rest.length
|
458
|
-
} (${SUGGAR.CONDITION} ${stringifyArgs(rest)})`
|
459
|
-
)
|
460
|
-
exp.length = 0
|
461
|
-
let temp = exp
|
462
|
-
for (let i = 0; i < rest.length; i += 2) {
|
463
|
-
if (i === rest.length - 2) {
|
464
|
-
temp.push([APPLY, KEYWORDS.IF], rest[i], rest.at(-1))
|
465
|
-
} else {
|
466
|
-
temp.push([APPLY, KEYWORDS.IF], rest[i], rest[i + 1], [])
|
467
|
-
temp = temp.at(-1)
|
468
|
-
}
|
469
|
-
}
|
470
|
-
deSuggar(exp)
|
471
|
-
}
|
472
|
-
break
|
473
|
-
case SUGGAR.LIST_TYPE:
|
474
|
-
{
|
475
|
-
exp.length = 0
|
476
|
-
let temp = exp
|
477
|
-
for (const item of rest) {
|
478
|
-
temp.push([APPLY, KEYWORDS.ARRAY_TYPE], item, [])
|
479
|
-
temp = temp.at(-1)
|
480
|
-
}
|
481
|
-
temp.push([APPLY, KEYWORDS.ARRAY_TYPE])
|
482
|
-
}
|
483
|
-
deSuggar(exp)
|
484
|
-
break
|
485
|
-
case SUGGAR.INTEGER_DEVISION:
|
486
|
-
{
|
487
|
-
if (rest.length !== 2)
|
488
|
-
throw new RangeError(
|
489
|
-
`Invalid number of arguments for (${
|
490
|
-
SUGGAR.INTEGER_DEVISION
|
491
|
-
}), expected (= 2) but got ${rest.length} (${
|
492
|
-
SUGGAR.INTEGER_DEVISION
|
493
|
-
} ${stringifyArgs(rest)})`
|
494
|
-
)
|
495
|
-
else if (rest.some((x) => x[TYPE] === APPLY)) {
|
496
|
-
exp.length = 0
|
497
|
-
exp.push([0, KEYWORDS.CALL_FUNCTION], FLOOR, ...rest)
|
498
|
-
} else {
|
499
|
-
exp.length = 1
|
500
|
-
exp[0] = [APPLY, KEYWORDS.BITWISE_OR]
|
501
|
-
exp.push([[APPLY, KEYWORDS.DIVISION], ...rest])
|
502
|
-
exp.push([ATOM, 0])
|
503
|
-
}
|
504
|
-
}
|
505
|
-
break
|
506
|
-
case SUGGAR.POWER:
|
507
|
-
{
|
508
|
-
if (rest.length !== 2)
|
509
|
-
throw new RangeError(
|
510
|
-
`Invalid number of arguments for (${
|
511
|
-
SUGGAR.POWER
|
512
|
-
}), expected (= 2) but got ${rest.length} (${
|
513
|
-
SUGGAR.POWER
|
514
|
-
} ${stringifyArgs(rest)})`
|
515
|
-
)
|
516
|
-
const isExponentAtom = exp[1][TYPE] === ATOM
|
517
|
-
const isPowerAtom = exp[2][TYPE] === ATOM
|
518
|
-
const isExponentWord = exp[1][TYPE] === WORD
|
519
|
-
if ((isExponentWord || isExponentAtom) && isPowerAtom) {
|
520
|
-
if (isExponentAtom) {
|
521
|
-
exp[0][VALUE] = KEYWORDS.MULTIPLICATION
|
522
|
-
const exponent = exp[1]
|
523
|
-
const power = exp[2][VALUE]
|
524
|
-
exp.length = 1
|
525
|
-
exp.push(exponent, [ATOM, exponent[VALUE] ** (power - 1)])
|
526
|
-
} else if (isExponentWord) {
|
527
|
-
const exponent = exp[1]
|
528
|
-
const power = exp[2]
|
529
|
-
exp.length = 0
|
530
|
-
exp.push(
|
531
|
-
[0, KEYWORDS.CALL_FUNCTION],
|
532
|
-
EXPONENTIATION,
|
533
|
-
exponent,
|
534
|
-
power
|
535
|
-
)
|
536
|
-
}
|
537
|
-
} else {
|
538
|
-
const exponent = exp[1]
|
539
|
-
const power = exp[2]
|
540
|
-
exp.length = 0
|
541
|
-
exp.push(
|
542
|
-
[0, KEYWORDS.CALL_FUNCTION],
|
543
|
-
EXPONENTIATION,
|
544
|
-
exponent,
|
545
|
-
power
|
546
|
-
)
|
547
|
-
}
|
548
|
-
deSuggar(exp)
|
549
|
-
}
|
550
|
-
break
|
551
|
-
case KEYWORDS.MULTIPLICATION:
|
552
|
-
if (!rest.length) {
|
553
|
-
exp[0][TYPE] = ATOM
|
554
|
-
exp[0][VALUE] = TRUE
|
555
|
-
} else if (rest.length > 2) {
|
556
|
-
exp.length = 0
|
557
|
-
let temp = exp
|
558
|
-
for (let i = 0; i < rest.length; i += 1) {
|
559
|
-
if (i < rest.length - 1) {
|
560
|
-
temp.push([APPLY, KEYWORDS.MULTIPLICATION], rest[i], [])
|
561
|
-
temp = temp.at(-1)
|
562
|
-
} else {
|
563
|
-
temp.push(...rest[i])
|
564
|
-
}
|
565
|
-
}
|
566
|
-
deSuggar(exp)
|
567
|
-
}
|
568
|
-
break
|
569
|
-
case KEYWORDS.ADDITION:
|
570
|
-
if (!rest.length) {
|
571
|
-
exp[0][TYPE] = ATOM
|
572
|
-
exp[0][VALUE] = FALSE
|
573
|
-
} else if (rest.length > 2) {
|
574
|
-
exp.length = 0
|
575
|
-
let temp = exp
|
576
|
-
for (let i = 0; i < rest.length; i += 1) {
|
577
|
-
if (i < rest.length - 1) {
|
578
|
-
temp.push([APPLY, KEYWORDS.ADDITION], rest[i], [])
|
579
|
-
temp = temp.at(-1)
|
580
|
-
} else {
|
581
|
-
temp.push(...rest[i])
|
582
|
-
}
|
583
|
-
}
|
584
|
-
deSuggar(exp)
|
585
|
-
}
|
586
|
-
break
|
587
|
-
case KEYWORDS.DIVISION:
|
588
|
-
if (!rest.length) {
|
589
|
-
exp[0][TYPE] = ATOM
|
590
|
-
exp[0][VALUE] = FALSE
|
591
|
-
} else if (rest.length > 2) {
|
592
|
-
exp.length = 0
|
593
|
-
let temp = exp
|
594
|
-
for (let i = 0; i < rest.length; i += 1) {
|
595
|
-
if (i < rest.length - 1) {
|
596
|
-
temp.push([APPLY, KEYWORDS.DIVISION], rest[i], [])
|
597
|
-
temp = temp.at(-1)
|
598
|
-
} else {
|
599
|
-
temp.push(...rest[i])
|
600
|
-
}
|
601
|
-
}
|
602
|
-
deSuggar(exp)
|
603
|
-
}
|
604
|
-
break
|
605
|
-
case KEYWORDS.AND:
|
606
|
-
if (!rest.length) {
|
607
|
-
exp[0][TYPE] = ATOM
|
608
|
-
exp[0][VALUE] = FALSE
|
609
|
-
} else if (rest.length > 2) {
|
610
|
-
exp.length = 0
|
611
|
-
let temp = exp
|
612
|
-
for (let i = 0; i < rest.length; i += 1) {
|
613
|
-
if (i < rest.length - 1) {
|
614
|
-
temp.push([APPLY, KEYWORDS.AND], rest[i], [])
|
615
|
-
temp = temp.at(-1)
|
616
|
-
} else {
|
617
|
-
temp.push(...rest[i])
|
618
|
-
}
|
619
|
-
}
|
620
|
-
deSuggar(exp)
|
621
|
-
}
|
622
|
-
break
|
623
|
-
case KEYWORDS.OR:
|
624
|
-
if (!rest.length) {
|
625
|
-
exp[0][TYPE] = ATOM
|
626
|
-
exp[0][VALUE] = FALSE
|
627
|
-
} else if (rest.length > 2) {
|
628
|
-
exp.length = 0
|
629
|
-
let temp = exp
|
630
|
-
for (let i = 0; i < rest.length; i += 1) {
|
631
|
-
if (i < rest.length - 1) {
|
632
|
-
temp.push([APPLY, KEYWORDS.OR], rest[i], [])
|
633
|
-
temp = temp.at(-1)
|
634
|
-
} else {
|
635
|
-
temp.push(...rest[i])
|
636
|
-
}
|
637
|
-
}
|
638
|
-
deSuggar(exp)
|
639
|
-
}
|
640
|
-
break
|
641
|
-
case SUGGAR.UNLESS:
|
642
|
-
{
|
643
|
-
if (rest.length > 3 || rest.length < 2)
|
644
|
-
throw new RangeError(
|
645
|
-
`Invalid number of arguments for (${
|
646
|
-
SUGGAR.UNLESS
|
647
|
-
}), expected (or (= 3) (= 2)) but got ${rest.length} (${
|
648
|
-
SUGGAR.UNLESS
|
649
|
-
} ${stringifyArgs(rest)})`
|
650
|
-
)
|
651
|
-
exp[0][VALUE] = KEYWORDS.IF
|
652
|
-
const temp = exp[2]
|
653
|
-
exp[2] = exp[3] ?? [ATOM, FALSE]
|
654
|
-
exp[3] = temp
|
655
|
-
}
|
656
|
-
deSuggar(exp)
|
657
|
-
break
|
658
|
-
case SUGGAR.NOT_EQUAL_1:
|
659
|
-
case SUGGAR.NOT_EQUAL_2:
|
660
|
-
{
|
661
|
-
if (rest.length > 3 || rest.length < 2)
|
662
|
-
throw new RangeError(
|
663
|
-
`Invalid number of arguments for (${
|
664
|
-
exp[0][1]
|
665
|
-
}), expected (or (= 3) (= 2)) but got ${rest.length} (${
|
666
|
-
exp[0][1]
|
667
|
-
} ${stringifyArgs(rest)})`
|
668
|
-
)
|
669
|
-
exp[0][VALUE] = KEYWORDS.NOT
|
670
|
-
exp[1] = [[APPLY, KEYWORDS.EQUAL], exp[1], exp[2]]
|
671
|
-
exp.length = 2
|
672
|
-
deSuggar(exp)
|
673
|
-
}
|
674
|
-
break
|
675
|
-
}
|
676
|
-
prev = first
|
677
|
-
}
|
678
|
-
break
|
679
|
-
default:
|
680
|
-
for (const e of exp) evaluate(e)
|
681
|
-
break
|
682
|
-
}
|
683
|
-
for (const r of rest) evaluate(r)
|
684
|
-
}
|
685
|
-
}
|
686
|
-
evaluate(ast)
|
687
|
-
return ast
|
688
|
-
}
|