fez-lisp 1.5.40 → 1.5.41

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
@@ -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 { hasApplyLambdaBlock, hasBlock, stringifyArgs } from './utils.js'
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 SUB_RETURN_TYPE = 'sub_return_type'
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
- [SUB_RETURN_TYPE]: PREDICATE
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
- [SUB_RETURN_TYPE]: PREDICATE
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
- [SUB_RETURN_TYPE]: PREDICATE
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
- [SUB_RETURN_TYPE]: PREDICATE
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
- [SUB_RETURN_TYPE]: PREDICATE
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
- [SUB_RETURN_TYPE]: PREDICATE
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
- [SUB_RETURN_TYPE]: PREDICATE
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
- [SUB_RETURN_TYPE]: PREDICATE
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
- [SUB_RETURN_TYPE]: PREDICATE
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
- [SUB_RETURN_TYPE]: PREDICATE
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])
@@ -518,6 +524,150 @@ export const typeCheck = (ast) => {
518
524
  )
519
525
  } else {
520
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]]) {
550
+ env[name][STATS][RETURNS] =
551
+ env[re[0][0][VALUE]][STATS][RETURNS]
552
+ env[name][STATS][SUB_TYPE] =
553
+ env[re[0][0][VALUE]][STATS][SUB_TYPE]
554
+ } 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
+ }
564
+ }
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
604
+ )
605
+ }
606
+ }
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
+ }
617
+ } else {
618
+ env[name][STATS][RETURNS] = UNKNOWN
619
+ // env[name][STATS][RETURNS] = APPLY
620
+ }
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
643
+ }
644
+ }
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
+ }
521
671
  if (
522
672
  rest.at(-1)[0][TYPE] === APPLY &&
523
673
  rest.at(-1)[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
@@ -531,102 +681,7 @@ export const typeCheck = (ast) => {
531
681
  [ARGS]: []
532
682
  }
533
683
  }
534
- const checkReturnType = () => {
535
- // if (name[name.length - 1] === PREDICATE_SUFFIX) {
536
- // env[name][STATS][RETURNS] = ATOM
537
- // env[name][STATS][SUB_RETURN_TYPE] = PREDICATE
538
- // } else {
539
- const isPredicate =
540
- name[name.length - 1] === PREDICATE_SUFFIX
541
- const last = rest.at(-1).at(-1)
542
- const body = hasApplyLambdaBlock(last)
543
- ? last.at(-1).at(-1)
544
- : last
545
- const rem = hasBlock(body) ? body.at(-1) : body
546
- const returns = isLeaf(rem) ? rem : rem[0]
547
- if (returns[TYPE] === ATOM) {
548
- env[name][STATS][RETURNS] = ATOM
549
- } else {
550
- switch (returns[VALUE]) {
551
- case KEYWORDS.IF:
552
- const re = rem.slice(2)
553
- if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
554
- env[name][STATS][RETURNS] = ATOM
555
- // if (
556
- // re[0][VALUE] === FALSE ||
557
- // re[0][VALUE] === TRUE ||
558
- // re[1][VALUE] === FALSE ||
559
- // re[1][VALUE] === TRUE
560
- // ) {
561
- // env[name][STATS][SUB_RETURN_TYPE] = PREDICATE
562
- // }
563
- } else if (!isLeaf(re[0]) && env[re[0][0][VALUE]]) {
564
- env[name][STATS][RETURNS] =
565
- env[re[0][0][VALUE]][STATS][RETURNS]
566
- env[name][STATS][SUB_RETURN_TYPE] =
567
- env[re[0][0][VALUE]][STATS][SUB_RETURN_TYPE]
568
- } else {
569
- if (env[re[0][VALUE]]) {
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]
587
- } else {
588
- env[name][STATS][RETURNS] =
589
- env[returns[VALUE]][STATS].type
590
- env[name][STATS][SUB_RETURN_TYPE] =
591
- env[returns[VALUE]][SUB_RETURN_TYPE]
592
- }
593
- } else {
594
- env[name][STATS][RETURNS] = UNKNOWN
595
- // env[name][STATS][RETURNS] = APPLY
596
- }
597
- break
598
- }
599
- }
600
- if (
601
- isPredicate &&
602
- env[name][STATS][RETURNS] !== UNKNOWN &&
603
- env[name][STATS][SUB_RETURN_TYPE] !== PREDICATE
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
611
- ) {
612
- warningStack.add(
613
- `${name} should end in (${PREDICATE_SUFFIX}) because it return (Predicate) (try adding ? at the end of the lambda name) (check #8)`
614
- )
615
- }
616
- if (isPredicate) {
617
- env[name][STATS][RETURNS] = ATOM
618
- env[name][STATS][SUB_RETURN_TYPE] = PREDICATE
619
- }
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
- }
684
+
630
685
  checkReturnType()
