fez-lisp 1.5.36 → 1.5.38
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/README.md +1 -1
- package/lib/baked/std.js +1 -1
- package/package.json +1 -1
- package/src/check.js +119 -56
- package/src/compiler.js +1 -1
- package/src/interpreter.js +1 -1
- package/src/utils.js +11 -4
package/package.json
CHANGED
package/src/check.js
CHANGED
@@ -2,16 +2,18 @@ import {
|
|
2
2
|
APPLY,
|
3
3
|
ATOM,
|
4
4
|
DEBUG,
|
5
|
+
FALSE,
|
5
6
|
KEYWORDS,
|
6
7
|
PLACEHOLDER,
|
7
8
|
PREDICATE_SUFFIX,
|
8
9
|
SPECIAL_FORMS_SET,
|
10
|
+
TRUE,
|
9
11
|
TYPE,
|
10
12
|
VALUE,
|
11
13
|
WORD
|
12
14
|
} from './keywords.js'
|
13
15
|
import { isLeaf } from './parser.js'
|
14
|
-
import { hasBlock, stringifyArgs } from './utils.js'
|
16
|
+
import { hasApplyLambdaBlock, hasBlock, stringifyArgs } from './utils.js'
|
15
17
|
const ARGS_COUNT = 'n'
|
16
18
|
const VARIADIC = '...'
|
17
19
|
const STATS = '__stats__'
|
@@ -19,10 +21,11 @@ const ARGS = 'args'
|
|
19
21
|
const UNKNOWN = -1
|
20
22
|
const RETURNS = 'returns'
|
21
23
|
const SCOPE_NAME = '__scope__'
|
22
|
-
const
|
24
|
+
const SUB_RETURN_TYPE = 'sub_return_type'
|
23
25
|
const PREDICATE = 3
|
24
26
|
const RETRY_COUNT = 1
|
25
27
|
const DEFINITON_RETRY_COUNT = 1
|
28
|
+
const SUB = 2
|
26
29
|
const toTypeNames = (type) => {
|
27
30
|
switch (type) {
|
28
31
|
case APPLY:
|
@@ -130,8 +133,7 @@ export const typeCheck = (ast) => {
|
|
130
133
|
[ATOM, PLACEHOLDER, PREDICATE],
|
131
134
|
[UNKNOWN, PLACEHOLDER]
|
132
135
|
],
|
133
|
-
[RETURNS]: ATOM
|
134
|
-
[SUBTYPE]: PREDICATE
|
136
|
+
[RETURNS]: ATOM
|
135
137
|
}
|
136
138
|
},
|
137
139
|
[KEYWORDS.ADDITION]: {
|
@@ -326,7 +328,7 @@ export const typeCheck = (ast) => {
|
|
326
328
|
[ARGS_COUNT]: 1,
|
327
329
|
[ARGS]: [[ATOM, PLACEHOLDER, PREDICATE]],
|
328
330
|
[RETURNS]: ATOM,
|
329
|
-
[
|
331
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
330
332
|
}
|
331
333
|
},
|
332
334
|
[KEYWORDS.EQUAL]: {
|
@@ -339,7 +341,7 @@ export const typeCheck = (ast) => {
|
|
339
341
|
[ATOM, PLACEHOLDER]
|
340
342
|
],
|
341
343
|
[RETURNS]: ATOM,
|
342
|
-
[
|
344
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
343
345
|
}
|
344
346
|
},
|
345
347
|
[KEYWORDS.LESS_THAN]: {
|
@@ -352,7 +354,7 @@ export const typeCheck = (ast) => {
|
|
352
354
|
[ATOM, PLACEHOLDER]
|
353
355
|
],
|
354
356
|
[RETURNS]: ATOM,
|
355
|
-
[
|
357
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
356
358
|
}
|
357
359
|
},
|
358
360
|
[KEYWORDS.GREATHER_THAN]: {
|
@@ -365,7 +367,7 @@ export const typeCheck = (ast) => {
|
|
365
367
|
[ATOM, PLACEHOLDER]
|
366
368
|
],
|
367
369
|
[RETURNS]: ATOM,
|
368
|
-
[
|
370
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
369
371
|
}
|
370
372
|
},
|
371
373
|
[KEYWORDS.GREATHER_THAN_OR_EQUAL]: {
|
@@ -378,7 +380,7 @@ export const typeCheck = (ast) => {
|
|
378
380
|
[ATOM, PLACEHOLDER]
|
379
381
|
],
|
380
382
|
[RETURNS]: ATOM,
|
381
|
-
[
|
383
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
382
384
|
}
|
383
385
|
},
|
384
386
|
[KEYWORDS.LESS_THAN_OR_EQUAL]: {
|
@@ -391,7 +393,7 @@ export const typeCheck = (ast) => {
|
|
391
393
|
[ATOM, PLACEHOLDER]
|
392
394
|
],
|
393
395
|
[RETURNS]: ATOM,
|
394
|
-
[
|
396
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
395
397
|
}
|
396
398
|
},
|
397
399
|
[KEYWORDS.AND]: {
|
@@ -404,7 +406,7 @@ export const typeCheck = (ast) => {
|
|
404
406
|
[ATOM, PLACEHOLDER, PREDICATE]
|
405
407
|
],
|
406
408
|
[RETURNS]: ATOM,
|
407
|
-
[
|
409
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
408
410
|
}
|
409
411
|
},
|
410
412
|
[KEYWORDS.OR]: {
|
@@ -417,7 +419,7 @@ export const typeCheck = (ast) => {
|
|
417
419
|
[ATOM, PLACEHOLDER, PREDICATE]
|
418
420
|
],
|
419
421
|
[RETURNS]: ATOM,
|
420
|
-
[
|
422
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
421
423
|
}
|
422
424
|
},
|
423
425
|
[KEYWORDS.IS_ATOM]: {
|
@@ -427,7 +429,7 @@ export const typeCheck = (ast) => {
|
|
427
429
|
[ARGS_COUNT]: 1,
|
428
430
|
[ARGS]: [[UNKNOWN, PLACEHOLDER]],
|
429
431
|
[RETURNS]: ATOM,
|
430
|
-
[
|
432
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
431
433
|
}
|
432
434
|
},
|
433
435
|
[KEYWORDS.IS_LAMBDA]: {
|
@@ -437,7 +439,7 @@ export const typeCheck = (ast) => {
|
|
437
439
|
[ARGS_COUNT]: 1,
|
438
440
|
[ARGS]: [[UNKNOWN, PLACEHOLDER]],
|
439
441
|
[RETURNS]: ATOM,
|
440
|
-
[
|
442
|
+
[SUB_RETURN_TYPE]: PREDICATE
|
441
443
|
}
|
442
444
|
},
|
443
445
|
[KEYWORDS.ERROR]: {
|
@@ -451,6 +453,8 @@ export const typeCheck = (ast) => {
|
|
451
453
|
}
|
452
454
|
}
|
453
455
|
const errorStack = new Map()
|
456
|
+
const warningStack = new Set()
|
457
|
+
|
454
458
|
// const isDefinitionOfAFunction = (head, tail) =>
|
455
459
|
// head[TYPE] === APPLY &&
|
456
460
|
// head[VALUE] === KEYWORDS.DEFINE_VARIABLE &&
|
@@ -487,6 +491,12 @@ export const typeCheck = (ast) => {
|
|
487
491
|
errorStack.set(
|
488
492
|
key.str,
|
489
493
|
`Trying to access undefined variable ${first[VALUE]} (check #11)`
|
494
|
+
|
495
|
+
// `Trying to access undefined variable ${
|
496
|
+
// first[VALUE]
|
497
|
+
// }\n${formatCallstack(
|
498
|
+
// key.chain.filter((x) => isNaN(Number(x[0])))
|
499
|
+
// )}\n(check #11)`
|
490
500
|
)
|
491
501
|
}
|
492
502
|
})
|
@@ -522,49 +532,84 @@ export const typeCheck = (ast) => {
|
|
522
532
|
}
|
523
533
|
}
|
524
534
|
const checkReturnType = () => {
|
525
|
-
if (name[name.length - 1] === PREDICATE_SUFFIX) {
|
535
|
+
// if (name[name.length - 1] === PREDICATE_SUFFIX) {
|
536
|
+
// env[name][STATS][RETURNS] = ATOM
|
537
|
+
// env[name][STATS][SUB_RETURN_TYPE] = PREDICATE
|
538
|
+
// } else {
|
539
|
+
const isPredicate =
|
540
|
+
name[name.length - 1] === PREDICATE_SUFFIX
|
541
|
+
const last = rest.at(-1).at(-1)
|
542
|
+
const body = hasApplyLambdaBlock(last)
|
543
|
+
? last.at(-1).at(-1)
|
544
|
+
: last
|
545
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
546
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
547
|
+
if (returns[TYPE] === ATOM) {
|
526
548
|
env[name][STATS][RETURNS] = ATOM
|
527
|
-
env[name][STATS][SUBTYPE] = PREDICATE
|
528
549
|
} else {
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
550
|
+
switch (returns[VALUE]) {
|
551
|
+
case KEYWORDS.IF:
|
552
|
+
const re = rem.slice(2)
|
553
|
+
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
554
|
+
env[name][STATS][RETURNS] = ATOM
|
555
|
+
// if (
|
556
|
+
// re[0][VALUE] === FALSE ||
|
557
|
+
// re[0][VALUE] === TRUE ||
|
558
|
+
// re[1][VALUE] === FALSE ||
|
559
|
+
// re[1][VALUE] === TRUE
|
560
|
+
// ) {
|
561
|
+
// env[name][STATS][SUB_RETURN_TYPE] = PREDICATE
|
562
|
+
// }
|
563
|
+
} else if (!isLeaf(re[0]) && env[re[0][0][VALUE]]) {
|
564
|
+
env[name][STATS][RETURNS] =
|
565
|
+
env[re[0][0][VALUE]][STATS][RETURNS]
|
566
|
+
env[name][STATS][SUB_RETURN_TYPE] =
|
567
|
+
env[re[0][0][VALUE]][STATS][SUB_RETURN_TYPE]
|
568
|
+
} else {
|
569
|
+
if (env[re[0][VALUE]]) {
|
541
570
|
env[name][STATS][RETURNS] =
|
542
|
-
env[re[0][
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
// env[name][STATS][SUBTYPE] =
|
556
|
-
// env[returns[VALUE]][STATS][SUBTYPE]
|
557
|
-
} else {
|
558
|
-
env[name][STATS][RETURNS] =
|
559
|
-
env[returns[VALUE]].type
|
560
|
-
}
|
571
|
+
env[re[0][VALUE]][STATS].type
|
572
|
+
env[name][STATS][SUB_RETURN_TYPE] =
|
573
|
+
env[re[0][VALUE]][STATS][SUB_RETURN_TYPE]
|
574
|
+
} else env[name][STATS][RETURNS] = UNKNOWN
|
575
|
+
}
|
576
|
+
break
|
577
|
+
default:
|
578
|
+
if (env[returns[VALUE]]) {
|
579
|
+
if (env[returns[VALUE]][STATS].type === APPLY) {
|
580
|
+
env[name][STATS][RETURNS] =
|
581
|
+
env[returns[VALUE]][STATS][RETURNS]
|
582
|
+
env[name][STATS][SUB_RETURN_TYPE] =
|
583
|
+
env[returns[VALUE]][STATS][SUB_RETURN_TYPE]
|
561
584
|
} else {
|
562
|
-
env[name][STATS][RETURNS] =
|
585
|
+
env[name][STATS][RETURNS] =
|
586
|
+
env[returns[VALUE]][STATS].type
|
587
|
+
env[name][STATS][SUB_RETURN_TYPE] =
|
588
|
+
env[returns[VALUE]][SUB_RETURN_TYPE]
|
563
589
|
}
|
564
|
-
|
565
|
-
|
590
|
+
} else {
|
591
|
+
env[name][STATS][RETURNS] = UNKNOWN
|
592
|
+
}
|
593
|
+
break
|
566
594
|
}
|
567
595
|
}
|
596
|
+
if (
|
597
|
+
isPredicate &&
|
598
|
+
env[name][STATS][RETURNS] !== UNKNOWN &&
|
599
|
+
env[name][STATS][SUB_RETURN_TYPE] !== PREDICATE
|
600
|
+
) {
|
601
|
+
warningStack.add(
|
602
|
+
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (check #7)`
|
603
|
+
)
|
604
|
+
} else if (
|
605
|
+
!isPredicate &&
|
606
|
+
env[name][STATS][SUB_RETURN_TYPE] === PREDICATE
|
607
|
+
) {
|
608
|
+
warningStack.add(
|
609
|
+
`${name} should end in (${PREDICATE_SUFFIX}) because it return (Predicate) (check #8)`
|
610
|
+
)
|
611
|
+
}
|
612
|
+
// }
|
568
613
|
// if (
|
569
614
|
// env[name][STATS][RETURNS] === UNKNOWN &&
|
570
615
|
// env[name][STATS].retried < RETRY_COUNT
|
@@ -696,10 +741,12 @@ export const typeCheck = (ast) => {
|
|
696
741
|
if (expectedArgs[i][TYPE] === UNKNOWN) continue
|
697
742
|
if (!isLeaf(rest[i])) {
|
698
743
|
const CAR = rest[i][0][VALUE]
|
699
|
-
|
744
|
+
const isKnown =
|
700
745
|
env[CAR] &&
|
701
746
|
env[CAR][STATS][RETURNS] != undefined &&
|
702
|
-
env[CAR][STATS][RETURNS] !== UNKNOWN
|
747
|
+
env[CAR][STATS][RETURNS] !== UNKNOWN
|
748
|
+
if (
|
749
|
+
isKnown &&
|
703
750
|
env[CAR][STATS][RETURNS] !==
|
704
751
|
expectedArgs[i][TYPE]
|
705
752
|
) {
|
@@ -714,10 +761,24 @@ export const typeCheck = (ast) => {
|
|
714
761
|
env[CAR][STATS][RETURNS]
|
715
762
|
)}) (${stringifyArgs(exp)}) (check #1)`
|
716
763
|
)
|
764
|
+
} else if (
|
765
|
+
isKnown &&
|
766
|
+
expectedArgs[i][SUB] &&
|
767
|
+
env[CAR][STATS][SUB_RETURN_TYPE] !==
|
768
|
+
expectedArgs[i][SUB]
|
769
|
+
) {
|
770
|
+
errorStack.set(
|
771
|
+
key.str,
|
772
|
+
`Incorrect type of arguments for special form (${
|
773
|
+
first[VALUE]
|
774
|
+
}). Expected (${toTypeNames(
|
775
|
+
expectedArgs[i][SUB]
|
776
|
+
)}) but got (${toTypeNames(
|
777
|
+
env[CAR][STATS][SUB_RETURN_TYPE] ??
|
778
|
+
env[CAR][STATS][RETURNS]
|
779
|
+
)}) (${stringifyArgs(exp)}) (check #13)`
|
780
|
+
)
|
717
781
|
}
|
718
|
-
// else {
|
719
|
-
// console.log(env[CAR])
|
720
|
-
// }
|
721
782
|
}
|
722
783
|
if (
|
723
784
|
env[rest[i][VALUE]] &&
|
@@ -886,6 +947,8 @@ export const typeCheck = (ast) => {
|
|
886
947
|
check(copy, root, copy)
|
887
948
|
while (stack.length) stack.pop()()
|
888
949
|
if (errorStack.size)
|
889
|
-
throw new TypeError(
|
950
|
+
throw new TypeError(
|
951
|
+
[...new Set(errorStack.values()), ...warningStack].join('\n')
|
952
|
+
)
|
890
953
|
return ast
|
891
954
|
}
|
package/src/compiler.js
CHANGED
package/src/interpreter.js
CHANGED
@@ -17,7 +17,7 @@ export const keywords = {
|
|
17
17
|
if (args.length != 2)
|
18
18
|
throw new RangeError(`Wrong number of args to ${KEYWORDS.LOOP}`)
|
19
19
|
while (evaluate(args[0], env) === TRUE) evaluate(args[1], env)
|
20
|
-
return
|
20
|
+
return -1
|
21
21
|
},
|
22
22
|
[KEYWORDS.ADDITION]: (args, env) => {
|
23
23
|
if (args.length !== 2)
|
package/src/utils.js
CHANGED
@@ -11,11 +11,13 @@ import {
|
|
11
11
|
export const logError = (error) =>
|
12
12
|
console.log('\x1b[31m', `\n${error}\n`, '\x1b[0m')
|
13
13
|
export const logSuccess = (output) => console.log('\x1b[32m', output, '\x1b[0m')
|
14
|
-
export const
|
15
|
-
|
14
|
+
export const formatCallstack = (callstack) =>
|
15
|
+
callstack
|
16
16
|
.reverse()
|
17
17
|
.map((x, i) => `${Array(i + 2).join(' ')}(${x} ...)`)
|
18
|
-
.join('\n')
|
18
|
+
.join('\n')
|
19
|
+
export const formatErrorWithCallstack = (error, callstack) => {
|
20
|
+
return `${error.message}\n${formatCallstack(callstack)}`
|
19
21
|
}
|
20
22
|
export const removeNoCode = (source) =>
|
21
23
|
source
|
@@ -193,7 +195,12 @@ const deepShake = (tree, deps, visited = new Set(), ignored = new Set()) => {
|
|
193
195
|
|
194
196
|
export const hasBlock = (body) =>
|
195
197
|
body[0] && body[0][TYPE] === APPLY && body[0][VALUE] === KEYWORDS.BLOCK
|
196
|
-
|
198
|
+
export const hasApplyLambdaBlock = (body) =>
|
199
|
+
body[0] &&
|
200
|
+
body[0][TYPE] === APPLY &&
|
201
|
+
body[0][VALUE] === KEYWORDS.CALL_FUNCTION &&
|
202
|
+
body[1][0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION &&
|
203
|
+
body[1][1][0][VALUE] === KEYWORDS.BLOCK
|
197
204
|
const extractDeps = (visited, deps) =>
|
198
205
|
[...visited]
|
199
206
|
.map((x) => deps.get(x))
|