fez-lisp 1.5.40 → 1.5.42
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 +745 -413
- package/src/compiler.js +0 -2
- package/src/evaluator.js +0 -1
- package/src/macros.js +3 -3
- package/src/parser.js +2 -8
- package/src/utils.js +1 -0
package/src/check.js
CHANGED
@@ -4,6 +4,7 @@ import {
|
|
4
4
|
DEBUG,
|
5
5
|
FALSE,
|
6
6
|
KEYWORDS,
|
7
|
+
MUTATION_SUFFIX,
|
7
8
|
PLACEHOLDER,
|
8
9
|
PREDICATE_SUFFIX,
|
9
10
|
SPECIAL_FORMS_SET,
|
@@ -13,7 +14,12 @@ import {
|
|
13
14
|
WORD
|
14
15
|
} from './keywords.js'
|
15
16
|
import { isLeaf } from './parser.js'
|
16
|
-
import {
|
17
|
+
import {
|
18
|
+
getSuffix,
|
19
|
+
hasApplyLambdaBlock,
|
20
|
+
hasBlock,
|
21
|
+
stringifyArgs
|
22
|
+
} from './utils.js'
|
17
23
|
const ARGS_COUNT = 'n'
|
18
24
|
const VARIADIC = '...'
|
19
25
|
const STATS = '__stats__'
|
@@ -21,7 +27,8 @@ const ARGS = 'args'
|
|
21
27
|
const UNKNOWN = -1
|
22
28
|
const RETURNS = 'returns'
|
23
29
|
const SCOPE_NAME = '__scope__'
|
24
|
-
const
|
30
|
+
const SUB_TYPE = 'subType'
|
31
|
+
const TYPE_PROP = 'type'
|
25
32
|
const PREDICATE = 3
|
26
33
|
const RETRY_COUNT = 1
|
27
34
|
const DEFINITON_RETRY_COUNT = 1
|
@@ -328,7 +335,7 @@ export const typeCheck = (ast) => {
|
|
328
335
|
[ARGS_COUNT]: 1,
|
329
336
|
[ARGS]: [[ATOM, PLACEHOLDER, PREDICATE]],
|
330
337
|
[RETURNS]: ATOM,
|
331
|
-
[
|
338
|
+
[SUB_TYPE]: PREDICATE
|
332
339
|
}
|
333
340
|
},
|
334
341
|
[KEYWORDS.EQUAL]: {
|
@@ -341,7 +348,7 @@ export const typeCheck = (ast) => {
|
|
341
348
|
[ATOM, PLACEHOLDER]
|
342
349
|
],
|
343
350
|
[RETURNS]: ATOM,
|
344
|
-
[
|
351
|
+
[SUB_TYPE]: PREDICATE
|
345
352
|
}
|
346
353
|
},
|
347
354
|
[KEYWORDS.LESS_THAN]: {
|
@@ -354,7 +361,7 @@ export const typeCheck = (ast) => {
|
|
354
361
|
[ATOM, PLACEHOLDER]
|
355
362
|
],
|
356
363
|
[RETURNS]: ATOM,
|
357
|
-
[
|
364
|
+
[SUB_TYPE]: PREDICATE
|
358
365
|
}
|
359
366
|
},
|
360
367
|
[KEYWORDS.GREATHER_THAN]: {
|
@@ -367,7 +374,7 @@ export const typeCheck = (ast) => {
|
|
367
374
|
[ATOM, PLACEHOLDER]
|
368
375
|
],
|
369
376
|
[RETURNS]: ATOM,
|
370
|
-
[
|
377
|
+
[SUB_TYPE]: PREDICATE
|
371
378
|
}
|
372
379
|
},
|
373
380
|
[KEYWORDS.GREATHER_THAN_OR_EQUAL]: {
|
@@ -380,7 +387,7 @@ export const typeCheck = (ast) => {
|
|
380
387
|
[ATOM, PLACEHOLDER]
|
381
388
|
],
|
382
389
|
[RETURNS]: ATOM,
|
383
|
-
[
|
390
|
+
[SUB_TYPE]: PREDICATE
|
384
391
|
}
|
385
392
|
},
|
386
393
|
[KEYWORDS.LESS_THAN_OR_EQUAL]: {
|
@@ -393,7 +400,7 @@ export const typeCheck = (ast) => {
|
|
393
400
|
[ATOM, PLACEHOLDER]
|
394
401
|
],
|
395
402
|
[RETURNS]: ATOM,
|
396
|
-
[
|
403
|
+
[SUB_TYPE]: PREDICATE
|
397
404
|
}
|
398
405
|
},
|
399
406
|
[KEYWORDS.AND]: {
|
@@ -406,7 +413,7 @@ export const typeCheck = (ast) => {
|
|
406
413
|
[ATOM, PLACEHOLDER, PREDICATE]
|
407
414
|
],
|
408
415
|
[RETURNS]: ATOM,
|
409
|
-
[
|
416
|
+
[SUB_TYPE]: PREDICATE
|
410
417
|
}
|
411
418
|
},
|
412
419
|
[KEYWORDS.OR]: {
|
@@ -419,7 +426,7 @@ export const typeCheck = (ast) => {
|
|
419
426
|
[ATOM, PLACEHOLDER, PREDICATE]
|
420
427
|
],
|
421
428
|
[RETURNS]: ATOM,
|
422
|
-
[
|
429
|
+
[SUB_TYPE]: PREDICATE
|
423
430
|
}
|
424
431
|
},
|
425
432
|
[KEYWORDS.IS_ATOM]: {
|
@@ -429,7 +436,7 @@ export const typeCheck = (ast) => {
|
|
429
436
|
[ARGS_COUNT]: 1,
|
430
437
|
[ARGS]: [[UNKNOWN, PLACEHOLDER]],
|
431
438
|
[RETURNS]: ATOM,
|
432
|
-
[
|
439
|
+
[SUB_TYPE]: PREDICATE
|
433
440
|
}
|
434
441
|
},
|
435
442
|
[KEYWORDS.IS_LAMBDA]: {
|
@@ -439,7 +446,7 @@ export const typeCheck = (ast) => {
|
|
439
446
|
[ARGS_COUNT]: 1,
|
440
447
|
[ARGS]: [[UNKNOWN, PLACEHOLDER]],
|
441
448
|
[RETURNS]: ATOM,
|
442
|
-
[
|
449
|
+
[SUB_TYPE]: PREDICATE
|
443
450
|
}
|
444
451
|
},
|
445
452
|
[KEYWORDS.ERROR]: {
|
@@ -463,7 +470,6 @@ export const typeCheck = (ast) => {
|
|
463
470
|
const getScopeNames = (scope) => {
|
464
471
|
const scopeNames = []
|
465
472
|
let current = scope
|
466
|
-
|
467
473
|
while (current) {
|
468
474
|
if (current[SCOPE_NAME]) {
|
469
475
|
scopeNames.push(current[SCOPE_NAME])
|
@@ -481,445 +487,736 @@ export const typeCheck = (ast) => {
|
|
481
487
|
const stack = []
|
482
488
|
const check = (exp, env, scope) => {
|
483
489
|
const [first, ...rest] = isLeaf(exp) ? [exp] : exp
|
484
|
-
if (first
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
490
|
+
if (first === undefined) {
|
491
|
+
throw new TypeError(
|
492
|
+
`(lambda) invocation with missing (Application) name () Provide an (Application) name as the (1) argument.`
|
493
|
+
)
|
494
|
+
}
|
495
|
+
switch (first[TYPE]) {
|
496
|
+
case WORD:
|
497
|
+
{
|
498
|
+
stack.push(() => {
|
499
|
+
const key = withScope(first[VALUE], scope)
|
500
|
+
if (env[first[VALUE]] === undefined) {
|
501
|
+
errorStack.set(
|
502
|
+
key.str,
|
503
|
+
`Trying to access undefined variable ${first[VALUE]} (check #11)`
|
494
504
|
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
505
|
+
// `Trying to access undefined variable ${
|
506
|
+
// first[VALUE]
|
507
|
+
// }\n${formatCallstack(
|
508
|
+
// key.chain.filter((x) => isNaN(Number(x[0])))
|
509
|
+
// )}\n(check #11)`
|
510
|
+
)
|
511
|
+
}
|
512
|
+
})
|
513
|
+
}
|
514
|
+
break
|
515
|
+
case ATOM:
|
516
|
+
break
|
517
|
+
case APPLY: {
|
518
|
+
switch (first[VALUE]) {
|
519
|
+
case KEYWORDS.DEFINE_VARIABLE:
|
520
|
+
{
|
521
|
+
if (rest.length !== 2) {
|
522
|
+
throw new TypeError(
|
523
|
+
`Incorrect number of arguments for (${
|
524
|
+
first[VALUE]
|
525
|
+
}). Expected (= 2) but got ${rest.length} (${stringifyArgs(
|
526
|
+
exp
|
527
|
+
)}) (check #10)`
|
500
528
|
)
|
501
|
-
}
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
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
|
-
// 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]]) {
|
570
|
-
env[name][STATS][RETURNS] =
|
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 {
|
575
|
-
env[name][STATS][RETURNS] = UNKNOWN
|
576
|
-
// env[name][STATS][RETURNS] = APPLY
|
577
|
-
}
|
578
|
-
}
|
579
|
-
break
|
580
|
-
default:
|
581
|
-
if (env[returns[VALUE]]) {
|
582
|
-
if (env[returns[VALUE]][STATS].type === APPLY) {
|
583
|
-
env[name][STATS][RETURNS] =
|
584
|
-
env[returns[VALUE]][STATS][RETURNS]
|
585
|
-
env[name][STATS][SUB_RETURN_TYPE] =
|
586
|
-
env[returns[VALUE]][STATS][SUB_RETURN_TYPE]
|
529
|
+
} else {
|
530
|
+
const name = rest[0][VALUE]
|
531
|
+
const resolveRetunType = (returns, rem, prop, isPredicate) => {
|
532
|
+
if (returns[TYPE] === ATOM) {
|
533
|
+
env[name][STATS][prop] = ATOM
|
534
|
+
} else {
|
535
|
+
switch (returns[VALUE]) {
|
536
|
+
case KEYWORDS.IF:
|
537
|
+
const re = rem.slice(2)
|
538
|
+
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
539
|
+
env[name][STATS][RETURNS] = ATOM
|
540
|
+
// if (
|
541
|
+
// re[0][VALUE] === FALSE ||
|
542
|
+
// re[0][VALUE] === TRUE ||
|
543
|
+
// re[1][VALUE] === FALSE ||
|
544
|
+
// re[1][VALUE] === TRUE
|
545
|
+
// ) {
|
546
|
+
// env[name][STATS][SUB_TYPE] = PREDICATE
|
547
|
+
// }
|
548
|
+
} else if (!isLeaf(re[0]) && env[re[0][0][VALUE]]) {
|
549
|
+
env[name][STATS][RETURNS] =
|
550
|
+
env[re[0][0][VALUE]][STATS][RETURNS]
|
551
|
+
env[name][STATS][SUB_TYPE] =
|
552
|
+
env[re[0][0][VALUE]][STATS][SUB_TYPE]
|
553
|
+
} else {
|
554
|
+
if (env[re[0][VALUE]]) {
|
555
|
+
env[name][STATS][RETURNS] =
|
556
|
+
env[re[0][VALUE]][STATS].type
|
557
|
+
env[name][STATS][SUB_TYPE] =
|
558
|
+
env[re[0][VALUE]][STATS][SUB_TYPE]
|
559
|
+
} else {
|
560
|
+
env[name][STATS][RETURNS] = UNKNOWN
|
561
|
+
// env[name][STATS][RETURNS] = APPLY
|
562
|
+
}
|
563
|
+
}
|
564
|
+
break
|
565
|
+
default:
|
566
|
+
if (env[returns[VALUE]]) {
|
567
|
+
if (env[returns[VALUE]][STATS].type === APPLY) {
|
568
|
+
if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
569
|
+
if (isLeaf(rest.at(-1).at(-1).at(-1))) {
|
570
|
+
const fnName = rest.at(-1).at(-1).at(-1)[VALUE]
|
571
|
+
const fn = env[fnName]
|
572
|
+
if (
|
573
|
+
!isPredicate &&
|
574
|
+
fn[STATS][SUB_TYPE] === PREDICATE
|
575
|
+
) {
|
576
|
+
warningStack.add(
|
577
|
+
`${name} is assigned to ${fnName} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #24)`
|
578
|
+
)
|
579
|
+
} else if (
|
580
|
+
isPredicate &&
|
581
|
+
fn[STATS][SUB_TYPE] !== PREDICATE
|
582
|
+
) {
|
583
|
+
warningStack.add(
|
584
|
+
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (try wrapping it in a (true?) or (false?)) (check #25)`
|
585
|
+
)
|
586
|
+
}
|
587
|
+
env[name][STATS].type = fn[STATS][RETURNS]
|
588
|
+
env[name][STATS][SUB_TYPE] = fn[STATS][SUB_TYPE]
|
587
589
|
} else {
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
590
|
+
const body = rest.at(-1).at(-1).at(-1).at(-1)
|
591
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
592
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
593
|
+
resolveRetunType(
|
594
|
+
returns,
|
595
|
+
rem,
|
596
|
+
TYPE_PROP,
|
597
|
+
isPredicate
|
598
|
+
)
|
592
599
|
}
|
593
|
-
} else {
|
594
|
-
env[name][STATS][RETURNS] = UNKNOWN
|
595
|
-
// env[name][STATS][RETURNS] = APPLY
|
596
600
|
}
|
597
|
-
|
601
|
+
env[name][STATS][RETURNS] =
|
602
|
+
env[returns[VALUE]][STATS][RETURNS]
|
603
|
+
env[name][STATS][SUB_TYPE] =
|
604
|
+
env[returns[VALUE]][STATS][SUB_TYPE]
|
605
|
+
} else {
|
606
|
+
env[name][STATS][RETURNS] =
|
607
|
+
env[returns[VALUE]][STATS].type
|
608
|
+
env[name][STATS][SUB_TYPE] =
|
609
|
+
env[returns[VALUE]][SUB_TYPE]
|
610
|
+
}
|
611
|
+
} else {
|
612
|
+
env[name][STATS][RETURNS] = UNKNOWN
|
613
|
+
// env[name][STATS][RETURNS] = APPLY
|
598
614
|
}
|
599
|
-
|
615
|
+
break
|
616
|
+
}
|
617
|
+
}
|
618
|
+
if (
|
619
|
+
isPredicate &&
|
620
|
+
env[name][STATS][prop] !== UNKNOWN &&
|
621
|
+
env[name][STATS][SUB_TYPE] !== PREDICATE
|
622
|
+
) {
|
623
|
+
warningStack.add(
|
624
|
+
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (try wrapping it in a (true?) or (false?)) (check #7)`
|
625
|
+
)
|
626
|
+
} else if (
|
627
|
+
!isPredicate &&
|
628
|
+
env[name][STATS][SUB_TYPE] === PREDICATE
|
629
|
+
) {
|
630
|
+
warningStack.add(
|
631
|
+
`${name} should end in (${PREDICATE_SUFFIX}) because it return (Predicate) (try adding ? at the end of the lambda name) (check #8)`
|
632
|
+
)
|
633
|
+
}
|
634
|
+
if (isPredicate) {
|
635
|
+
env[name][STATS][prop] = ATOM
|
636
|
+
env[name][STATS][SUB_TYPE] = PREDICATE
|
637
|
+
}
|
638
|
+
}
|
639
|
+
const checkReturnType = () => {
|
640
|
+
// if (name[name.length - 1] === PREDICATE_SUFFIX) {
|
641
|
+
// env[name][STATS][RETURNS] = ATOM
|
642
|
+
// env[name][STATS][SUB_TYPE] = PREDICATE
|
643
|
+
// } else {
|
644
|
+
const last = rest.at(-1).at(-1)
|
645
|
+
// const isApplyLambdaDoBlock = hasApplyLambdaBlock(
|
646
|
+
// rest.at(-1)
|
647
|
+
// )
|
648
|
+
const body = hasApplyLambdaBlock(last)
|
649
|
+
? last.at(-1).at(-1)
|
650
|
+
: last
|
651
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
652
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
653
|
+
const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
|
654
|
+
resolveRetunType(returns, rem, RETURNS, isPredicate)
|
655
|
+
// }
|
656
|
+
// if (
|
657
|
+
// env[name][STATS][RETURNS] === UNKNOWN &&
|
658
|
+
// env[name][STATS].retried < RETRY_COUNT
|
659
|
+
// ) {
|
660
|
+
// env[name][STATS].retried += 1
|
661
|
+
// console.log(name, env[name][STATS])
|
662
|
+
// checkReturnType()
|
663
|
+
// }
|
664
|
+
}
|
665
|
+
if (
|
666
|
+
rest.at(-1) &&
|
667
|
+
rest.at(-1)[0] &&
|
668
|
+
rest.at(-1)[0][TYPE] === APPLY &&
|
669
|
+
rest.at(-1)[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
|
670
|
+
) {
|
671
|
+
const n = rest.at(-1).length
|
672
|
+
env[name] = {
|
673
|
+
[STATS]: {
|
674
|
+
type: APPLY,
|
675
|
+
retried: 0,
|
676
|
+
[ARGS_COUNT]: n - 2,
|
677
|
+
[ARGS]: []
|
678
|
+
}
|
679
|
+
}
|
680
|
+
|
681
|
+
checkReturnType()
|
682
|
+
if (
|
683
|
+
env[name][STATS][RETURNS] === UNKNOWN &&
|
684
|
+
env[name][STATS].retried < DEFINITON_RETRY_COUNT
|
685
|
+
) {
|
686
|
+
env[name][STATS].retried += 1
|
687
|
+
stack.unshift(() => {
|
688
|
+
checkReturnType()
|
689
|
+
check(rest.at(-1), env, exp)
|
690
|
+
})
|
691
|
+
check(rest.at(-1), env, exp)
|
692
|
+
} else {
|
693
|
+
check(rest.at(-1), env, exp)
|
694
|
+
}
|
695
|
+
} else {
|
696
|
+
// if (!(name in env)) {
|
697
|
+
if (rest[1][TYPE] === WORD) {
|
698
|
+
env[name] = env[rest[1][VALUE]]
|
699
|
+
if (
|
700
|
+
getSuffix(rest[1][VALUE]) === PREDICATE_SUFFIX &&
|
701
|
+
getSuffix(name) !== PREDICATE_SUFFIX
|
702
|
+
)
|
703
|
+
warningStack.add(
|
704
|
+
`${name} is assigned to ${rest[1][VALUE]} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #17)`
|
705
|
+
)
|
706
|
+
else if (
|
707
|
+
getSuffix(rest[1][VALUE]) === MUTATION_SUFFIX &&
|
708
|
+
getSuffix(name) !== MUTATION_SUFFIX
|
709
|
+
)
|
710
|
+
warningStack.add(
|
711
|
+
`${name} is assigned to ${rest[1][VALUE]} which ends in (${MUTATION_SUFFIX}) so ${name} must also end in (${MUTATION_SUFFIX}) (check #18)`
|
712
|
+
)
|
713
|
+
} else {
|
714
|
+
const isL = isLeaf(rest.at(-1))
|
715
|
+
const right = isL ? rest.at(-1) : rest.at(-1)[0]
|
716
|
+
if (isL && right[TYPE] === ATOM) {
|
717
|
+
const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
|
600
718
|
if (
|
601
719
|
isPredicate &&
|
602
|
-
|
603
|
-
|
604
|
-
) {
|
605
|
-
warningStack.add(
|
606
|
-
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (try wrapping it in a (true?) or (false?)) (check #7)`
|
607
|
-
)
|
608
|
-
} else if (
|
609
|
-
!isPredicate &&
|
610
|
-
env[name][STATS][SUB_RETURN_TYPE] === PREDICATE
|
720
|
+
right[VALUE] !== TRUE &&
|
721
|
+
right[VALUE] !== FALSE
|
611
722
|
) {
|
612
723
|
warningStack.add(
|
613
|
-
`${name}
|
724
|
+
`${name} ends in (${PREDICATE_SUFFIX}) but is assigned to ${
|
725
|
+
right[VALUE]
|
726
|
+
} which is not a (${toTypeNames(
|
727
|
+
PREDICATE
|
728
|
+
)}). Either remove (${PREDICATE_SUFFIX}) or change the value to ${TRUE} or ${FALSE} (check #20)`
|
614
729
|
)
|
615
730
|
}
|
616
|
-
|
617
|
-
|
618
|
-
|
731
|
+
env[name] = {
|
732
|
+
[STATS]: {
|
733
|
+
retried: 0,
|
734
|
+
type: ATOM
|
735
|
+
}
|
619
736
|
}
|
620
|
-
|
621
|
-
// if (
|
622
|
-
// env[name][STATS][RETURNS] === UNKNOWN &&
|
623
|
-
// env[name][STATS].retried < RETRY_COUNT
|
624
|
-
// ) {
|
625
|
-
// env[name][STATS].retried += 1
|
626
|
-
// console.log(name, env[name][STATS])
|
627
|
-
// checkReturnType()
|
628
|
-
// }
|
629
|
-
}
|
630
|
-
checkReturnType()
|
631
|
-
if (
|
632
|
-
env[name][STATS][RETURNS] === UNKNOWN &&
|
633
|
-
env[name][STATS].retried < DEFINITON_RETRY_COUNT
|
634
|
-
) {
|
635
|
-
env[name][STATS].retried += 1
|
636
|
-
stack.unshift(() => {
|
637
|
-
checkReturnType()
|
638
|
-
check(rest.at(-1), env, exp)
|
639
|
-
})
|
640
|
-
check(rest.at(-1), env, exp)
|
737
|
+
if (isPredicate) env[name][STATS][SUB_TYPE] = PREDICATE
|
641
738
|
} else {
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
[
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
739
|
+
const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
|
740
|
+
if (
|
741
|
+
right &&
|
742
|
+
right[VALUE] &&
|
743
|
+
getSuffix(right[VALUE]) === PREDICATE_SUFFIX &&
|
744
|
+
!isPredicate
|
745
|
+
)
|
746
|
+
warningStack.add(
|
747
|
+
`${name} is assigned to ${right[VALUE]} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #19)`
|
748
|
+
)
|
749
|
+
env[name] = {
|
750
|
+
[STATS]: {
|
751
|
+
retried: 0,
|
752
|
+
type: isL
|
753
|
+
? right[TYPE]
|
754
|
+
: env[right?.[VALUE]]?.[STATS]?.[RETURNS] ?? UNKNOWN
|
755
|
+
}
|
756
|
+
}
|
757
|
+
if (isPredicate) env[name][STATS][SUB_TYPE] = PREDICATE
|
758
|
+
if (right && right[VALUE]) {
|
759
|
+
if (right[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
760
|
+
if (isLeaf(rest.at(-1).at(-1))) {
|
761
|
+
const fnName = rest.at(-1).at(-1)[VALUE]
|
762
|
+
const fn = env[fnName]
|
763
|
+
if (
|
764
|
+
!isPredicate &&
|
765
|
+
fn[STATS][SUB_TYPE] === PREDICATE
|
766
|
+
) {
|
767
|
+
warningStack.add(
|
768
|
+
`${name} is assigned to ${fnName} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #24)`
|
769
|
+
)
|
770
|
+
} else if (
|
771
|
+
isPredicate &&
|
772
|
+
fn[STATS][SUB_TYPE] !== PREDICATE
|
773
|
+
) {
|
774
|
+
warningStack.add(
|
775
|
+
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (try wrapping it in a (true?) or (false?)) (check #25)`
|
776
|
+
)
|
777
|
+
}
|
778
|
+
env[name][STATS].type = fn[STATS][RETURNS]
|
779
|
+
env[name][STATS][SUB_TYPE] = fn[STATS][SUB_TYPE]
|
780
|
+
} else {
|
781
|
+
const body = rest.at(-1).at(-1).at(-1)
|
782
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
783
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
784
|
+
// console.log({ returns })
|
785
|
+
resolveRetunType(
|
786
|
+
returns,
|
787
|
+
rem,
|
788
|
+
TYPE_PROP,
|
789
|
+
isPredicate
|
790
|
+
)
|
791
|
+
}
|
792
|
+
}
|
793
|
+
if (env[right[VALUE]]?.[STATS]?.[SUB_TYPE]) {
|
794
|
+
if (
|
795
|
+
env[right[VALUE]][STATS][SUB_TYPE] === PREDICATE &&
|
796
|
+
!isPredicate
|
797
|
+
) {
|
798
|
+
warningStack.add(
|
799
|
+
`${name} is assigned to the result of a (${toTypeNames(
|
800
|
+
PREDICATE
|
801
|
+
)}) so ${name} must end in (${PREDICATE_SUFFIX}) (check #23)`
|
802
|
+
)
|
657
803
|
}
|
804
|
+
env[name][STATS][SUB_TYPE] =
|
805
|
+
env[right[VALUE]][STATS][SUB_TYPE]
|
658
806
|
}
|
807
|
+
}
|
659
808
|
}
|
660
|
-
|
809
|
+
|
810
|
+
// console.log(name, env[name])
|
661
811
|
}
|
812
|
+
// }
|
813
|
+
check(rest.at(-1), env, scope)
|
662
814
|
}
|
663
815
|
}
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
)
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
816
|
+
}
|
817
|
+
break
|
818
|
+
case KEYWORDS.ANONYMOUS_FUNCTION:
|
819
|
+
{
|
820
|
+
if (exp.length === 1) {
|
821
|
+
throw new TypeError(
|
822
|
+
`Incorrect number of arguments for (${
|
823
|
+
first[VALUE]
|
824
|
+
}). Expected at least 1 (the lambda body) but got 1 (${stringifyArgs(
|
825
|
+
exp
|
826
|
+
)}) (check #10)`
|
827
|
+
)
|
828
|
+
}
|
829
|
+
const params = exp.slice(1, -1)
|
830
|
+
const copy = Object.create(env)
|
831
|
+
if (Array.isArray(scope[1]) && scope[1][TYPE] === WORD) {
|
832
|
+
copy[SCOPE_NAME] = scope[1][VALUE]
|
833
|
+
} else {
|
834
|
+
copy[SCOPE_NAME] = performance.now().toString().replace('.', 0)
|
835
|
+
}
|
836
|
+
for (let i = 0; i < params.length; ++i) {
|
837
|
+
const param = params[i]
|
838
|
+
copy[param[VALUE]] = {
|
839
|
+
[STATS]: { type: UNKNOWN, retried: 0 }
|
685
840
|
}
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
[STATS]
|
690
|
-
|
691
|
-
if (env[copy[SCOPE_NAME]]) {
|
692
|
-
env[copy[SCOPE_NAME]][STATS][ARGS][i] = copy[param[VALUE]]
|
693
|
-
if (
|
694
|
-
param[VALUE][param[VALUE].length - 1] === PREDICATE_SUFFIX
|
695
|
-
) {
|
696
|
-
copy[param[VALUE]][STATS][RETURNS] = ATOM
|
697
|
-
copy[param[VALUE]][STATS][SUB_RETURN_TYPE] = PREDICATE
|
698
|
-
}
|
841
|
+
if (env[copy[SCOPE_NAME]]) {
|
842
|
+
env[copy[SCOPE_NAME]][STATS][ARGS][i] = copy[param[VALUE]]
|
843
|
+
if (getSuffix(param[VALUE]) === PREDICATE_SUFFIX) {
|
844
|
+
copy[param[VALUE]][STATS][RETURNS] = ATOM
|
845
|
+
copy[param[VALUE]][STATS][SUB_TYPE] = PREDICATE
|
699
846
|
}
|
700
847
|
}
|
701
|
-
check(rest.at(-1), copy, copy)
|
702
848
|
}
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
849
|
+
check(rest.at(-1), copy, copy)
|
850
|
+
}
|
851
|
+
break
|
852
|
+
default:
|
853
|
+
stack.push(() => {
|
854
|
+
const key = withScope(first[VALUE], scope)
|
855
|
+
if (env[first[VALUE]] === undefined)
|
856
|
+
errorStack.set(
|
857
|
+
key.str,
|
858
|
+
`Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
|
859
|
+
)
|
860
|
+
else {
|
861
|
+
if (
|
862
|
+
env[first[VALUE]][STATS].type === APPLY &&
|
863
|
+
env[first[VALUE]][STATS][ARGS_COUNT] !== VARIADIC &&
|
864
|
+
env[first[VALUE]][STATS][ARGS_COUNT] !== rest.length
|
865
|
+
) {
|
708
866
|
errorStack.set(
|
709
867
|
key.str,
|
710
|
-
`
|
868
|
+
`Incorrect number of arguments for (${
|
869
|
+
first[VALUE]
|
870
|
+
}). Expected (= ${
|
871
|
+
env[first[VALUE]][STATS][ARGS_COUNT]
|
872
|
+
}) but got ${rest.length} (${stringifyArgs(
|
873
|
+
exp
|
874
|
+
)}) (check #15)`
|
711
875
|
)
|
712
|
-
else {
|
713
|
-
|
714
|
-
env[first[VALUE]][STATS].type === APPLY &&
|
715
|
-
env[first[VALUE]][STATS][ARGS_COUNT] !== VARIADIC &&
|
716
|
-
env[first[VALUE]][STATS][ARGS_COUNT] !== rest.length
|
717
|
-
) {
|
718
|
-
errorStack.set(
|
719
|
-
key.str,
|
720
|
-
`Incorrect number of arguments for (${
|
721
|
-
first[VALUE]
|
722
|
-
}). Expected (= ${
|
723
|
-
env[first[VALUE]][STATS][ARGS_COUNT]
|
724
|
-
}) but got ${rest.length} (${stringifyArgs(
|
725
|
-
exp
|
726
|
-
)}) (check #15)`
|
727
|
-
)
|
728
|
-
} else {
|
729
|
-
const isSpecial = SPECIAL_FORMS_SET.has(first[VALUE])
|
876
|
+
} else {
|
877
|
+
const isSpecial = SPECIAL_FORMS_SET.has(first[VALUE])
|
730
878
|
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
}
|
879
|
+
if (first[TYPE] === APPLY && !isSpecial) {
|
880
|
+
if (env[first[VALUE]][STATS].type === ATOM) {
|
881
|
+
errorStack.set(
|
882
|
+
key.str,
|
883
|
+
`(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
|
884
|
+
exp
|
885
|
+
)}) (check #12)`
|
886
|
+
)
|
887
|
+
} else if (!env[first[VALUE]][STATS][ARGS_COUNT]) {
|
888
|
+
env[first[VALUE]][STATS][RETURNS] = UNKNOWN
|
889
|
+
env[first[VALUE]][STATS].type = APPLY
|
890
|
+
env[first[VALUE]][STATS][ARGS_COUNT] = rest.length
|
744
891
|
}
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
env[CAR] &&
|
762
|
-
env[CAR][STATS][RETURNS] != undefined &&
|
763
|
-
env[CAR][STATS][RETURNS] !== UNKNOWN
|
764
|
-
if (
|
765
|
-
isKnown &&
|
766
|
-
env[CAR][STATS][RETURNS] !==
|
767
|
-
expectedArgs[i][TYPE]
|
768
|
-
) {
|
769
|
-
// console.log(env[CAR][STATS], expectedArgs[i][TYPE])
|
770
|
-
errorStack.set(
|
771
|
-
key.str,
|
772
|
-
`Incorrect type of arguments for special form (${
|
773
|
-
first[VALUE]
|
774
|
-
}). Expected (${toTypeNames(
|
775
|
-
expectedArgs[i][TYPE]
|
776
|
-
)}) but got (${toTypeNames(
|
777
|
-
env[CAR][STATS][RETURNS]
|
778
|
-
)}) (${stringifyArgs(exp)}) (check #1)`
|
779
|
-
)
|
780
|
-
} else if (
|
781
|
-
isKnown &&
|
782
|
-
expectedArgs[i][SUB] &&
|
783
|
-
env[CAR][STATS][SUB_RETURN_TYPE] !==
|
784
|
-
expectedArgs[i][SUB]
|
785
|
-
) {
|
786
|
-
errorStack.set(
|
787
|
-
key.str,
|
788
|
-
`Incorrect type of arguments for special form (${
|
789
|
-
first[VALUE]
|
790
|
-
}). Expected (${toTypeNames(
|
791
|
-
expectedArgs[i][SUB]
|
792
|
-
)}) but got (${toTypeNames(
|
793
|
-
env[CAR][STATS][SUB_RETURN_TYPE] ??
|
794
|
-
env[CAR][STATS][RETURNS]
|
795
|
-
)}) (${stringifyArgs(exp)}) (check #13)`
|
796
|
-
)
|
797
|
-
}
|
798
|
-
}
|
892
|
+
}
|
893
|
+
|
894
|
+
// also type of arg
|
895
|
+
const args = env[first[VALUE]][STATS][ARGS]
|
896
|
+
if (args) {
|
897
|
+
for (let i = 0; i < args.length; ++i) {
|
898
|
+
// type check
|
899
|
+
// todo finish this
|
900
|
+
|
901
|
+
if (args[i][SUB] != undefined) {
|
902
|
+
// first[TYPE] === APPLY &&
|
903
|
+
// env[first[VALUE]][STATS][SUB_TYPE] === PREDICATE
|
904
|
+
// args[i][SUB] = env[rest[i][VALUE]][SUB_TYPE]
|
905
|
+
if (isLeaf(rest[i])) {
|
906
|
+
if (rest[i][TYPE] === WORD) {
|
907
|
+
// TODO finish this
|
799
908
|
if (
|
800
909
|
env[rest[i][VALUE]] &&
|
801
|
-
|
910
|
+
args[i][SUB] !==
|
911
|
+
env[rest[i][VALUE]][STATS][SUB_TYPE]
|
802
912
|
) {
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
913
|
+
errorStack.set(
|
914
|
+
key.str,
|
915
|
+
`Incorrect type of arguments for (${
|
916
|
+
first[VALUE]
|
917
|
+
}). Expected (${toTypeNames(
|
918
|
+
args[i][SUB]
|
919
|
+
)}) but got (${toTypeNames(
|
920
|
+
env[rest[i][VALUE]][STATS][SUB_TYPE] ??
|
921
|
+
env[rest[i][VALUE]][STATS].type
|
922
|
+
)}) (${stringifyArgs(exp)}) (check #16)`
|
923
|
+
)
|
924
|
+
}
|
925
|
+
} else if (rest[i][TYPE] === ATOM) {
|
926
|
+
if (
|
927
|
+
args[i][SUB] === PREDICATE &&
|
928
|
+
rest[i][VALUE] !== TRUE &&
|
929
|
+
rest[i][VALUE] !== FALSE
|
930
|
+
) {
|
931
|
+
errorStack.set(
|
932
|
+
key.str,
|
933
|
+
`Incorrect type of arguments for (${
|
934
|
+
first[VALUE]
|
935
|
+
}). Expected (${toTypeNames(
|
936
|
+
args[i][SUB]
|
937
|
+
)}) but got an (${toTypeNames(
|
938
|
+
rest[i][TYPE]
|
939
|
+
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
940
|
+
exp
|
941
|
+
)}) (check #22)`
|
942
|
+
)
|
943
|
+
}
|
944
|
+
}
|
945
|
+
} else {
|
946
|
+
const current = rest[i][0]
|
947
|
+
if (current[TYPE] === APPLY) {
|
948
|
+
if (current[VALUE] == KEYWORDS.CALL_FUNCTION) {
|
949
|
+
if (isLeaf(rest[i].at(-1))) {
|
950
|
+
const fnName = rest[i].at(-1)[VALUE]
|
951
|
+
const fn = env[fnName]
|
952
|
+
if (
|
953
|
+
fn &&
|
954
|
+
fn[STATS][RETURNS] !== args[i][TYPE]
|
955
|
+
) {
|
956
|
+
errorStack.set(
|
957
|
+
key.str,
|
958
|
+
`Incorrect type of arguments for (${
|
959
|
+
first[VALUE]
|
960
|
+
}). Expected (${toTypeNames(
|
961
|
+
args[i][TYPE]
|
962
|
+
)}) but got an (${toTypeNames(
|
963
|
+
fn[STATS][RETURNS]
|
964
|
+
)}) (${stringifyArgs(exp)}) (check #26)`
|
965
|
+
)
|
966
|
+
}
|
967
|
+
if (
|
968
|
+
fn &&
|
969
|
+
fn[STATS][SUB_TYPE] !== args[i][SUB]
|
970
|
+
) {
|
971
|
+
errorStack.set(
|
972
|
+
key.str,
|
973
|
+
`Incorrect type of arguments for (${
|
974
|
+
first[VALUE]
|
975
|
+
}). Expected (${toTypeNames(
|
976
|
+
args[i][SUB]
|
977
|
+
)}) but got an (${toTypeNames(
|
978
|
+
fn[STATS][SUB_TYPE]
|
979
|
+
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
980
|
+
exp
|
981
|
+
)}) (check #27)`
|
982
|
+
)
|
983
|
+
}
|
984
|
+
// env[name][STATS].type = fn[STATS][RETURNS]
|
985
|
+
// env[name][STATS][SUB_TYPE] = fn[STATS][SUB_TYPE]
|
986
|
+
} else {
|
987
|
+
const body = rest[i].at(-1).at(-1)
|
988
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
989
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
990
|
+
if (returns[TYPE] === ATOM) {
|
991
|
+
if (args[i][TYPE] !== ATOM) {
|
992
|
+
errorStack.set(
|
993
|
+
key.str,
|
994
|
+
`Incorrect type of argument ${i} for (${
|
995
|
+
first[VALUE]
|
996
|
+
}). Expected (${toTypeNames(
|
997
|
+
args[i][TYPE]
|
998
|
+
)}) but got an (${toTypeNames(
|
999
|
+
ATOM
|
1000
|
+
)}) (${stringifyArgs(exp)}) (check #27)`
|
817
1001
|
)
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
)}) but got (${toTypeNames(
|
825
|
-
rest[i][TYPE]
|
826
|
-
)}) (${stringifyArgs(exp)}) (check #2)`
|
827
|
-
)
|
828
|
-
} else if (
|
829
|
-
T !== UNKNOWN &&
|
830
|
-
expectedArgs[i][TYPE] !== UNKNOWN &&
|
831
|
-
expectedArgs[i][TYPE] !== T
|
1002
|
+
}
|
1003
|
+
if (
|
1004
|
+
args[i][SUB] &&
|
1005
|
+
args[i][SUB] === PREDICATE &&
|
1006
|
+
returns[VALUE] !== TRUE &&
|
1007
|
+
returns[VALUE] !== FALSE
|
832
1008
|
) {
|
833
1009
|
errorStack.set(
|
834
1010
|
key.str,
|
835
|
-
`Incorrect type of
|
1011
|
+
`Incorrect type of argument ${i} for (${
|
836
1012
|
first[VALUE]
|
837
1013
|
}). Expected (${toTypeNames(
|
838
|
-
|
1014
|
+
args[i][SUB]
|
1015
|
+
)}) but got an (${toTypeNames(
|
1016
|
+
ATOM
|
1017
|
+
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
1018
|
+
exp
|
1019
|
+
)}) (check #27)`
|
1020
|
+
)
|
1021
|
+
}
|
1022
|
+
} else if (env[returns[VALUE]]) {
|
1023
|
+
if (
|
1024
|
+
args[i][TYPE] !==
|
1025
|
+
env[returns[VALUE]][STATS][RETURNS]
|
1026
|
+
) {
|
1027
|
+
errorStack.set(
|
1028
|
+
key.str,
|
1029
|
+
`Incorrect type of argument ${i} for (${
|
1030
|
+
first[VALUE]
|
1031
|
+
}). Expected (${toTypeNames(
|
1032
|
+
args[i][TYPE]
|
839
1033
|
)}) but got (${toTypeNames(
|
840
|
-
|
841
|
-
)})
|
1034
|
+
env[returns[VALUE]][STATS][TYPE_PROP]
|
1035
|
+
)}) (${stringifyArgs(exp)}) (check #29)`
|
842
1036
|
)
|
843
|
-
} else {
|
844
|
-
env[rest[i][VALUE]][STATS].type =
|
845
|
-
expectedArgs[i][TYPE]
|
846
1037
|
}
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
1038
|
+
if (
|
1039
|
+
args[i][SUB] &&
|
1040
|
+
args[i][SUB] !==
|
1041
|
+
env[returns[VALUE]][STATS][SUB_TYPE]
|
1042
|
+
) {
|
1043
|
+
errorStack.set(
|
1044
|
+
key.str,
|
1045
|
+
`Incorrect type of argument ${i} for (${
|
1046
|
+
first[VALUE]
|
1047
|
+
}). Expected (${toTypeNames(
|
1048
|
+
args[i][SUB]
|
1049
|
+
)}) but got (${toTypeNames(
|
1050
|
+
env[returns[VALUE]][STATS][SUB_TYPE]
|
1051
|
+
)}) (${stringifyArgs(exp)}) (check #28)`
|
1052
|
+
)
|
1053
|
+
}
|
1054
|
+
}
|
1055
|
+
|
1056
|
+
// // console.log({ returns })
|
1057
|
+
// resolveRetunType(
|
1058
|
+
// returns,
|
1059
|
+
// rem,
|
1060
|
+
// TYPE_PROP,
|
1061
|
+
// isPredicate
|
1062
|
+
// )
|
861
1063
|
}
|
1064
|
+
|
1065
|
+
// console.log(args[i], env[current[VALUE]][STATS])
|
1066
|
+
} else if (
|
1067
|
+
env[current[VALUE]][STATS][SUB_TYPE] !==
|
1068
|
+
args[i][SUB]
|
1069
|
+
) {
|
1070
|
+
errorStack.set(
|
1071
|
+
key.str,
|
1072
|
+
`Incorrect type of arguments (${i}) for (${
|
1073
|
+
first[VALUE]
|
1074
|
+
}). Expected (${toTypeNames(
|
1075
|
+
args[i][SUB]
|
1076
|
+
)}) but got (${toTypeNames(
|
1077
|
+
env[current[VALUE]][STATS][SUB_TYPE] ??
|
1078
|
+
env[current[VALUE]][STATS][RETURNS]
|
1079
|
+
)}) (${stringifyArgs(exp)}) (check #21)`
|
1080
|
+
)
|
862
1081
|
}
|
863
1082
|
}
|
864
1083
|
}
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
1084
|
+
}
|
1085
|
+
|
1086
|
+
if (
|
1087
|
+
first[TYPE] === APPLY &&
|
1088
|
+
isSpecial
|
1089
|
+
// &&
|
1090
|
+
// env[first[VALUE]][STATS][ARGS_COUNT] !== VARIADIC
|
1091
|
+
) {
|
1092
|
+
const expectedArgs = env[first[VALUE]][STATS][ARGS]
|
1093
|
+
for (let i = 0; i < rest.length; ++i) {
|
1094
|
+
if (expectedArgs[i][TYPE] === UNKNOWN) continue
|
1095
|
+
if (!isLeaf(rest[i])) {
|
1096
|
+
const CAR = rest[i][0][VALUE]
|
1097
|
+
const isKnown =
|
1098
|
+
env[CAR] &&
|
1099
|
+
env[CAR][STATS][RETURNS] != undefined &&
|
1100
|
+
env[CAR][STATS][RETURNS] !== UNKNOWN
|
876
1101
|
if (
|
877
|
-
|
878
|
-
|
879
|
-
args[i][STATS].type !== ATOM) ||
|
880
|
-
(env[rest[i][VALUE]] &&
|
881
|
-
env[rest[i][VALUE]][STATS].type !== UNKNOWN &&
|
882
|
-
args[i][STATS].type !== UNKNOWN &&
|
883
|
-
env[rest[i][VALUE]][STATS].type !==
|
884
|
-
args[i][STATS].type)
|
1102
|
+
isKnown &&
|
1103
|
+
env[CAR][STATS][RETURNS] !== expectedArgs[i][TYPE]
|
885
1104
|
) {
|
1105
|
+
// console.log(env[CAR][STATS], expectedArgs[i][TYPE])
|
886
1106
|
errorStack.set(
|
887
1107
|
key.str,
|
888
|
-
`Incorrect type of arguments
|
1108
|
+
`Incorrect type of arguments for special form (${
|
889
1109
|
first[VALUE]
|
890
1110
|
}). Expected (${toTypeNames(
|
891
|
-
|
1111
|
+
expectedArgs[i][TYPE]
|
892
1112
|
)}) but got (${toTypeNames(
|
893
|
-
|
894
|
-
)}) (${stringifyArgs(exp)})`
|
1113
|
+
env[CAR][STATS][RETURNS]
|
1114
|
+
)}) (${stringifyArgs(exp)}) (check #1)`
|
1115
|
+
)
|
1116
|
+
} else if (
|
1117
|
+
isKnown &&
|
1118
|
+
expectedArgs[i][SUB] &&
|
1119
|
+
env[CAR][STATS][SUB_TYPE] !== expectedArgs[i][SUB]
|
1120
|
+
) {
|
1121
|
+
errorStack.set(
|
1122
|
+
key.str,
|
1123
|
+
`Incorrect type of arguments for special form (${
|
1124
|
+
first[VALUE]
|
1125
|
+
}). Expected (${toTypeNames(
|
1126
|
+
expectedArgs[i][SUB]
|
1127
|
+
)}) but got (${toTypeNames(
|
1128
|
+
env[CAR][STATS][SUB_TYPE] ??
|
1129
|
+
env[CAR][STATS][RETURNS]
|
1130
|
+
)}) (${stringifyArgs(exp)}) (check #13)`
|
895
1131
|
)
|
896
|
-
} else {
|
897
|
-
// env[rest[i][VALUE]][STATS] THiss SHOULD BE
|
898
|
-
const retry = env[rest[i][VALUE]]
|
899
|
-
if (
|
900
|
-
retry &&
|
901
|
-
retry[STATS].retried < RETRY_COUNT &&
|
902
|
-
args[i][STATS].type === UNKNOWN
|
903
|
-
) {
|
904
|
-
retry[STATS].retried += 1
|
905
|
-
stack.unshift(() => check(exp, env, scope))
|
906
|
-
}
|
907
|
-
// console.log(
|
908
|
-
// first[VALUE],
|
909
|
-
// env[first[VALUE]][STATS],
|
910
|
-
// rest[i][TYPE],
|
911
|
-
// args[i][STATS].type
|
912
|
-
// )
|
913
1132
|
}
|
914
|
-
}
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
1133
|
+
}
|
1134
|
+
if (
|
1135
|
+
env[rest[i][VALUE]] &&
|
1136
|
+
expectedArgs[i][TYPE] !== rest[i][TYPE]
|
1137
|
+
) {
|
1138
|
+
switch (rest[i][TYPE]) {
|
1139
|
+
case UNKNOWN:
|
1140
|
+
env[first[VALUE]][STATS].type =
|
1141
|
+
expectedArgs[i][TYPE]
|
1142
|
+
break
|
1143
|
+
case WORD:
|
1144
|
+
const T = env[rest[i][VALUE]][STATS].type
|
1145
|
+
if (Array.isArray(T)) {
|
1146
|
+
const TT = T[VALUE]
|
1147
|
+
if (
|
1148
|
+
env[TT][STATS][RETURNS] &&
|
1149
|
+
env[TT][STATS][RETURNS] !== UNKNOWN &&
|
1150
|
+
expectedArgs[i][TYPE] !==
|
1151
|
+
env[TT][STATS][RETURNS]
|
1152
|
+
)
|
1153
|
+
errorStack.set(
|
1154
|
+
key.str,
|
1155
|
+
`Incorrect type of arguments for special form (${
|
1156
|
+
first[VALUE]
|
1157
|
+
}). Expected (${toTypeNames(
|
1158
|
+
expectedArgs[i][TYPE]
|
1159
|
+
)}) but got (${toTypeNames(
|
1160
|
+
rest[i][TYPE]
|
1161
|
+
)}) (${stringifyArgs(exp)}) (check #2)`
|
1162
|
+
)
|
1163
|
+
} else if (
|
1164
|
+
T !== UNKNOWN &&
|
1165
|
+
expectedArgs[i][TYPE] !== UNKNOWN &&
|
1166
|
+
expectedArgs[i][TYPE] !== T
|
1167
|
+
) {
|
1168
|
+
errorStack.set(
|
1169
|
+
key.str,
|
1170
|
+
`Incorrect type of arguments for special form (${
|
1171
|
+
first[VALUE]
|
1172
|
+
}). Expected (${toTypeNames(
|
1173
|
+
expectedArgs[i][TYPE]
|
1174
|
+
)}) but got (${toTypeNames(
|
1175
|
+
T
|
1176
|
+
)}) (${stringifyArgs(exp)}) (check #3)`
|
1177
|
+
)
|
1178
|
+
} else {
|
1179
|
+
env[rest[i][VALUE]][STATS].type =
|
1180
|
+
expectedArgs[i][TYPE]
|
1181
|
+
}
|
1182
|
+
break
|
1183
|
+
case APPLY:
|
1184
|
+
case ATOM:
|
1185
|
+
errorStack.set(
|
1186
|
+
key.str,
|
1187
|
+
`Incorrect type of arguments for (${
|
1188
|
+
first[VALUE]
|
1189
|
+
}). Expected (${toTypeNames(
|
1190
|
+
expectedArgs[i][TYPE]
|
1191
|
+
)}) but got (${toTypeNames(
|
1192
|
+
rest[i][TYPE]
|
1193
|
+
)}) (${stringifyArgs(exp)}) (check #5)`
|
1194
|
+
)
|
1195
|
+
break
|
1196
|
+
}
|
1197
|
+
}
|
1198
|
+
}
|
1199
|
+
}
|
1200
|
+
// type checking
|
1201
|
+
else if (
|
1202
|
+
rest[i] &&
|
1203
|
+
args[i][STATS] &&
|
1204
|
+
rest[i][TYPE] !== args[i][STATS].type
|
1205
|
+
) {
|
1206
|
+
if (isLeaf(rest[i])) {
|
1207
|
+
const T =
|
1208
|
+
rest[i][TYPE] === WORD && env[rest[i][VALUE]]
|
1209
|
+
? env[rest[i][VALUE]][STATS].type
|
1210
|
+
: rest[i][TYPE]
|
1211
|
+
if (
|
1212
|
+
(args[i][STATS].type !== UNKNOWN &&
|
1213
|
+
T === ATOM &&
|
1214
|
+
args[i][STATS].type !== ATOM) ||
|
1215
|
+
(env[rest[i][VALUE]] &&
|
1216
|
+
env[rest[i][VALUE]][STATS].type !== UNKNOWN &&
|
1217
|
+
args[i][STATS].type !== UNKNOWN &&
|
1218
|
+
env[rest[i][VALUE]][STATS].type !==
|
1219
|
+
args[i][STATS].type)
|
923
1220
|
) {
|
924
1221
|
errorStack.set(
|
925
1222
|
key.str,
|
@@ -927,33 +1224,68 @@ export const typeCheck = (ast) => {
|
|
927
1224
|
first[VALUE]
|
928
1225
|
}). Expected (${toTypeNames(
|
929
1226
|
args[i][STATS].type
|
930
|
-
)}) but got (${toTypeNames(
|
931
|
-
|
932
|
-
)})
|
1227
|
+
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
1228
|
+
exp
|
1229
|
+
)})`
|
933
1230
|
)
|
934
1231
|
} else {
|
1232
|
+
// env[rest[i][VALUE]][STATS] THiss SHOULD BE
|
1233
|
+
const retry = env[rest[i][VALUE]]
|
935
1234
|
if (
|
936
|
-
|
937
|
-
|
938
|
-
args[i][STATS].type === UNKNOWN
|
939
|
-
env[rest[i][0][VALUE]][STATS].retried <
|
940
|
-
RETRY_COUNT
|
1235
|
+
retry &&
|
1236
|
+
retry[STATS].retried < RETRY_COUNT &&
|
1237
|
+
args[i][STATS].type === UNKNOWN
|
941
1238
|
) {
|
942
|
-
|
943
|
-
if (!scope[SCOPE_NAME])
|
944
|
-
scope[SCOPE_NAME] = scope[1][VALUE]
|
1239
|
+
retry[STATS].retried += 1
|
945
1240
|
stack.unshift(() => check(exp, env, scope))
|
946
1241
|
}
|
1242
|
+
// console.log(
|
1243
|
+
// first[VALUE],
|
1244
|
+
// env[first[VALUE]][STATS],
|
1245
|
+
// rest[i][TYPE],
|
1246
|
+
// args[i][STATS].type
|
1247
|
+
// )
|
1248
|
+
}
|
1249
|
+
} else if (
|
1250
|
+
rest[i].length &&
|
1251
|
+
SPECIAL_FORMS_SET.has(rest[i][0][VALUE]) &&
|
1252
|
+
env[rest[i][0][VALUE]] &&
|
1253
|
+
env[rest[i][0][VALUE]][STATS][RETURNS] !== UNKNOWN &&
|
1254
|
+
args[i][STATS].type !== UNKNOWN &&
|
1255
|
+
env[rest[i][0][VALUE]][STATS][RETURNS] !==
|
1256
|
+
args[i][STATS].type
|
1257
|
+
) {
|
1258
|
+
errorStack.set(
|
1259
|
+
key.str,
|
1260
|
+
`Incorrect type of arguments ${i} for (${
|
1261
|
+
first[VALUE]
|
1262
|
+
}). Expected (${toTypeNames(
|
1263
|
+
args[i][STATS].type
|
1264
|
+
)}) but got (${toTypeNames(
|
1265
|
+
env[rest[i][0][VALUE]][STATS][RETURNS]
|
1266
|
+
)}) (${stringifyArgs(exp)}) (check #4)`
|
1267
|
+
)
|
1268
|
+
} else {
|
1269
|
+
if (
|
1270
|
+
rest[i].length &&
|
1271
|
+
env[rest[i][0][VALUE]] &&
|
1272
|
+
args[i][STATS].type === UNKNOWN &&
|
1273
|
+
env[rest[i][0][VALUE]][STATS].retried < RETRY_COUNT
|
1274
|
+
) {
|
1275
|
+
env[rest[i][0][VALUE]][STATS].retried += 1
|
1276
|
+
if (!scope[SCOPE_NAME])
|
1277
|
+
scope[SCOPE_NAME] = scope[1][VALUE]
|
1278
|
+
stack.unshift(() => check(exp, env, scope))
|
947
1279
|
}
|
948
1280
|
}
|
949
1281
|
}
|
950
1282
|
}
|
951
1283
|
}
|
952
1284
|
}
|
953
|
-
}
|
954
|
-
|
955
|
-
|
956
|
-
|
1285
|
+
}
|
1286
|
+
})
|
1287
|
+
for (const r of rest) check(r, env, scope)
|
1288
|
+
break
|
957
1289
|
}
|
958
1290
|
}
|
959
1291
|
}
|