631
686
  if (
632
687
  env[name][STATS][RETURNS] === UNKNOWN &&
@@ -642,21 +697,119 @@ export const typeCheck = (ast) => {
642
697
  check(rest.at(-1), env, exp)
643
698
  }
644
699
  } else {
645
- if (!(name in env)) {
646
- if (rest[1][TYPE] === WORD)
647
- env[name] = env[rest[1][VALUE]]
648
- 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
706
+ )
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
713
+ )
714
+ 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)`
716
+ )
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
+ }
649
735
  env[name] = {
650
736
  [STATS]: {
651
737
  retried: 0,
652
- type: isLeaf(rest.at(-1))
653
- ? rest.at(-1)[TYPE]
654
- : env[rest.at(-1)[0]?.[VALUE]]?.[STATS]?.[
655
- RETURNS
656
- ] ?? UNKNOWN
738
+ type: ATOM
739
+ }
740
+ }
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
747
+ )
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
+ }
758
+ }
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 (isPredicate) env[name][STATS][SUB_TYPE] = PREDICATE
794
+ if (env[right[VALUE]]?.[STATS]?.[SUB_TYPE]) {
795
+ if (
796
+ env[right[VALUE]][STATS][SUB_TYPE] === PREDICATE &&
797
+ !isPredicate
798
+ ) {
799
+ warningStack.add(
800
+ `${name} is assigned to the result of a (${toTypeNames(
801
+ PREDICATE
802
+ )}) so ${name} must end in (${PREDICATE_SUFFIX}) (check #23)`
803
+ )
657
804
  }
805
+ env[name][STATS][SUB_TYPE] =
806
+ env[right[VALUE]][STATS][SUB_TYPE]
658
807
  }
808
+ }
809
+
810
+ // console.log(name, env[name])
659
811
  }
812
+ // }
660
813
  check(rest.at(-1), env, scope)
661
814
  }
662
815
  }
@@ -690,11 +843,9 @@ export const typeCheck = (ast) => {
690
843
  }
691
844
  if (env[copy[SCOPE_NAME]]) {
692
845
  env[copy[SCOPE_NAME]][STATS][ARGS][i] = copy[param[VALUE]]
693
- if (
694
- param[VALUE][param[VALUE].length - 1] === PREDICATE_SUFFIX
695
- ) {
846
+ if (getSuffix(param[VALUE]) === PREDICATE_SUFFIX) {
696
847
  copy[param[VALUE]][STATS][RETURNS] = ATOM
697
- copy[param[VALUE]][STATS][SUB_RETURN_TYPE] = PREDICATE
848
+ copy[param[VALUE]][STATS][SUB_TYPE] = PREDICATE
698
849
  }
699
850
  }
700
851
  }
@@ -742,15 +893,210 @@ export const typeCheck = (ast) => {
742
893
  env[first[VALUE]][STATS][ARGS_COUNT] = rest.length
743
894
  }
744
895
  }
896
+
745
897
  // also type of arg
746
898
  const args = env[first[VALUE]][STATS][ARGS]
747
899
  if (args) {
748
900
  for (let i = 0; i < args.length; ++i) {
749
901
  // type check
902
+ // todo finish this
903
+
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
+ }
947
+ }
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
+ ) {
959
+ errorStack.set(
960
+ key.str,
961
+ `Incorrect type of arguments for (${
962
+ first[VALUE]
963
+ }). Expected (${toTypeNames(
964
+ args[i][TYPE]
965
+ )}) but got an (${toTypeNames(
966
+ fn[STATS][RETURNS]
967
+ )}) (${stringifyArgs(exp)}) (check #26)`
968
+ )
969
+ }
970
+ if (
971
+ fn &&
972
+ fn[STATS][SUB_TYPE] !== args[i][SUB]
973
+ ) {
974
+ errorStack.set(
975
+ key.str,
976
+ `Incorrect type of arguments for (${
977
+ first[VALUE]
978
+ }). Expected (${toTypeNames(
979
+ args[i][SUB]
980
+ )}) but got an (${toTypeNames(
981
+ fn[STATS][SUB_TYPE]
982
+ )}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
983
+ exp
984
+ )}) (check #27)`
985
+ )
986
+ }
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] !==
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
+ }
1063
+ }
1064
+
1065
+ // // console.log({ returns })
1066
+ // resolveRetunType(
1067
+ // returns,
1068
+ // rem,
1069
+ // TYPE_PROP,
1070
+ // isPredicate
1071
+ // )
1072
+ }
1073
+
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
+ )
1090
+ }
1091
+ }
1092
+ }
1093
+ }
1094
+
750
1095
  if (
751
1096
  first[TYPE] === APPLY &&
752
- isSpecial &&
753
- env[first[VALUE]][STATS][ARGS_COUNT] !== VARIADIC
1097
+ isSpecial
1098
+ // &&
1099
+ // env[first[VALUE]][STATS][ARGS_COUNT] !== VARIADIC
754
1100
  ) {
755
1101
  const expectedArgs = env[first[VALUE]][STATS][ARGS]
756
1102
  for (let i = 0; i < rest.length; ++i) {
@@ -780,7 +1126,7 @@ export const typeCheck = (ast) => {
780
1126
  } else if (
781
1127
  isKnown &&
782
1128
  expectedArgs[i][SUB] &&
783
- env[CAR][STATS][SUB_RETURN_TYPE] !==
1129
+ env[CAR][STATS][SUB_TYPE] !==
784
1130
  expectedArgs[i][SUB]
785
1131
  ) {
786
1132
  errorStack.set(
@@ -790,7 +1136,7 @@ export const typeCheck = (ast) => {
790
1136
  }). Expected (${toTypeNames(
791
1137
  expectedArgs[i][SUB]
792
1138
  )}) but got (${toTypeNames(
793
- env[CAR][STATS][SUB_RETURN_TYPE] ??
1139
+ env[CAR][STATS][SUB_TYPE] ??
794
1140
  env[CAR][STATS][RETURNS]
795
1141
  )}) (${stringifyArgs(exp)}) (check #13)`
796
1142
  )