fez-lisp 1.5.31 → 1.5.33
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/check.js +87 -68
- package/src/macros.js +1 -2
- package/src/utils.js +28 -2
package/package.json
CHANGED
package/src/check.js
CHANGED
@@ -61,7 +61,6 @@ export const typeCheck = (ast) => {
|
|
61
61
|
[DEBUG.SET_THEME]: {
|
62
62
|
[STATS]: { type: APPLY, [ARGS_COUNT]: VARIADIC, [RETURNS]: UNKNOWN }
|
63
63
|
},
|
64
|
-
[SCOPE_NAME]: performance.now().toString().replace('.', 0),
|
65
64
|
[KEYWORDS.BLOCK]: {
|
66
65
|
[STATS]: { type: APPLY, [ARGS_COUNT]: VARIADIC, [RETURNS]: UNKNOWN }
|
67
66
|
},
|
@@ -376,8 +375,29 @@ export const typeCheck = (ast) => {
|
|
376
375
|
}
|
377
376
|
}
|
378
377
|
const errorStack = new Map()
|
379
|
-
const
|
380
|
-
|
378
|
+
// const isDefinitionOfAFunction = (head, tail) =>
|
379
|
+
// head[TYPE] === APPLY &&
|
380
|
+
// head[VALUE] === KEYWORDS.DEFINE_VARIABLE &&
|
381
|
+
// tail.at(-1)[0][TYPE] === APPLY &&
|
382
|
+
// tail.at(-1)[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
|
383
|
+
const getScopeNames = (scope) => {
|
384
|
+
const scopeNames = []
|
385
|
+
let current = scope
|
386
|
+
|
387
|
+
while (current) {
|
388
|
+
if (current[SCOPE_NAME]) {
|
389
|
+
scopeNames.push(current[SCOPE_NAME])
|
390
|
+
}
|
391
|
+
current = Object.getPrototypeOf(current)
|
392
|
+
}
|
393
|
+
return scopeNames.reverse()
|
394
|
+
}
|
395
|
+
const withScope = (name, scope) => {
|
396
|
+
const chain = getScopeNames(scope)
|
397
|
+
const str = `${chain.join('_')}_${name}`
|
398
|
+
// console.log({ str })
|
399
|
+
return { str, chain }
|
400
|
+
}
|
381
401
|
|
382
402
|
const stack = []
|
383
403
|
const check = (exp, env, scope) => {
|
@@ -386,14 +406,15 @@ export const typeCheck = (ast) => {
|
|
386
406
|
switch (first[TYPE]) {
|
387
407
|
case WORD:
|
388
408
|
{
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
409
|
+
stack.push(() => {
|
410
|
+
const key = withScope(first[VALUE], scope)
|
411
|
+
if (env[first[VALUE]] === undefined) {
|
412
|
+
errorStack.set(
|
413
|
+
key.str,
|
414
|
+
`Trying to access undefined variable ${first[VALUE]} (check #11)`
|
415
|
+
)
|
416
|
+
}
|
417
|
+
})
|
397
418
|
}
|
398
419
|
break
|
399
420
|
case ATOM:
|
@@ -402,50 +423,48 @@ export const typeCheck = (ast) => {
|
|
402
423
|
switch (first[VALUE]) {
|
403
424
|
case KEYWORDS.DEFINE_VARIABLE:
|
404
425
|
{
|
405
|
-
if (
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
env[name] = {
|
414
|
-
[STATS]: {
|
415
|
-
type: APPLY,
|
416
|
-
[ARGS_COUNT]: n - 2,
|
417
|
-
[ARGS]: []
|
418
|
-
}
|
419
|
-
}
|
420
|
-
if (name[name.length - 1] === PREDICATE_SUFFIX)
|
421
|
-
env[name][STATS][SUBTYPE] = PREDICATE
|
422
|
-
|
423
|
-
scope = exp
|
424
|
-
if (env[SCOPE_NAME]) {
|
425
|
-
const key = withScope(name, scope)
|
426
|
-
if (errorStack.has(key)) errorStack.delete(key)
|
427
|
-
}
|
428
|
-
check(rest.at(-1), env, scope)
|
426
|
+
if (rest.length !== 2) {
|
427
|
+
throw new TypeError(
|
428
|
+
`Incorrect number of arguments for (${
|
429
|
+
first[VALUE]
|
430
|
+
}). Expected (= 2) but got ${rest.length} (${stringifyArgs(
|
431
|
+
exp
|
432
|
+
)}) (check #10)`
|
433
|
+
)
|
429
434
|
} else {
|
430
435
|
const name = rest[0][VALUE]
|
431
|
-
if (
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
}
|
436
|
+
if (
|
437
|
+
rest.at(-1)[0][TYPE] === APPLY &&
|
438
|
+
rest.at(-1)[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
|
439
|
+
) {
|
440
|
+
const n = rest.at(-1).length
|
441
|
+
env[name] = {
|
442
|
+
[STATS]: {
|
443
|
+
type: APPLY,
|
444
|
+
[ARGS_COUNT]: n - 2,
|
445
|
+
[ARGS]: []
|
442
446
|
}
|
447
|
+
}
|
448
|
+
if (name[name.length - 1] === PREDICATE_SUFFIX)
|
449
|
+
env[name][STATS][SUBTYPE] = PREDICATE
|
450
|
+
check(rest.at(-1), env, exp)
|
451
|
+
} else {
|
452
|
+
if (!(name in env)) {
|
453
|
+
if (rest[1][TYPE] === WORD)
|
454
|
+
env[name] = env[rest[1][VALUE]]
|
455
|
+
else
|
456
|
+
env[name] = {
|
457
|
+
[STATS]: {
|
458
|
+
type: isLeaf(rest.at(-1))
|
459
|
+
? rest.at(-1)[TYPE]
|
460
|
+
: env[rest.at(-1)[0]?.[VALUE]]?.[STATS]?.[
|
461
|
+
RETURNS
|
462
|
+
] ?? UNKNOWN
|
463
|
+
}
|
464
|
+
}
|
465
|
+
}
|
466
|
+
check(rest.at(-1), env, scope)
|
443
467
|
}
|
444
|
-
if (env[SCOPE_NAME]) {
|
445
|
-
const key = withScope(name, scope)
|
446
|
-
if (errorStack.has(key)) errorStack.delete(key)
|
447
|
-
}
|
448
|
-
check(rest.at(-1), env, scope)
|
449
468
|
}
|
450
469
|
}
|
451
470
|
break
|
@@ -462,19 +481,20 @@ export const typeCheck = (ast) => {
|
|
462
481
|
}
|
463
482
|
const params = exp.slice(1, -1)
|
464
483
|
const copy = Object.create(env)
|
465
|
-
if (
|
484
|
+
if (Array.isArray(scope[1]) && scope[1][TYPE] === WORD) {
|
466
485
|
copy[SCOPE_NAME] = scope[1][VALUE]
|
467
|
-
} else
|
486
|
+
} else {
|
468
487
|
copy[SCOPE_NAME] = performance
|
469
488
|
.now()
|
470
489
|
.toString()
|
471
490
|
.replace('.', 0)
|
491
|
+
}
|
472
492
|
for (const param of params) {
|
473
493
|
copy[param[VALUE]] = { [STATS]: { type: UNKNOWN } }
|
474
494
|
if (env[copy[SCOPE_NAME]])
|
475
495
|
env[copy[SCOPE_NAME]][STATS][ARGS].push(copy[param[VALUE]])
|
476
496
|
}
|
477
|
-
check(rest.at(-1), copy,
|
497
|
+
check(rest.at(-1), copy, copy)
|
478
498
|
}
|
479
499
|
break
|
480
500
|
default:
|
@@ -482,7 +502,7 @@ export const typeCheck = (ast) => {
|
|
482
502
|
const key = withScope(first[VALUE], scope)
|
483
503
|
if (env[first[VALUE]] === undefined)
|
484
504
|
errorStack.set(
|
485
|
-
key,
|
505
|
+
key.str,
|
486
506
|
`Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
|
487
507
|
)
|
488
508
|
else if (
|
@@ -491,7 +511,7 @@ export const typeCheck = (ast) => {
|
|
491
511
|
env[first[VALUE]][STATS][ARGS_COUNT] !== rest.length
|
492
512
|
) {
|
493
513
|
errorStack.set(
|
494
|
-
key,
|
514
|
+
key.str,
|
495
515
|
`Incorrect number of arguments for (${
|
496
516
|
first[VALUE]
|
497
517
|
}). Expected (= ${
|
@@ -506,10 +526,10 @@ export const typeCheck = (ast) => {
|
|
506
526
|
if (first[TYPE] === APPLY && !isSpecial) {
|
507
527
|
if (env[first[VALUE]][STATS].type === ATOM) {
|
508
528
|
errorStack.set(
|
509
|
-
key,
|
529
|
+
key.str,
|
510
530
|
`(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
|
511
531
|
exp
|
512
|
-
)})`
|
532
|
+
)}) (check #12)`
|
513
533
|
)
|
514
534
|
} else if (!env[first[VALUE]][STATS][ARGS_COUNT]) {
|
515
535
|
env[first[VALUE]][STATS][RETURNS] = UNKNOWN
|
@@ -535,7 +555,7 @@ export const typeCheck = (ast) => {
|
|
535
555
|
env[rest[i][VALUE]][STATS][ARGS_COUNT]
|
536
556
|
) {
|
537
557
|
errorStack.set(
|
538
|
-
key,
|
558
|
+
key.str,
|
539
559
|
`Incorrect number of arguments for (${
|
540
560
|
first[VALUE]
|
541
561
|
}). Expected (= ${
|
@@ -554,7 +574,7 @@ export const typeCheck = (ast) => {
|
|
554
574
|
) {
|
555
575
|
if (args[i][STATS][ARGS_COUNT] !== rest[i].length - 2)
|
556
576
|
errorStack.set(
|
557
|
-
key,
|
577
|
+
key.str,
|
558
578
|
`Incorrect number of arguments for (${
|
559
579
|
first[VALUE]
|
560
580
|
}). Expected (= ${
|
@@ -584,7 +604,7 @@ export const typeCheck = (ast) => {
|
|
584
604
|
) {
|
585
605
|
// console.log(env[CAR][STATS], expectedArgs[i][TYPE])
|
586
606
|
errorStack.set(
|
587
|
-
key,
|
607
|
+
key.str,
|
588
608
|
`Incorrect type of arguments for special form (${
|
589
609
|
first[VALUE]
|
590
610
|
}). Expected (${toTypeNames(
|
@@ -618,7 +638,7 @@ export const typeCheck = (ast) => {
|
|
618
638
|
env[TT][STATS][RETURNS]
|
619
639
|
)
|
620
640
|
errorStack.set(
|
621
|
-
key,
|
641
|
+
key.str,
|
622
642
|
`Incorrect type of arguments for special form (${
|
623
643
|
first[VALUE]
|
624
644
|
}). Expected (${toTypeNames(
|
@@ -633,7 +653,7 @@ export const typeCheck = (ast) => {
|
|
633
653
|
expectedArgs[i][TYPE] !== T
|
634
654
|
) {
|
635
655
|
errorStack.set(
|
636
|
-
key,
|
656
|
+
key.str,
|
637
657
|
`Incorrect type of arguments for special form (${
|
638
658
|
first[VALUE]
|
639
659
|
}). Expected (${toTypeNames(
|
@@ -650,7 +670,7 @@ export const typeCheck = (ast) => {
|
|
650
670
|
case APPLY:
|
651
671
|
case ATOM:
|
652
672
|
errorStack.set(
|
653
|
-
key,
|
673
|
+
key.str,
|
654
674
|
`Incorrect type of arguments for (${
|
655
675
|
first[VALUE]
|
656
676
|
}). Expected (${toTypeNames(
|
@@ -686,7 +706,7 @@ export const typeCheck = (ast) => {
|
|
686
706
|
args[i][STATS].type)
|
687
707
|
) {
|
688
708
|
errorStack.set(
|
689
|
-
key,
|
709
|
+
key.str,
|
690
710
|
`Incorrect type of arguments ${i} for (${
|
691
711
|
first[VALUE]
|
692
712
|
}). Expected (${toTypeNames(
|
@@ -704,8 +724,6 @@ export const typeCheck = (ast) => {
|
|
704
724
|
args[i][STATS].type === UNKNOWN
|
705
725
|
) {
|
706
726
|
retry.retried = true
|
707
|
-
if (!scope[SCOPE_NAME])
|
708
|
-
scope[SCOPE_NAME] = scope[1][VALUE]
|
709
727
|
stack.unshift(() => check(exp, env, scope))
|
710
728
|
}
|
711
729
|
// console.log(
|
@@ -725,7 +743,7 @@ export const typeCheck = (ast) => {
|
|
725
743
|
args[i][STATS].type
|
726
744
|
) {
|
727
745
|
errorStack.set(
|
728
|
-
key,
|
746
|
+
key.str,
|
729
747
|
`Incorrect type of arguments ${i} for (${
|
730
748
|
first[VALUE]
|
731
749
|
}). Expected (${toTypeNames(
|
@@ -760,6 +778,7 @@ export const typeCheck = (ast) => {
|
|
760
778
|
}
|
761
779
|
}
|
762
780
|
const copy = JSON.parse(JSON.stringify(ast))
|
781
|
+
copy[SCOPE_NAME] = 'root'
|
763
782
|
check(copy, root, copy)
|
764
783
|
while (stack.length) stack.pop()()
|
765
784
|
if (errorStack.size)
|
package/src/macros.js
CHANGED
@@ -619,7 +619,6 @@ export const deSuggarAst = (ast, scope) => {
|
|
619
619
|
]
|
620
620
|
deSuggarAst(exp[exp.length - 1])
|
621
621
|
} else if (prefix === OPTIMIZATIONS.CACHE) {
|
622
|
-
// TODO: Make this
|
623
622
|
const args = last.slice(1, -1)
|
624
623
|
const newName = `*${performance
|
625
624
|
.now()
|
@@ -810,7 +809,7 @@ export const deSuggarAst = (ast, scope) => {
|
|
810
809
|
export const replaceStrings = (source) => {
|
811
810
|
// const quotes = source.match(/"(.*?)"/g)
|
812
811
|
const quotes = source.match(/"(?:.*?(\n|\r))*?.*?"/g)
|
813
|
-
// TODO handle escaping
|
812
|
+
// TODO: handle escaping
|
814
813
|
if (quotes)
|
815
814
|
for (const q of quotes)
|
816
815
|
source = source.replaceAll(
|
package/src/utils.js
CHANGED
@@ -195,8 +195,34 @@ const extractDeps = (visited, deps) =>
|
|
195
195
|
.map((x) => deps.get(x))
|
196
196
|
.sort((a, b) => a.index - b.index)
|
197
197
|
.map((x) => x.value)
|
198
|
-
const toIgnore = (ast) =>
|
199
|
-
|
198
|
+
const toIgnore = (ast) => {
|
199
|
+
const out = []
|
200
|
+
const dfs = (exp) => {
|
201
|
+
const [head, ...tail] = isLeaf(exp) ? [exp] : exp
|
202
|
+
if (head == undefined) return []
|
203
|
+
switch (head[TYPE]) {
|
204
|
+
case WORD:
|
205
|
+
break
|
206
|
+
case ATOM:
|
207
|
+
break
|
208
|
+
case APPLY:
|
209
|
+
{
|
210
|
+
switch (head[VALUE]) {
|
211
|
+
case KEYWORDS.DEFINE_VARIABLE:
|
212
|
+
out.push(tail[0][VALUE])
|
213
|
+
break
|
214
|
+
default:
|
215
|
+
for (const r of tail) dfs(r)
|
216
|
+
break
|
217
|
+
}
|
218
|
+
}
|
219
|
+
break
|
220
|
+
}
|
221
|
+
}
|
222
|
+
dfs(ast[0])
|
223
|
+
return out
|
224
|
+
// ast.filter(([x]) => isDefinition(x)).map(([_, x]) => x[VALUE])
|
225
|
+
}
|
200
226
|
export const treeShake = (ast, libs) => {
|
201
227
|
const deps = toDeps(libs)
|
202
228
|
const visited = new Set()
|