fez-lisp 1.5.41 → 1.5.43

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/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 != undefined) {
491
- switch (first[TYPE]) {
492
- case WORD:
493
- {
494
- stack.push(() => {
495
- const key = withScope(first[VALUE], scope)
496
- if (env[first[VALUE]] === undefined) {
497
- errorStack.set(
498
- key.str,
499
- `Trying to access undefined variable ${first[VALUE]} (check #11)`
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
- // `Trying to access undefined variable ${
502
- // first[VALUE]
503
- // }\n${formatCallstack(
504
- // key.chain.filter((x) => isNaN(Number(x[0])))
505
- // )}\n(check #11)`
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
- break
511
- case ATOM:
512
- break
513
- case APPLY: {
514
- switch (first[VALUE]) {
515
- case KEYWORDS.DEFINE_VARIABLE:
516
- {
517
- if (rest.length !== 2) {
518
- throw new TypeError(
519
- `Incorrect number of arguments for (${
520
- first[VALUE]
521
- }). Expected (= 2) but got ${rest.length} (${stringifyArgs(
522
- exp
523
- )}) (check #10)`
524
- )
525
- } else {
526
- const name = rest[0][VALUE]
527
- const resolveRetunType = (
528
- returns,
529
- rem,
530
- prop,
531
- isPredicate
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][0][VALUE]][STATS][RETURNS]
556
+ env[re[0][VALUE]][STATS].type
552
557
  env[name][STATS][SUB_TYPE] =
553
- env[re[0][0][VALUE]][STATS][SUB_TYPE]
558
+ env[re[0][VALUE]][STATS][SUB_TYPE]
554
559
  } else {
555
- if (env[re[0][VALUE]]) {
556
- env[name][STATS][RETURNS] =
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
- break
566
- default:
567
- if (env[returns[VALUE]]) {
568
- if (env[returns[VALUE]][STATS].type === APPLY) {
569
- if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
570
- if (isLeaf(rest.at(-1).at(-1).at(-1))) {
571
- const fnName = rest.at(-1).at(-1).at(-1)[
572
- VALUE
573
- ]
574
- const fn = env[fnName]
575
- if (
576
- !isPredicate &&
577
- fn[STATS][SUB_TYPE] === PREDICATE
578
- ) {
579
- warningStack.add(
580
- `${name} is assigned to ${fnName} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #24)`
581
- )
582
- } else if (
583
- isPredicate &&
584
- fn[STATS][SUB_TYPE] !== PREDICATE
585
- ) {
586
- warningStack.add(
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] = UNKNOWN
619
- // env[name][STATS][RETURNS] = APPLY
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
- break
622
- }
623
- }
624
- if (
625
- isPredicate &&
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
- rest.at(-1)[0][TYPE] === APPLY &&
673
- rest.at(-1)[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
619
+ isPredicate &&
620
+ env[name][STATS][prop] !== UNKNOWN &&
621
+ env[name][STATS][SUB_TYPE] !== PREDICATE
674
622
  ) {
675
- const n = rest.at(-1).length
676
- env[name] = {
677
- [STATS]: {
678
- type: APPLY,
679
- retried: 0,
680
- [ARGS_COUNT]: n - 2,
681
- [ARGS]: []
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
- checkReturnType()
686
- if (
687
- env[name][STATS][RETURNS] === UNKNOWN &&
688
- env[name][STATS].retried < DEFINITON_RETRY_COUNT
689
- ) {
690
- env[name][STATS].retried += 1
691
- stack.unshift(() => {
692
- checkReturnType()
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
- // if (!(name in env)) {
701
- if (rest[1][TYPE] === WORD) {
702
- env[name] = env[rest[1][VALUE]]
703
- if (
704
- getSuffix(rest[1][VALUE]) === PREDICATE_SUFFIX &&
705
- getSuffix(name) !== PREDICATE_SUFFIX
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
- warningStack.add(
708
- `${name} is assigned to ${rest[1][VALUE]} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #17)`
709
- )
710
- else if (
711
- getSuffix(rest[1][VALUE]) === MUTATION_SUFFIX &&
712
- getSuffix(name) !== MUTATION_SUFFIX
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} is assigned to ${rest[1][VALUE]} which ends in (${MUTATION_SUFFIX}) so ${name} must also end in (${MUTATION_SUFFIX}) (check #18)`
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
- } else {
718
- const isL = isLeaf(rest.at(-1))
719
- const right = isL ? rest.at(-1) : rest.at(-1)[0]
720
- if (isL && right[TYPE] === ATOM) {
721
- const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
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
- if (isPredicate) env[name][STATS][SUB_TYPE] = PREDICATE
742
- } else {
743
- const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
744
- if (
745
- getSuffix(right[VALUE]) === PREDICATE_SUFFIX &&
746
- !isPredicate
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
- warningStack.add(
749
- `${name} is assigned to ${right[VALUE]} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #19)`
750
- )
751
- env[name] = {
752
- [STATS]: {
753
- retried: 0,
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
- check(rest.at(-1), env, scope)
809
+
810
+ // console.log(name, env[name])
814
811
  }
812
+ // }
813
+ check(rest.at(-1), env, scope)
815
814
  }
816
815
  }
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
835
- .now()
836
- .toString()
837
- .replace('.', 0)
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
- for (let i = 0; i < params.length; ++i) {
840
- const param = params[i]
841
- copy[param[VALUE]] = {
842
- [STATS]: { type: UNKNOWN, retried: 0 }
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
- break
855
- default:
856
- stack.push(() => {
857
- const key = withScope(first[VALUE], scope)
858
- if (env[first[VALUE]] === undefined)
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
- `Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
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
- if (
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
- if (first[TYPE] === APPLY && !isSpecial) {
883
- if (env[first[VALUE]][STATS].type === ATOM) {
884
- errorStack.set(
885
- key.str,
886
- `(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
887
- exp
888
- )}) (check #12)`
889
- )
890
- } else if (!env[first[VALUE]][STATS][ARGS_COUNT]) {
891
- env[first[VALUE]][STATS][RETURNS] = UNKNOWN
892
- env[first[VALUE]][STATS].type = APPLY
893
- env[first[VALUE]][STATS][ARGS_COUNT] = rest.length
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
- // also type of arg
898
- const args = env[first[VALUE]][STATS][ARGS]
899
- if (args) {
900
- for (let i = 0; i < args.length; ++i) {
901
- // type check
902
- // todo finish this
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
- if (args[i][SUB] != undefined) {
905
- // first[TYPE] === APPLY &&
906
- // env[first[VALUE]][STATS][SUB_TYPE] === PREDICATE
907
- // args[i][SUB] = env[rest[i][VALUE]][SUB_TYPE]
908
- if (isLeaf(rest[i])) {
909
- if (rest[i][TYPE] === WORD) {
910
- // TODO finish this
911
- if (
912
- env[rest[i][VALUE]] &&
913
- args[i][SUB] !==
914
- env[rest[i][VALUE]][STATS][SUB_TYPE]
915
- ) {
916
- errorStack.set(
917
- key.str,
918
- `Incorrect type of arguments for (${
919
- first[VALUE]
920
- }). Expected (${toTypeNames(
921
- args[i][SUB]
922
- )}) but got (${toTypeNames(
923
- env[rest[i][VALUE]][STATS][SUB_TYPE] ??
924
- env[rest[i][VALUE]][STATS].type
925
- )}) (${stringifyArgs(exp)}) (check #16)`
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
- const current = rest[i][0]
950
- if (current[TYPE] === APPLY) {
951
- if (current[VALUE] == KEYWORDS.CALL_FUNCTION) {
952
- if (isLeaf(rest[i].at(-1))) {
953
- const fnName = rest[i].at(-1)[VALUE]
954
- const fn = env[fnName]
955
- if (
956
- fn &&
957
- fn[STATS][RETURNS] !== args[i][TYPE]
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 arguments for (${
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
- fn[STATS][RETURNS]
967
- )}) (${stringifyArgs(exp)}) (check #26)`
999
+ ATOM
1000
+ )}) (${stringifyArgs(exp)}) (check #27)`
968
1001
  )
969
1002
  }
970
1003
  if (
971
- fn &&
972
- fn[STATS][SUB_TYPE] !== args[i][SUB]
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 arguments for (${
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
- fn[STATS][SUB_TYPE]
1016
+ ATOM
982
1017
  )}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
983
1018
  exp
984
1019
  )}) (check #27)`
985
1020
  )
986
1021
  }
987
- // env[name][STATS].type = fn[STATS][RETURNS]
988
- // env[name][STATS][SUB_TYPE] = fn[STATS][SUB_TYPE]
989
- } else {
990
- const body = rest[i].at(-1).at(-1)
991
- const rem = hasBlock(body)
992
- ? body.at(-1)
993
- : body
994
- const returns = isLeaf(rem) ? rem : rem[0]
995
- if (returns[TYPE] === ATOM) {
996
- if (args[i][TYPE] !== ATOM) {
997
- errorStack.set(
998
- key.str,
999
- `Incorrect type of argument ${i} for (${
1000
- first[VALUE]
1001
- }). Expected (${toTypeNames(
1002
- args[i][TYPE]
1003
- )}) but got an (${toTypeNames(
1004
- ATOM
1005
- )}) (${stringifyArgs(
1006
- exp
1007
- )}) (check #27)`
1008
- )
1009
- }
1010
- if (
1011
- args[i][SUB] &&
1012
- args[i][SUB] === PREDICATE &&
1013
- returns[VALUE] !== TRUE &&
1014
- returns[VALUE] !== FALSE
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
- errorStack.set(
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(args[i], env[current[VALUE]][STATS])
1075
- } else if (
1076
- env[current[VALUE]][STATS][SUB_TYPE] !==
1077
- args[i][SUB]
1078
- ) {
1079
- errorStack.set(
1080
- key.str,
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
- if (
1096
- first[TYPE] === APPLY &&
1097
- isSpecial
1098
- // &&
1099
- // env[first[VALUE]][STATS][ARGS_COUNT] !== VARIADIC
1100
- ) {
1101
- const expectedArgs = env[first[VALUE]][STATS][ARGS]
1102
- for (let i = 0; i < rest.length; ++i) {
1103
- if (expectedArgs[i][TYPE] === UNKNOWN) continue
1104
- if (!isLeaf(rest[i])) {
1105
- const CAR = rest[i][0][VALUE]
1106
- const isKnown =
1107
- env[CAR] &&
1108
- env[CAR][STATS][RETURNS] != undefined &&
1109
- env[CAR][STATS][RETURNS] !== UNKNOWN
1110
- if (
1111
- isKnown &&
1112
- env[CAR][STATS][RETURNS] !==
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
- // console.log(env[CAR][STATS], expectedArgs[i][TYPE])
1116
- errorStack.set(
1117
- key.str,
1118
- `Incorrect type of arguments for special form (${
1119
- first[VALUE]
1120
- }). Expected (${toTypeNames(
1121
- expectedArgs[i][TYPE]
1122
- )}) but got (${toTypeNames(
1123
- env[CAR][STATS][RETURNS]
1124
- )}) (${stringifyArgs(exp)}) (check #1)`
1125
- )
1126
- } else if (
1127
- isKnown &&
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
- errorStack.set(
1133
- key.str,
1134
- `Incorrect type of arguments for special form (${
1135
- first[VALUE]
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
- if (
1146
- env[rest[i][VALUE]] &&
1147
- expectedArgs[i][TYPE] !== rest[i][TYPE]
1148
- ) {
1149
- switch (rest[i][TYPE]) {
1150
- case UNKNOWN:
1151
- env[first[VALUE]][STATS].type =
1152
- expectedArgs[i][TYPE]
1153
- break
1154
- case WORD:
1155
- const T = env[rest[i][VALUE]][STATS].type
1156
- if (Array.isArray(T)) {
1157
- const TT = T[VALUE]
1158
- if (
1159
- env[TT][STATS][RETURNS] &&
1160
- env[TT][STATS][RETURNS] !== UNKNOWN &&
1161
- expectedArgs[i][TYPE] !==
1162
- env[TT][STATS][RETURNS]
1163
- )
1164
- errorStack.set(
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
- T
1187
- )}) (${stringifyArgs(exp)}) (check #3)`
1160
+ rest[i][TYPE]
1161
+ )}) (${stringifyArgs(exp)}) (check #2)`
1188
1162
  )
1189
- } else {
1190
- env[rest[i][VALUE]][STATS].type =
1191
- expectedArgs[i][TYPE]
1192
- }
1193
- break
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
- rest[i][TYPE]
1204
- )}) (${stringifyArgs(exp)}) (check #5)`
1175
+ T
1176
+ )}) (${stringifyArgs(exp)}) (check #3)`
1205
1177
  )
1206
- break
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
- // type checking
1212
- else if (
1213
- rest[i] &&
1214
- args[i][STATS] &&
1215
- rest[i][TYPE] !== args[i][STATS].type
1216
- ) {
1217
- if (isLeaf(rest[i])) {
1218
- const T =
1219
- rest[i][TYPE] === WORD && env[rest[i][VALUE]]
1220
- ? env[rest[i][VALUE]][STATS].type
1221
- : rest[i][TYPE]
1222
- if (
1223
- (args[i][STATS].type !== UNKNOWN &&
1224
- T === ATOM &&
1225
- args[i][STATS].type !== ATOM) ||
1226
- (env[rest[i][VALUE]] &&
1227
- env[rest[i][VALUE]][STATS].type !== UNKNOWN &&
1228
- args[i][STATS].type !== UNKNOWN &&
1229
- env[rest[i][VALUE]][STATS].type !==
1230
- args[i][STATS].type)
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
- env[rest[i][0][VALUE]][STATS][RETURNS]
1278
- )}) (${stringifyArgs(exp)}) (check #4)`
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
- rest[i].length &&
1283
- env[rest[i][0][VALUE]] &&
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
- env[rest[i][0][VALUE]][STATS].retried += 1
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
- for (const r of rest) check(r, env, scope)
1301
- break
1302
- }
1285
+ }
1286
+ })
1287
+ for (const r of rest) check(r, env, scope)
1288
+ break
1303
1289
  }
1304
1290
  }
1305
1291
  }