fez-lisp 1.5.41 → 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/package.json +1 -1
- package/src/check.js +637 -651
- package/src/compiler.js +0 -2
- package/src/evaluator.js +0 -1
- package/src/parser.js +2 -8
package/src/check.js
CHANGED
@@ -487,275 +487,275 @@ export const typeCheck = (ast) => {
|
|
487
487
|
const stack = []
|
488
488
|
const check = (exp, env, scope) => {
|
489
489
|
const [first, ...rest] = isLeaf(exp) ? [exp] : exp
|
490
|
-
if (first
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
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)`
|
500
504
|
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
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)`
|
506
528
|
)
|
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
|
-
if (returns[TYPE] === ATOM) {
|
534
|
-
env[name][STATS][prop] = ATOM
|
535
|
-
} else {
|
536
|
-
switch (returns[VALUE]) {
|
537
|
-
case KEYWORDS.IF:
|
538
|
-
const re = rem.slice(2)
|
539
|
-
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
540
|
-
env[name][STATS][RETURNS] = ATOM
|
541
|
-
// if (
|
542
|
-
// re[0][VALUE] === FALSE ||
|
543
|
-
// re[0][VALUE] === TRUE ||
|
544
|
-
// re[1][VALUE] === FALSE ||
|
545
|
-
// re[1][VALUE] === TRUE
|
546
|
-
// ) {
|
547
|
-
// env[name][STATS][SUB_TYPE] = PREDICATE
|
548
|
-
// }
|
549
|
-
} else if (!isLeaf(re[0]) && env[re[0][0][VALUE]]) {
|
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]]) {
|
550
555
|
env[name][STATS][RETURNS] =
|
551
|
-
env[re[0][
|
556
|
+
env[re[0][VALUE]][STATS].type
|
552
557
|
env[name][STATS][SUB_TYPE] =
|
553
|
-
env[re[0][
|
558
|
+
env[re[0][VALUE]][STATS][SUB_TYPE]
|
554
559
|
} else {
|
555
|
-
|
556
|
-
|
557
|
-
env[re[0][VALUE]][STATS].type
|
558
|
-
env[name][STATS][SUB_TYPE] =
|
559
|
-
env[re[0][VALUE]][STATS][SUB_TYPE]
|
560
|
-
} else {
|
561
|
-
env[name][STATS][RETURNS] = UNKNOWN
|
562
|
-
// env[name][STATS][RETURNS] = APPLY
|
563
|
-
}
|
560
|
+
env[name][STATS][RETURNS] = UNKNOWN
|
561
|
+
// env[name][STATS][RETURNS] = APPLY
|
564
562
|
}
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
`${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)`
|
588
|
-
)
|
589
|
-
}
|
590
|
-
env[name][STATS].type = fn[STATS][RETURNS]
|
591
|
-
env[name][STATS][SUB_TYPE] =
|
592
|
-
fn[STATS][SUB_TYPE]
|
593
|
-
} else {
|
594
|
-
const body = rest.at(-1).at(-1).at(-1).at(-1)
|
595
|
-
const rem = hasBlock(body)
|
596
|
-
? body.at(-1)
|
597
|
-
: body
|
598
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
599
|
-
resolveRetunType(
|
600
|
-
returns,
|
601
|
-
rem,
|
602
|
-
TYPE_PROP,
|
603
|
-
isPredicate
|
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)`
|
604
585
|
)
|
605
586
|
}
|
587
|
+
env[name][STATS].type = fn[STATS][RETURNS]
|
588
|
+
env[name][STATS][SUB_TYPE] = fn[STATS][SUB_TYPE]
|
589
|
+
} else {
|
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
|
+
)
|
606
599
|
}
|
607
|
-
env[name][STATS][RETURNS] =
|
608
|
-
env[returns[VALUE]][STATS][RETURNS]
|
609
|
-
env[name][STATS][SUB_TYPE] =
|
610
|
-
env[returns[VALUE]][STATS][SUB_TYPE]
|
611
|
-
} else {
|
612
|
-
env[name][STATS][RETURNS] =
|
613
|
-
env[returns[VALUE]][STATS].type
|
614
|
-
env[name][STATS][SUB_TYPE] =
|
615
|
-
env[returns[VALUE]][SUB_TYPE]
|
616
600
|
}
|
601
|
+
env[name][STATS][RETURNS] =
|
602
|
+
env[returns[VALUE]][STATS][RETURNS]
|
603
|
+
env[name][STATS][SUB_TYPE] =
|
604
|
+
env[returns[VALUE]][STATS][SUB_TYPE]
|
617
605
|
} else {
|
618
|
-
env[name][STATS][RETURNS] =
|
619
|
-
|
606
|
+
env[name][STATS][RETURNS] =
|
607
|
+
env[returns[VALUE]][STATS].type
|
608
|
+
env[name][STATS][SUB_TYPE] =
|
609
|
+
env[returns[VALUE]][SUB_TYPE]
|
620
610
|
}
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
env[name][STATS][prop] !== UNKNOWN &&
|
627
|
-
env[name][STATS][SUB_TYPE] !== PREDICATE
|
628
|
-
) {
|
629
|
-
warningStack.add(
|
630
|
-
`${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)`
|
631
|
-
)
|
632
|
-
} else if (
|
633
|
-
!isPredicate &&
|
634
|
-
env[name][STATS][SUB_TYPE] === PREDICATE
|
635
|
-
) {
|
636
|
-
warningStack.add(
|
637
|
-
`${name} should end in (${PREDICATE_SUFFIX}) because it return (Predicate) (try adding ? at the end of the lambda name) (check #8)`
|
638
|
-
)
|
639
|
-
}
|
640
|
-
if (isPredicate) {
|
641
|
-
env[name][STATS][prop] = ATOM
|
642
|
-
env[name][STATS][SUB_TYPE] = PREDICATE
|
611
|
+
} else {
|
612
|
+
env[name][STATS][RETURNS] = UNKNOWN
|
613
|
+
// env[name][STATS][RETURNS] = APPLY
|
614
|
+
}
|
615
|
+
break
|
643
616
|
}
|
644
617
|
}
|
645
|
-
const checkReturnType = () => {
|
646
|
-
// if (name[name.length - 1] === PREDICATE_SUFFIX) {
|
647
|
-
// env[name][STATS][RETURNS] = ATOM
|
648
|
-
// env[name][STATS][SUB_TYPE] = PREDICATE
|
649
|
-
// } else {
|
650
|
-
const last = rest.at(-1).at(-1)
|
651
|
-
// const isApplyLambdaDoBlock = hasApplyLambdaBlock(
|
652
|
-
// rest.at(-1)
|
653
|
-
// )
|
654
|
-
const body = hasApplyLambdaBlock(last)
|
655
|
-
? last.at(-1).at(-1)
|
656
|
-
: last
|
657
|
-
const rem = hasBlock(body) ? body.at(-1) : body
|
658
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
659
|
-
const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
|
660
|
-
resolveRetunType(returns, rem, RETURNS, isPredicate)
|
661
|
-
// }
|
662
|
-
// if (
|
663
|
-
// env[name][STATS][RETURNS] === UNKNOWN &&
|
664
|
-
// env[name][STATS].retried < RETRY_COUNT
|
665
|
-
// ) {
|
666
|
-
// env[name][STATS].retried += 1
|
667
|
-
// console.log(name, env[name][STATS])
|
668
|
-
// checkReturnType()
|
669
|
-
// }
|
670
|
-
}
|
671
618
|
if (
|
672
|
-
|
673
|
-
|
619
|
+
isPredicate &&
|
620
|
+
env[name][STATS][prop] !== UNKNOWN &&
|
621
|
+
env[name][STATS][SUB_TYPE] !== PREDICATE
|
674
622
|
) {
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
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]: []
|
683
678
|
}
|
679
|
+
}
|
684
680
|
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
check(rest.at(-1), env, exp)
|
694
|
-
})
|
695
|
-
check(rest.at(-1), env, exp)
|
696
|
-
} else {
|
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()
|
697
689
|
check(rest.at(-1), env, exp)
|
698
|
-
}
|
690
|
+
})
|
691
|
+
check(rest.at(-1), env, exp)
|
699
692
|
} else {
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
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)`
|
706
705
|
)
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
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)`
|
713
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
|
718
|
+
if (
|
719
|
+
isPredicate &&
|
720
|
+
right[VALUE] !== TRUE &&
|
721
|
+
right[VALUE] !== FALSE
|
722
|
+
) {
|
714
723
|
warningStack.add(
|
715
|
-
`${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)`
|
716
729
|
)
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
if (
|
723
|
-
isPredicate &&
|
724
|
-
right[VALUE] !== TRUE &&
|
725
|
-
right[VALUE] !== FALSE
|
726
|
-
) {
|
727
|
-
warningStack.add(
|
728
|
-
`${name} ends in (${PREDICATE_SUFFIX}) but is assigned to ${
|
729
|
-
right[VALUE]
|
730
|
-
} which is not a (${toTypeNames(
|
731
|
-
PREDICATE
|
732
|
-
)}). Either remove (${PREDICATE_SUFFIX}) or change the value to ${TRUE} or ${FALSE} (check #20)`
|
733
|
-
)
|
734
|
-
}
|
735
|
-
env[name] = {
|
736
|
-
[STATS]: {
|
737
|
-
retried: 0,
|
738
|
-
type: ATOM
|
739
|
-
}
|
730
|
+
}
|
731
|
+
env[name] = {
|
732
|
+
[STATS]: {
|
733
|
+
retried: 0,
|
734
|
+
type: ATOM
|
740
735
|
}
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
736
|
+
}
|
737
|
+
if (isPredicate) env[name][STATS][SUB_TYPE] = PREDICATE
|
738
|
+
} else {
|
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)`
|
747
748
|
)
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
type: isL
|
755
|
-
? right[TYPE]
|
756
|
-
: env[right[VALUE]]?.[STATS]?.[RETURNS] ?? UNKNOWN
|
757
|
-
}
|
749
|
+
env[name] = {
|
750
|
+
[STATS]: {
|
751
|
+
retried: 0,
|
752
|
+
type: isL
|
753
|
+
? right[TYPE]
|
754
|
+
: env[right?.[VALUE]]?.[STATS]?.[RETURNS] ?? UNKNOWN
|
758
755
|
}
|
756
|
+
}
|
757
|
+
if (isPredicate) env[name][STATS][SUB_TYPE] = PREDICATE
|
758
|
+
if (right && right[VALUE]) {
|
759
759
|
if (right[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
760
760
|
if (isLeaf(rest.at(-1).at(-1))) {
|
761
761
|
const fnName = rest.at(-1).at(-1)[VALUE]
|
@@ -790,7 +790,6 @@ export const typeCheck = (ast) => {
|
|
790
790
|
)
|
791
791
|
}
|
792
792
|
}
|
793
|
-
if (isPredicate) env[name][STATS][SUB_TYPE] = PREDICATE
|
794
793
|
if (env[right[VALUE]]?.[STATS]?.[SUB_TYPE]) {
|
795
794
|
if (
|
796
795
|
env[right[VALUE]][STATS][SUB_TYPE] === PREDICATE &&
|
@@ -806,376 +805,351 @@ export const typeCheck = (ast) => {
|
|
806
805
|
env[right[VALUE]][STATS][SUB_TYPE]
|
807
806
|
}
|
808
807
|
}
|
809
|
-
|
810
|
-
// console.log(name, env[name])
|
811
808
|
}
|
812
|
-
|
813
|
-
|
809
|
+
|
810
|
+
// console.log(name, env[name])
|
814
811
|
}
|
812
|
+
// }
|
813
|
+
check(rest.at(-1), env, scope)
|
815
814
|
}
|
816
815
|
}
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
)
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
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 }
|
838
840
|
}
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
[STATS]
|
843
|
-
|
844
|
-
if (env[copy[SCOPE_NAME]]) {
|
845
|
-
env[copy[SCOPE_NAME]][STATS][ARGS][i] = copy[param[VALUE]]
|
846
|
-
if (getSuffix(param[VALUE]) === PREDICATE_SUFFIX) {
|
847
|
-
copy[param[VALUE]][STATS][RETURNS] = ATOM
|
848
|
-
copy[param[VALUE]][STATS][SUB_TYPE] = PREDICATE
|
849
|
-
}
|
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
|
850
846
|
}
|
851
847
|
}
|
852
|
-
check(rest.at(-1), copy, copy)
|
853
848
|
}
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
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
|
+
) {
|
859
866
|
errorStack.set(
|
860
867
|
key.str,
|
861
|
-
`
|
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)`
|
862
875
|
)
|
863
|
-
else {
|
864
|
-
|
865
|
-
env[first[VALUE]][STATS].type === APPLY &&
|
866
|
-
env[first[VALUE]][STATS][ARGS_COUNT] !== VARIADIC &&
|
867
|
-
env[first[VALUE]][STATS][ARGS_COUNT] !== rest.length
|
868
|
-
) {
|
869
|
-
errorStack.set(
|
870
|
-
key.str,
|
871
|
-
`Incorrect number of arguments for (${
|
872
|
-
first[VALUE]
|
873
|
-
}). Expected (= ${
|
874
|
-
env[first[VALUE]][STATS][ARGS_COUNT]
|
875
|
-
}) but got ${rest.length} (${stringifyArgs(
|
876
|
-
exp
|
877
|
-
)}) (check #15)`
|
878
|
-
)
|
879
|
-
} else {
|
880
|
-
const isSpecial = SPECIAL_FORMS_SET.has(first[VALUE])
|
876
|
+
} else {
|
877
|
+
const isSpecial = SPECIAL_FORMS_SET.has(first[VALUE])
|
881
878
|
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
}
|
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
|
895
891
|
}
|
892
|
+
}
|
896
893
|
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
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
|
903
900
|
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
}
|
928
|
-
} else if (rest[i][TYPE] === ATOM) {
|
929
|
-
if (
|
930
|
-
args[i][SUB] === PREDICATE &&
|
931
|
-
rest[i][VALUE] !== TRUE &&
|
932
|
-
rest[i][VALUE] !== FALSE
|
933
|
-
) {
|
934
|
-
errorStack.set(
|
935
|
-
key.str,
|
936
|
-
`Incorrect type of arguments for (${
|
937
|
-
first[VALUE]
|
938
|
-
}). Expected (${toTypeNames(
|
939
|
-
args[i][SUB]
|
940
|
-
)}) but got an (${toTypeNames(
|
941
|
-
rest[i][TYPE]
|
942
|
-
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
943
|
-
exp
|
944
|
-
)}) (check #22)`
|
945
|
-
)
|
946
|
-
}
|
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
|
908
|
+
if (
|
909
|
+
env[rest[i][VALUE]] &&
|
910
|
+
args[i][SUB] !==
|
911
|
+
env[rest[i][VALUE]][STATS][SUB_TYPE]
|
912
|
+
) {
|
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
|
+
)
|
947
924
|
}
|
948
|
-
} else {
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
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) {
|
959
992
|
errorStack.set(
|
960
993
|
key.str,
|
961
|
-
`Incorrect type of
|
994
|
+
`Incorrect type of argument ${i} for (${
|
962
995
|
first[VALUE]
|
963
996
|
}). Expected (${toTypeNames(
|
964
997
|
args[i][TYPE]
|
965
998
|
)}) but got an (${toTypeNames(
|
966
|
-
|
967
|
-
)})
|
999
|
+
ATOM
|
1000
|
+
)}) (${stringifyArgs(exp)}) (check #27)`
|
968
1001
|
)
|
969
1002
|
}
|
970
1003
|
if (
|
971
|
-
|
972
|
-
|
1004
|
+
args[i][SUB] &&
|
1005
|
+
args[i][SUB] === PREDICATE &&
|
1006
|
+
returns[VALUE] !== TRUE &&
|
1007
|
+
returns[VALUE] !== FALSE
|
973
1008
|
) {
|
974
1009
|
errorStack.set(
|
975
1010
|
key.str,
|
976
|
-
`Incorrect type of
|
1011
|
+
`Incorrect type of argument ${i} for (${
|
977
1012
|
first[VALUE]
|
978
1013
|
}). Expected (${toTypeNames(
|
979
1014
|
args[i][SUB]
|
980
1015
|
)}) but got an (${toTypeNames(
|
981
|
-
|
1016
|
+
ATOM
|
982
1017
|
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
983
1018
|
exp
|
984
1019
|
)}) (check #27)`
|
985
1020
|
)
|
986
1021
|
}
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
) {
|
1016
|
-
errorStack.set(
|
1017
|
-
key.str,
|
1018
|
-
`Incorrect type of argument ${i} for (${
|
1019
|
-
first[VALUE]
|
1020
|
-
}). Expected (${toTypeNames(
|
1021
|
-
args[i][SUB]
|
1022
|
-
)}) but got an (${toTypeNames(
|
1023
|
-
ATOM
|
1024
|
-
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
1025
|
-
exp
|
1026
|
-
)}) (check #27)`
|
1027
|
-
)
|
1028
|
-
}
|
1029
|
-
} else if (env[returns[VALUE]]) {
|
1030
|
-
if (
|
1031
|
-
args[i][TYPE] !==
|
1032
|
-
env[returns[VALUE]][STATS][RETURNS]
|
1033
|
-
) {
|
1034
|
-
errorStack.set(
|
1035
|
-
key.str,
|
1036
|
-
`Incorrect type of argument ${i} for (${
|
1037
|
-
first[VALUE]
|
1038
|
-
}). Expected (${toTypeNames(
|
1039
|
-
args[i][TYPE]
|
1040
|
-
)}) but got (${toTypeNames(
|
1041
|
-
env[returns[VALUE]][STATS][TYPE_PROP]
|
1042
|
-
)}) (${stringifyArgs(
|
1043
|
-
exp
|
1044
|
-
)}) (check #29)`
|
1045
|
-
)
|
1046
|
-
}
|
1047
|
-
if (
|
1048
|
-
args[i][SUB] &&
|
1049
|
-
args[i][SUB] !==
|
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]
|
1033
|
+
)}) but got (${toTypeNames(
|
1034
|
+
env[returns[VALUE]][STATS][TYPE_PROP]
|
1035
|
+
)}) (${stringifyArgs(exp)}) (check #29)`
|
1036
|
+
)
|
1037
|
+
}
|
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
1050
|
env[returns[VALUE]][STATS][SUB_TYPE]
|
1051
|
-
|
1052
|
-
|
1053
|
-
key.str,
|
1054
|
-
`Incorrect type of argument ${i} for (${
|
1055
|
-
first[VALUE]
|
1056
|
-
}). Expected (${toTypeNames(
|
1057
|
-
args[i][SUB]
|
1058
|
-
)}) but got (${toTypeNames(
|
1059
|
-
env[returns[VALUE]][STATS][SUB_TYPE]
|
1060
|
-
)}) (${stringifyArgs(exp)}) (check #28)`
|
1061
|
-
)
|
1062
|
-
}
|
1051
|
+
)}) (${stringifyArgs(exp)}) (check #28)`
|
1052
|
+
)
|
1063
1053
|
}
|
1064
|
-
|
1065
|
-
// // console.log({ returns })
|
1066
|
-
// resolveRetunType(
|
1067
|
-
// returns,
|
1068
|
-
// rem,
|
1069
|
-
// TYPE_PROP,
|
1070
|
-
// isPredicate
|
1071
|
-
// )
|
1072
1054
|
}
|
1073
1055
|
|
1074
|
-
// console.log(
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
`Incorrect type of arguments (${i}) for (${
|
1082
|
-
first[VALUE]
|
1083
|
-
}). Expected (${toTypeNames(
|
1084
|
-
args[i][SUB]
|
1085
|
-
)}) but got (${toTypeNames(
|
1086
|
-
env[current[VALUE]][STATS][SUB_TYPE] ??
|
1087
|
-
env[current[VALUE]][STATS][RETURNS]
|
1088
|
-
)}) (${stringifyArgs(exp)}) (check #21)`
|
1089
|
-
)
|
1056
|
+
// // console.log({ returns })
|
1057
|
+
// resolveRetunType(
|
1058
|
+
// returns,
|
1059
|
+
// rem,
|
1060
|
+
// TYPE_PROP,
|
1061
|
+
// isPredicate
|
1062
|
+
// )
|
1090
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
|
+
)
|
1091
1081
|
}
|
1092
1082
|
}
|
1093
1083
|
}
|
1084
|
+
}
|
1094
1085
|
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
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
|
1101
|
+
if (
|
1102
|
+
isKnown &&
|
1103
|
+
env[CAR][STATS][RETURNS] !== expectedArgs[i][TYPE]
|
1104
|
+
) {
|
1105
|
+
// console.log(env[CAR][STATS], expectedArgs[i][TYPE])
|
1106
|
+
errorStack.set(
|
1107
|
+
key.str,
|
1108
|
+
`Incorrect type of arguments for special form (${
|
1109
|
+
first[VALUE]
|
1110
|
+
}). Expected (${toTypeNames(
|
1113
1111
|
expectedArgs[i][TYPE]
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
expectedArgs[i][SUB] &&
|
1129
|
-
env[CAR][STATS][SUB_TYPE] !==
|
1112
|
+
)}) but got (${toTypeNames(
|
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(
|
1130
1126
|
expectedArgs[i][SUB]
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
}). Expected (${toTypeNames(
|
1137
|
-
expectedArgs[i][SUB]
|
1138
|
-
)}) but got (${toTypeNames(
|
1139
|
-
env[CAR][STATS][SUB_TYPE] ??
|
1140
|
-
env[CAR][STATS][RETURNS]
|
1141
|
-
)}) (${stringifyArgs(exp)}) (check #13)`
|
1142
|
-
)
|
1143
|
-
}
|
1127
|
+
)}) but got (${toTypeNames(
|
1128
|
+
env[CAR][STATS][SUB_TYPE] ??
|
1129
|
+
env[CAR][STATS][RETURNS]
|
1130
|
+
)}) (${stringifyArgs(exp)}) (check #13)`
|
1131
|
+
)
|
1144
1132
|
}
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
key.str,
|
1166
|
-
`Incorrect type of arguments for special form (${
|
1167
|
-
first[VALUE]
|
1168
|
-
}). Expected (${toTypeNames(
|
1169
|
-
expectedArgs[i][TYPE]
|
1170
|
-
)}) but got (${toTypeNames(
|
1171
|
-
rest[i][TYPE]
|
1172
|
-
)}) (${stringifyArgs(exp)}) (check #2)`
|
1173
|
-
)
|
1174
|
-
} else if (
|
1175
|
-
T !== UNKNOWN &&
|
1176
|
-
expectedArgs[i][TYPE] !== UNKNOWN &&
|
1177
|
-
expectedArgs[i][TYPE] !== T
|
1178
|
-
) {
|
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
|
+
)
|
1179
1153
|
errorStack.set(
|
1180
1154
|
key.str,
|
1181
1155
|
`Incorrect type of arguments for special form (${
|
@@ -1183,89 +1157,66 @@ export const typeCheck = (ast) => {
|
|
1183
1157
|
}). Expected (${toTypeNames(
|
1184
1158
|
expectedArgs[i][TYPE]
|
1185
1159
|
)}) but got (${toTypeNames(
|
1186
|
-
|
1187
|
-
)}) (${stringifyArgs(exp)}) (check #
|
1160
|
+
rest[i][TYPE]
|
1161
|
+
)}) (${stringifyArgs(exp)}) (check #2)`
|
1188
1162
|
)
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
case APPLY:
|
1195
|
-
case ATOM:
|
1163
|
+
} else if (
|
1164
|
+
T !== UNKNOWN &&
|
1165
|
+
expectedArgs[i][TYPE] !== UNKNOWN &&
|
1166
|
+
expectedArgs[i][TYPE] !== T
|
1167
|
+
) {
|
1196
1168
|
errorStack.set(
|
1197
1169
|
key.str,
|
1198
|
-
`Incorrect type of arguments for (${
|
1170
|
+
`Incorrect type of arguments for special form (${
|
1199
1171
|
first[VALUE]
|
1200
1172
|
}). Expected (${toTypeNames(
|
1201
1173
|
expectedArgs[i][TYPE]
|
1202
1174
|
)}) but got (${toTypeNames(
|
1203
|
-
|
1204
|
-
)}) (${stringifyArgs(exp)}) (check #
|
1175
|
+
T
|
1176
|
+
)}) (${stringifyArgs(exp)}) (check #3)`
|
1205
1177
|
)
|
1206
|
-
|
1207
|
-
|
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
|
1208
1196
|
}
|
1209
1197
|
}
|
1210
1198
|
}
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
errorStack.set(
|
1233
|
-
key.str,
|
1234
|
-
`Incorrect type of arguments ${i} for (${
|
1235
|
-
first[VALUE]
|
1236
|
-
}). Expected (${toTypeNames(
|
1237
|
-
args[i][STATS].type
|
1238
|
-
)}) but got (${toTypeNames(
|
1239
|
-
T
|
1240
|
-
)}) (${stringifyArgs(exp)})`
|
1241
|
-
)
|
1242
|
-
} else {
|
1243
|
-
// env[rest[i][VALUE]][STATS] THiss SHOULD BE
|
1244
|
-
const retry = env[rest[i][VALUE]]
|
1245
|
-
if (
|
1246
|
-
retry &&
|
1247
|
-
retry[STATS].retried < RETRY_COUNT &&
|
1248
|
-
args[i][STATS].type === UNKNOWN
|
1249
|
-
) {
|
1250
|
-
retry[STATS].retried += 1
|
1251
|
-
stack.unshift(() => check(exp, env, scope))
|
1252
|
-
}
|
1253
|
-
// console.log(
|
1254
|
-
// first[VALUE],
|
1255
|
-
// env[first[VALUE]][STATS],
|
1256
|
-
// rest[i][TYPE],
|
1257
|
-
// args[i][STATS].type
|
1258
|
-
// )
|
1259
|
-
}
|
1260
|
-
} else if (
|
1261
|
-
rest[i].length &&
|
1262
|
-
SPECIAL_FORMS_SET.has(rest[i][0][VALUE]) &&
|
1263
|
-
env[rest[i][0][VALUE]] &&
|
1264
|
-
env[rest[i][0][VALUE]][STATS][RETURNS] !==
|
1265
|
-
UNKNOWN &&
|
1266
|
-
args[i][STATS].type !== UNKNOWN &&
|
1267
|
-
env[rest[i][0][VALUE]][STATS][RETURNS] !==
|
1268
|
-
args[i][STATS].type
|
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)
|
1269
1220
|
) {
|
1270
1221
|
errorStack.set(
|
1271
1222
|
key.str,
|
@@ -1273,33 +1224,68 @@ export const typeCheck = (ast) => {
|
|
1273
1224
|
first[VALUE]
|
1274
1225
|
}). Expected (${toTypeNames(
|
1275
1226
|
args[i][STATS].type
|
1276
|
-
)}) but got (${toTypeNames(
|
1277
|
-
|
1278
|
-
)})
|
1227
|
+
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
1228
|
+
exp
|
1229
|
+
)})`
|
1279
1230
|
)
|
1280
1231
|
} else {
|
1232
|
+
// env[rest[i][VALUE]][STATS] THiss SHOULD BE
|
1233
|
+
const retry = env[rest[i][VALUE]]
|
1281
1234
|
if (
|
1282
|
-
|
1283
|
-
|
1284
|
-
args[i][STATS].type === UNKNOWN
|
1285
|
-
env[rest[i][0][VALUE]][STATS].retried <
|
1286
|
-
RETRY_COUNT
|
1235
|
+
retry &&
|
1236
|
+
retry[STATS].retried < RETRY_COUNT &&
|
1237
|
+
args[i][STATS].type === UNKNOWN
|
1287
1238
|
) {
|
1288
|
-
|
1289
|
-
if (!scope[SCOPE_NAME])
|
1290
|
-
scope[SCOPE_NAME] = scope[1][VALUE]
|
1239
|
+
retry[STATS].retried += 1
|
1291
1240
|
stack.unshift(() => check(exp, env, scope))
|
1292
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))
|
1293
1279
|
}
|
1294
1280
|
}
|
1295
1281
|
}
|
1296
1282
|
}
|
1297
1283
|
}
|
1298
1284
|
}
|
1299
|
-
}
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1285
|
+
}
|
1286
|
+
})
|
1287
|
+
for (const r of rest) check(r, env, scope)
|
1288
|
+
break
|
1303
1289
|
}
|
1304
1290
|
}
|
1305
1291
|
}
|