fez-lisp 1.5.40 → 1.5.42

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