fez-lisp 1.5.91 → 1.5.92

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
@@ -32,12 +32,14 @@ import {
32
32
  MAX_ARGUMENT_RETRY,
33
33
  ORDER,
34
34
  VARIABLE_ORDER_INDEX,
35
- COLLECTION
35
+ COLLECTION,
36
+ ANY
36
37
  } from './types.js'
37
38
  import {
38
39
  getSuffix,
39
40
  hasApplyLambdaBlock,
40
41
  hasBlock,
42
+ logExp,
41
43
  stringifyArgs
42
44
  } from './utils.js'
43
45
 
@@ -63,6 +65,84 @@ const deepLambdaReturn = (rest, condition) => {
63
65
  const rem = hasBlock(body) ? body.at(-1) : body
64
66
  return condition(rem) ? rem : deepLambdaReturn(rem, condition)
65
67
  }
68
+ export const isTypeAbstraction = (stats) => {
69
+ return stats[TYPE_PROP] === APPLY
70
+ }
71
+ export const setTypeRef = (stats, value) => {
72
+ // if (!isAnyReturn(stats) && !isAnyReturn(value))
73
+ if (isUnknownType(stats)) stats[TYPE_PROP] = value[TYPE_PROP]
74
+ }
75
+ export const setReturnRef = (stats, value) => {
76
+ // if (!isAnyReturn(stats) && !isAnyReturn(value))
77
+ if (isUnknownReturn(stats)) stats[RETURNS] = value[RETURNS]
78
+ }
79
+ export const setReturnToTypeRef = (stats, value) => {
80
+ // if (!isAnyReturn(stats) && !isAnyReturn(value))
81
+ if (isUnknownReturn(stats)) stats[RETURNS] = value[TYPE_PROP]
82
+ }
83
+ export const setPropRef = (stats, prop, value) => {
84
+ // if (stats[prop][0] !== ANY && value[prop][0] !== ANY)
85
+ if (stats[prop][0] === UNKNOWN) stats[prop] = value[prop]
86
+ }
87
+ export const setReturn = (stats, value) => {
88
+ // if (!isAnyReturn(stats) && !isAnyReturn(value))
89
+ if (isUnknownReturn(stats) && !isUnknownReturn(value))
90
+ stats[RETURNS][0] = value[RETURNS][0]
91
+ }
92
+ export const setType = (stats, value) => {
93
+ // if (!isAnyType(stats) && !isAnyType(value))
94
+
95
+ if (isUnknownType(stats) && !isUnknownType(value))
96
+ stats[TYPE_PROP][0] = value[TYPE_PROP][0]
97
+ }
98
+ export const setTypeToReturn = (stats, value) => {
99
+ // if (!isAnyType(stats) && !isAnyReturn(value))
100
+ if (isUnknownType(stats) && !isUnknownReturn(value))
101
+ stats[TYPE_PROP][0] = value[RETURNS][0]
102
+ }
103
+ export const setReturnToType = (stats, value) => {
104
+ // if (!isAnyType(stats) && !isAnyReturn(value))
105
+ if (isUnknownReturn(stats) && !isUnknownType(value))
106
+ stats[RETURNS][0] = value[TYPE_PROP][0]
107
+ }
108
+ export const setProp = (stats, prop, value) => {
109
+ // if (stats[prop][0] !== ANY && value[prop][0] !== ANY)
110
+ if (stats[prop][0] === UNKNOWN && value[prop][0] !== UNKNOWN)
111
+ stats[prop][0] = value[prop][0]
112
+ }
113
+ export const isAnyReturn = (stats) => {
114
+ return stats && stats[RETURNS][0] === ANY
115
+ }
116
+ export const isAnyType = (stats) => {
117
+ return stats && stats[TYPE_PROP][0] === ANY
118
+ }
119
+ export const isUnknownType = (stats) => {
120
+ return stats && stats[TYPE_PROP][0] === UNKNOWN
121
+ }
122
+ export const isUnknownReturn = (stats) => {
123
+ return stats[RETURNS][0] === UNKNOWN
124
+ }
125
+ export const getType = (stats) => {
126
+ return stats && stats[TYPE_PROP][0]
127
+ }
128
+ export const getReturn = (stats) => {
129
+ return stats && stats[RETURNS][0]
130
+ }
131
+ export const isAtomType = (stats) => {
132
+ return isAnyType(stats) || stats[TYPE_PROP][0] === ATOM
133
+ }
134
+ export const isAtomReturn = (stats) => {
135
+ return isAnyType(stats) || stats[RETURNS][0] === ATOM
136
+ }
137
+ export const compareTypes = (a, b) => {
138
+ return isAnyType(a) || isAnyType(b) || a[TYPE_PROP][0] === b[TYPE_PROP][0]
139
+ }
140
+ export const compareReturns = (a, b) => {
141
+ return isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
142
+ }
143
+ export const compareTypeWithReturn = (a, b) => {
144
+ return isAnyType(a) || isAnyReturn(b) || a[TYPE_PROP][0] === b[RETURNS][0]
145
+ }
66
146
  const checkPredicateName = (exp, rest, warningStack) => {
67
147
  if (getSuffix(rest[0][VALUE]) === PREDICATE_SUFFIX) {
68
148
  const last = rest.at(-1)
@@ -147,7 +227,7 @@ export const formatType = (name, env) => {
147
227
  const stats = env[name][STATS]
148
228
  const isAnonymous = typeof name === 'number'
149
229
  return stats
150
- ? stats[TYPE_PROP][0] === APPLY
230
+ ? getType(stats) === APPLY
151
231
  ? `${isAnonymous ? '' : `(let ${name} `}(lambda ${
152
232
  stats[ARG_COUNT] === VARIADIC
153
233
  ? '... ' + STATIC_TYPES.UNKNOWN
@@ -155,17 +235,17 @@ export const formatType = (name, env) => {
155
235
  .map(
156
236
  (x, i) =>
157
237
  `${
158
- x[STATS][TYPE_PROP][0] === APPLY
238
+ getType(x[STATS]) === APPLY
159
239
  ? `${formatType(i, stats[ARGUMENTS])}`
160
- : `${toTypeNames(x[STATS][TYPE_PROP][0])}`
240
+ : `${toTypeNames(getType(x[STATS]))}`
161
241
  }`
162
242
  )
163
243
  .join(' ')
164
244
  // TODO format returned functions when type support is added
165
- } (${KEYWORDS.BLOCK} ${toTypeNames(stats[RETURNS][0])})${
245
+ } (${KEYWORDS.BLOCK} ${toTypeNames(getReturn(stats))})${
166
246
  isAnonymous ? '' : ')'
167
247
  })`
168
- : `(let ${name} ${toTypeNames(stats[TYPE_PROP][0])})`
248
+ : `(let ${name} ${toTypeNames(getType(stats))})`
169
249
  : name
170
250
  }
171
251
  const formatTypes = (env) => {
@@ -192,9 +272,9 @@ const withScope = (name, scope) => {
192
272
  .map((x) => (Number.isInteger(+x) ? '::' : x))
193
273
  .join(' ')} ${name}`
194
274
  }
195
- export const typeCheck = (ast) => {
275
+ export const typeCheck = (ast, error = true) => {
196
276
  const root = structuredClone(SPECIAL_FORM_TYPES)
197
- root[ORDER] = 0
277
+ // root[ORDER] = 0
198
278
  const errorStack = new Set()
199
279
  const warningStack = new Set()
200
280
  // TODO delete this
@@ -273,7 +353,7 @@ export const typeCheck = (ast) => {
273
353
  } else if (
274
354
  !isLeaf(re[0]) &&
275
355
  env[re[0][0][VALUE]] &&
276
- env[re[0][0][VALUE]][STATS][RETURNS][0] !== UNKNOWN
356
+ !isUnknownReturn(env[re[0][0][VALUE]][STATS])
277
357
  ) {
278
358
  env[name][STATS][prop] =
279
359
  env[re[0][0][VALUE]][STATS][RETURNS]
@@ -293,10 +373,13 @@ export const typeCheck = (ast) => {
293
373
  } else if (
294
374
  !isLeaf(re[1]) &&
295
375
  env[re[1][0][VALUE]] &&
296
- env[re[1][0][VALUE]][STATS][RETURNS][0] !== UNKNOWN
376
+ !isUnknownReturn(env[re[1][0][VALUE]][STATS])
297
377
  ) {
298
- env[name][STATS][prop] =
299
- env[re[1][0][VALUE]][STATS][prop]
378
+ setProp(
379
+ env[name][STATS],
380
+ prop,
381
+ env[re[1][0][VALUE]][STATS]
382
+ )
300
383
  env[name][STATS][prop] =
301
384
  env[re[1][0][VALUE]][STATS][RETURNS]
302
385
  if (re[1][0][TYPE] === APPLY) {
@@ -320,11 +403,24 @@ export const typeCheck = (ast) => {
320
403
  env[re[0][VALUE]][STATS][RETURNS]
321
404
  } else if (env[re[1][VALUE]]) {
322
405
  // ASSIGMENT
323
- env[name][STATS][prop] =
324
- env[re[1][VALUE]][STATS][prop]
325
- env[name][STATS][RETURNS] =
326
- env[re[1][VALUE]][STATS][RETURNS]
327
- } else env[name][STATS][prop] = [UNKNOWN]
406
+ setProp(
407
+ env[name][STATS],
408
+ prop,
409
+ env[re[1][VALUE]][STATS]
410
+ )
411
+ // env[name][STATS][prop] =
412
+ // env[re[1][VALUE]][STATS][prop]
413
+ setReturnRef(
414
+ env[name][STATS],
415
+ env[re[1][VALUE]][STATS]
416
+ )
417
+ }
418
+ // else {
419
+ // // setProp(env[name][STATS], prop, {
420
+ // // [prop]: [UNKNOWN]
421
+ // // })
422
+ // // env[name][STATS][prop] = [UNKNOWN]
423
+ // }
328
424
  }
329
425
  break
330
426
  default:
@@ -335,29 +431,38 @@ export const typeCheck = (ast) => {
335
431
  returns,
336
432
  warningStack
337
433
  )
338
- if (!env[returns[VALUE]])
339
- env[name][STATS][RETURNS] = [UNKNOWN]
434
+ if (!env[returns[VALUE]]) {
435
+ return false
436
+ // env[name][STATS][RETURNS] = [ANY]
437
+ }
340
438
  // env[name][STATS][RETURNS] = APPLY
341
439
  else if (
342
- env[returns[VALUE]][STATS][TYPE_PROP][0] === APPLY
440
+ getType(env[returns[VALUE]][STATS]) === APPLY
343
441
  ) {
344
442
  // ALWAYS APPLY
345
443
  // rest.at(-1)[0][TYPE] === APPLY
346
444
  // Here is upon application to store the result in the variable
347
- if (env[name][STATS][TYPE_PROP][0] === UNKNOWN)
445
+ if (isUnknownType(env[name][STATS]))
348
446
  stack.unshift(() => {
349
- env[name][STATS][TYPE_PROP][0] =
350
- env[returns[VALUE]][STATS][RETURNS][0]
447
+ setTypeToReturn(
448
+ env[name][STATS],
449
+ env[returns[VALUE]][STATS]
450
+ )
451
+ // env[name][STATS][TYPE_PROP][0] =
452
+ // env[returns[VALUE]][STATS][RETURNS][0]
351
453
  // this seems to be able to be deleted
352
454
  // env[name][STATS][TYPE_PROP][1] =
353
455
  // env[returns[VALUE]][STATS][RETURNS][1]
354
456
  })
355
- env[name][STATS][RETURNS] =
356
- env[returns[VALUE]][STATS][RETURNS]
457
+ setReturnRef(
458
+ env[name][STATS],
459
+ env[returns[VALUE]][STATS]
460
+ )
357
461
  }
358
462
  break
359
463
  }
360
464
  }
465
+ return true
361
466
  }
362
467
  const checkReturnType = () => {
363
468
  const last = rest.at(-1).at(-1)
@@ -366,7 +471,7 @@ export const typeCheck = (ast) => {
366
471
  : last
367
472
  const rem = hasBlock(body) ? body.at(-1) : body
368
473
  const returns = isLeaf(rem) ? rem : rem[0]
369
- resolveRetunType(returns, rem, RETURNS)
474
+ return resolveRetunType(returns, rem, RETURNS)
370
475
  }
371
476
  const rightHand = rest.at(-1)
372
477
  if (
@@ -382,17 +487,16 @@ export const typeCheck = (ast) => {
382
487
  [SIGNATURE]: name,
383
488
  retried: 0,
384
489
  counter: 0,
385
- [VARIABLE_ORDER_INDEX]: env[ORDER],
490
+ // [VARIABLE_ORDER_INDEX]: env[ORDER],
386
491
  [ARG_COUNT]: n - 2,
387
492
  [ARGUMENTS]: fillUknownArgs(n - 2),
388
493
  [RETURNS]: [UNKNOWN]
389
494
  }
390
495
  }
391
-
392
- checkReturnType()
393
496
  if (
394
- env[name][STATS][RETURNS][0] === UNKNOWN &&
395
- env[name][STATS].retried < MAX_RETRY_DEFINITION
497
+ !checkReturnType() ||
498
+ (isUnknownReturn(env[name][STATS]) &&
499
+ env[name][STATS].retried < MAX_RETRY_DEFINITION)
396
500
  ) {
397
501
  env[name][STATS].retried += 1
398
502
  stack.unshift(() => {
@@ -424,7 +528,7 @@ export const typeCheck = (ast) => {
424
528
  [SIGNATURE]: name,
425
529
  retried: 0,
426
530
  counter: 0,
427
- [VARIABLE_ORDER_INDEX]: env[ORDER],
531
+ // [VARIABLE_ORDER_INDEX]: env[ORDER],
428
532
  [TYPE_PROP]: [ATOM],
429
533
  [RETURNS]: [ATOM]
430
534
  }
@@ -437,7 +541,7 @@ export const typeCheck = (ast) => {
437
541
  retried: 0,
438
542
  counter: 0,
439
543
  [SIGNATURE]: name,
440
- [VARIABLE_ORDER_INDEX]: env[ORDER],
544
+ // [VARIABLE_ORDER_INDEX]: env[ORDER],
441
545
  [TYPE_PROP]: [
442
546
  isL
443
547
  ? right[TYPE]
@@ -466,7 +570,7 @@ export const typeCheck = (ast) => {
466
570
  }
467
571
  Types.set(withScope(name, env), () => formatType(name, env))
468
572
  }
469
- root[ORDER]++
573
+ // root[ORDER]++
470
574
  }
471
575
  break
472
576
  case KEYWORDS.ANONYMOUS_FUNCTION:
@@ -521,13 +625,17 @@ export const typeCheck = (ast) => {
521
625
  // this here is a variable WORD
522
626
  // so return type of that function is that varible type
523
627
  if (copy[returns[VALUE]])
524
- ref[STATS][RETURNS] =
525
- copy[returns[VALUE]][STATS][TYPE_PROP]
628
+ setReturnToTypeRef(
629
+ ref[STATS],
630
+ copy[returns[VALUE]][STATS]
631
+ )
526
632
  else
527
633
  stack.push(() => {
528
634
  if (copy[returns[VALUE]])
529
- ref[STATS][RETURNS] =
530
- copy[returns[VALUE]][STATS][TYPE_PROP]
635
+ setReturnToTypeRef(
636
+ ref[STATS],
637
+ copy[returns[VALUE]][STATS]
638
+ )
531
639
  })
532
640
  } else {
533
641
  const ret = returns[0]
@@ -551,37 +659,35 @@ export const typeCheck = (ast) => {
551
659
  // WHY not consiter making return types for everything
552
660
  if (
553
661
  concequent &&
554
- concequent[STATS][TYPE_PROP][0] !== UNKNOWN
662
+ getType(concequent[STATS]) !== UNKNOWN
555
663
  ) {
556
- if (concequent[STATS][TYPE_PROP][0] === APPLY)
557
- ref[STATS][RETURNS] = concequent[STATS][RETURNS]
664
+ if (getType(concequent[STATS]) === APPLY)
665
+ setReturnRef(ref[STATS], concequent[STATS])
558
666
  else
559
667
  ref[STATS][RETURNS] = concequent[STATS][TYPE_PROP]
560
668
  } else if (
561
669
  alternative &&
562
- alternative[STATS][TYPE_PROP][0] !== UNKNOWN
670
+ isUnknownType(alternative[STATS])
563
671
  ) {
564
- if (alternative[STATS][TYPE_PROP][0] === APPLY)
565
- ref[STATS][RETURNS] = alternative[STATS][RETURNS]
672
+ if (getType(alternative[STATS]) === APPLY)
673
+ setReturnRef(ref[STATS], alternative[STATS])
566
674
  else
567
- ref[STATS][RETURNS] =
568
- alternative[STATS][TYPE_PROP]
675
+ setReturnToTypeRef(ref[STATS], alternative[STATS])
569
676
  } else if (concequent) {
570
- if (concequent[STATS][TYPE_PROP][0] === APPLY)
571
- ref[STATS][RETURNS] = concequent[STATS][RETURNS]
677
+ if (getType(concequent[STATS]) === APPLY)
678
+ setReturnRef(ref[STATS], concequent[STATS])
572
679
  else
573
- ref[STATS][RETURNS] = concequent[STATS][TYPE_PROP]
680
+ setReturnToTypeRef(ref[STATS], concequent[STATS])
574
681
  }
575
682
  }
576
683
  break
577
684
  default:
578
685
  if (copy[ret[VALUE]])
579
- ref[STATS][RETURNS] = copy[ret[VALUE]][STATS][RETURNS]
686
+ setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
580
687
  else
581
688
  stack.push(() => {
582
689
  if (copy[ret[VALUE]])
583
- ref[STATS][RETURNS] =
584
- copy[ret[VALUE]][STATS][RETURNS]
690
+ setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
585
691
  })
586
692
 
587
693
  break
@@ -594,565 +700,585 @@ export const typeCheck = (ast) => {
594
700
  }
595
701
  break
596
702
  default:
597
- stack.push(() => {
598
- if (env[first[VALUE]] === undefined)
599
- errorStack.add(
600
- `Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
601
- )
602
- else if (
603
- env[first[VALUE]][STATS][TYPE_PROP][0] === APPLY &&
604
- env[first[VALUE]][STATS][ARG_COUNT] !== VARIADIC &&
605
- env[first[VALUE]][STATS][ARG_COUNT] !== rest.length
606
- ) {
607
- errorStack.add(
608
- `Incorrect number of arguments for (${
609
- first[VALUE]
610
- }). Expected (= ${
611
- env[first[VALUE]][STATS][ARG_COUNT]
612
- }) but got ${rest.length} (${stringifyArgs(exp)}) (check #15)`
613
- )
614
- } else {
615
- if (first[TYPE] === APPLY && !isSpecial) {
616
- if (env[first[VALUE]][STATS][TYPE_PROP][0] === ATOM) {
617
- errorStack.add(
618
- `(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
619
- exp
620
- )}) (check #12)`
621
- )
622
- } else if (!env[first[VALUE]][STATS][ARG_COUNT]) {
623
- // TODO recursively take return type of applicaion
624
- // if (env[first[VALUE]][STATS][RETURNS][0] === APPLY) {
625
- // env[first[VALUE]][STATS][RETURNS] = [UNKNOWN]
626
- // }
627
- // FN ASSIGMENT
703
+ if (!STATIC_TYPES_SET.has(first[VALUE]))
704
+ stack.push(() => {
705
+ if (env[first[VALUE]] === undefined)
706
+ errorStack.add(
707
+ `Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
708
+ )
709
+ else if (
710
+ env[first[VALUE]][STATS][TYPE_PROP][0] === APPLY &&
711
+ env[first[VALUE]][STATS][ARG_COUNT] !== VARIADIC &&
712
+ env[first[VALUE]][STATS][ARG_COUNT] !== rest.length
713
+ ) {
714
+ errorStack.add(
715
+ `Incorrect number of arguments for (${
716
+ first[VALUE]
717
+ }). Expected (= ${
718
+ env[first[VALUE]][STATS][ARG_COUNT]
719
+ }) but got ${rest.length} (${stringifyArgs(
720
+ exp
721
+ )}) (check #15)`
722
+ )
723
+ } else {
724
+ if (first[TYPE] === APPLY && !isSpecial) {
725
+ if (getType(env[first[VALUE]][STATS]) === ATOM) {
726
+ errorStack.add(
727
+ `(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
728
+ exp
729
+ )}) (check #12)`
730
+ )
731
+ } else if (!env[first[VALUE]][STATS][ARG_COUNT]) {
732
+ // TODO recursively take return type of applicaion
733
+ // if (env[first[VALUE]][STATS][RETURNS][0] === APPLY) {
734
+ // env[first[VALUE]][STATS][RETURNS] = [UNKNOWN]
735
+ // }
736
+ // FN ASSIGMENT
628
737
 
629
- // ASSIGMENT of paramaters of lambda that are a lambda
630
- // minus one to remove the body
631
- env[first[VALUE]][STATS][TYPE_PROP] = [APPLY]
632
- env[first[VALUE]][STATS][ARG_COUNT] = rest.length
633
- env[first[VALUE]][STATS][ARGUMENTS] = fillUknownArgs(
634
- rest.length
635
- )
636
- for (let i = 0; i < rest.length; ++i) {
637
- const arg = env[first[VALUE]][STATS][ARGUMENTS]
638
- arg[i] = {
639
- [STATS]: {
640
- retried: 0,
641
- [SIGNATURE]: PLACEHOLDER,
642
- [TYPE_PROP]: [UNKNOWN],
643
- [RETURNS]: [UNKNOWN],
644
- [ARGUMENTS]: [],
645
- [ARG_COUNT]: 0
738
+ // ASSIGMENT of paramaters of lambda that are a lambda
739
+ // minus one to remove the body
740
+ env[first[VALUE]][STATS][TYPE_PROP] = [APPLY]
741
+ env[first[VALUE]][STATS][ARG_COUNT] = rest.length
742
+ env[first[VALUE]][STATS][ARGUMENTS] = fillUknownArgs(
743
+ rest.length
744
+ )
745
+ for (let i = 0; i < rest.length; ++i) {
746
+ const arg = env[first[VALUE]][STATS][ARGUMENTS]
747
+ arg[i] = {
748
+ [STATS]: {
749
+ retried: 0,
750
+ [SIGNATURE]: PLACEHOLDER,
751
+ [TYPE_PROP]: [UNKNOWN],
752
+ [RETURNS]: [UNKNOWN],
753
+ [ARGUMENTS]: [],
754
+ [ARG_COUNT]: 0
755
+ }
756
+ }
757
+ const ARG = isLeaf(rest[i]) ? rest[i] : rest[i][0]
758
+ if (!env[ARG[VALUE]]) continue
759
+ // console.log(stringifyArgs(exp), ARG)
760
+ switch (ARG[TYPE]) {
761
+ // THERE ARE NO ATOM ARGUMENTS
762
+ // case ATOM:
763
+ // break
764
+ case APPLY:
765
+ // passing arg asA APPLICATION
766
+ if (isUnknownType(arg[i][STATS]))
767
+ arg[i][STATS][TYPE_PROP] =
768
+ env[ARG[VALUE]][STATS][RETURNS]
769
+ break
770
+ case WORD:
771
+ // if param is a word we assosiate them by referanc
772
+ if (isUnknownType(arg[i][STATS]))
773
+ arg[i][STATS] = env[ARG[VALUE]][STATS]
774
+ break
646
775
  }
647
- }
648
- const ARG = isLeaf(rest[i]) ? rest[i] : rest[i][0]
649
- if (!env[ARG[VALUE]]) continue
650
- // console.log(stringifyArgs(exp), ARG)
651
- switch (ARG[TYPE]) {
652
- // THERE ARE NO ATOM ARGUMENTS
653
- // case ATOM:
654
- // break
655
- case APPLY:
656
- // passing arg asA APPLICATION
657
- if (arg[i][STATS][TYPE_PROP][0] === UNKNOWN)
658
- arg[i][STATS][TYPE_PROP] =
659
- env[ARG[VALUE]][STATS][RETURNS]
660
- break
661
- case WORD:
662
- // if param is a word we assosiate them by referanc
663
- if (arg[i][STATS][TYPE_PROP][0] === UNKNOWN)
664
- arg[i][STATS] = env[ARG[VALUE]][STATS]
665
- break
666
776
  }
667
777
  }
668
778
  }
669
- }
670
- // also type of arg
671
- const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
672
- for (let i = 0; i < args.length; ++i) {
673
- const isRestILeaf = isLeaf(rest[i])
674
- // type check
675
- // TODO get rof pred type
676
- // const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
677
- const MAIN_TYPE = args[i][STATS][TYPE_PROP][0]
678
-
679
- if (first[TYPE] === APPLY && isSpecial) {
680
- if (
681
- MAIN_TYPE === ATOM &&
682
- PREDICATES_INPUT_SET.has(first[VALUE])
683
- ) {
779
+ // also type of arg
780
+ const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
781
+ for (let i = 0; i < args.length; ++i) {
782
+ const isRestILeaf = isLeaf(rest[i])
783
+ // type check
784
+ // TODO get rof pred type
785
+ // const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
786
+ const MAIN_TYPE = getType(args[i][STATS])
787
+ if (MAIN_TYPE === ANY) continue
788
+ if (first[TYPE] === APPLY && isSpecial) {
684
789
  if (
685
- !isRestILeaf &&
686
- rest[i][0][TYPE] === APPLY &&
687
- rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
790
+ MAIN_TYPE === ATOM &&
791
+ PREDICATES_INPUT_SET.has(first[VALUE])
688
792
  ) {
689
- if (isLeaf(rest[i].at(-1))) {
690
- const fnName = rest[i].at(-1)[VALUE]
691
- const fn = env[fnName]
692
- if (fn && fn[STATS][RETURNS][0] !== ATOM) {
693
- errorStack.add(
694
- `Incorrect type of argument (${i}) for (${
695
- first[VALUE]
696
- }). Expected (${toTypeNames(
697
- ATOM
698
- )}) but got an (${toTypeNames(
699
- fn[STATS][RETURNS][0]
700
- )}) (${stringifyArgs(exp)}) (check #26)`
701
- )
702
- }
703
- } else {
704
- const body = rest[i].at(-1).at(-1)
705
- const rem = hasBlock(body) ? body.at(-1) : body
706
- const returns = isLeaf(rem) ? rem : rem[0]
707
- if (returns[TYPE] === ATOM) {
708
- if (MAIN_TYPE !== ATOM) {
793
+ if (
794
+ !isRestILeaf &&
795
+ rest[i][0][TYPE] === APPLY &&
796
+ rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
797
+ ) {
798
+ if (isLeaf(rest[i].at(-1))) {
799
+ const fnName = rest[i].at(-1)[VALUE]
800
+ const fn = env[fnName]
801
+ if (fn && getReturn(fn[STATS]) !== ATOM) {
709
802
  errorStack.add(
710
- `Incorrect type of argument ${i} for (${
803
+ `Incorrect type of argument (${i}) for (${
711
804
  first[VALUE]
712
805
  }). Expected (${toTypeNames(
713
- MAIN_TYPE
714
- )}) but got an (${toTypeNames(
715
806
  ATOM
716
- )}) (${stringifyArgs(exp)}) (check #27)`
807
+ )}) but got an (${toTypeNames(
808
+ getReturn(fn[STATS])
809
+ )}) (${stringifyArgs(exp)}) (check #26)`
717
810
  )
718
811
  }
719
- } else if (
720
- env[returns[VALUE]] &&
721
- env[returns[VALUE]][STATS][RETURNS][0] !== ATOM
722
- ) {
723
- errorStack.add(
724
- `Incorrect type of argument ${i} for (${
725
- first[VALUE]
726
- }). Expected (${toTypeNames(
727
- ATOM
728
- )}) but got (${toTypeNames(
729
- env[returns[VALUE]][STATS][TYPE_PROP]
730
- )}) (${stringifyArgs(exp)}) (check #29)`
731
- )
732
- }
733
- }
734
- }
735
- }
736
- const isCast = STATIC_TYPES_SET.has(first[VALUE])
737
- const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
738
- const EXPECTED_TYPE = expectedArgs[i][STATS][TYPE_PROP][0]
739
- // IF UKNOWN andnot csted -we have nothing much to do
740
- if (EXPECTED_TYPE === UNKNOWN && !isCast) continue
741
- if (!isRestILeaf) {
742
- const CAR = rest[i][0][VALUE]
743
- const isKnown =
744
- env[CAR] && env[CAR][STATS][RETURNS][0] !== UNKNOWN
745
- if (isKnown && !isCast) {
746
- if (env[CAR][STATS][RETURNS][0] !== EXPECTED_TYPE) {
747
- errorStack.add(
748
- `Incorrect type of argument (${i}) for special form (${
749
- first[VALUE]
750
- }). Expected (${toTypeNames(
751
- EXPECTED_TYPE
752
- )}) but got (${toTypeNames(
753
- env[CAR][STATS][RETURNS][0]
754
- )}) (${stringifyArgs(exp)}) (check #1)`
755
- )
756
- }
757
- // never reached because there is only 1 subtype at the moment
758
- // else if (
759
- // PRED_TYPE &&
760
- // env[CAR][STATS][RETURNS][1] !== PRED_TYPE
761
- // ) {
762
- // }
763
- } else if (!isKnown && !isCast && env[CAR]) {
764
- if (
765
- env[CAR][STATS][TYPE_PROP][0] === APPLY &&
766
- env[CAR][STATS][RETURNS][0] !== UNKNOWN
767
- ) {
768
- switch (first[VALUE]) {
769
- case KEYWORDS.IF:
770
- break
771
- case KEYWORDS.CALL_FUNCTION:
772
- break
773
- default:
774
- // console.log(stringifyArgs(exp))
775
- // TODO fix this assigment
776
- // It turns out it's not possible to determine return type of function here
777
- // what if it's a global function used elsewhere where the return type mwould be different/
778
- // env[CAR][STATS][RETURNS][0] =
779
- // root[first[VALUE]][STATS][RETURNS][0]
780
- break
781
- }
782
- }
783
-
784
- // TODO also handle casting
785
- }
786
- } else {
787
- switch (rest[i][TYPE]) {
788
- case WORD:
789
- {
790
- const CAR = rest[i][VALUE]
791
- const isKnown =
792
- env[CAR] &&
793
- env[CAR][STATS][TYPE_PROP][0] !== UNKNOWN
794
- if (isKnown && !isCast) {
795
- if (
796
- EXPECTED_TYPE !== env[CAR][STATS][TYPE_PROP][0]
797
- ) {
812
+ } else {
813
+ const body = rest[i].at(-1).at(-1)
814
+ const rem = hasBlock(body) ? body.at(-1) : body
815
+ const returns = isLeaf(rem) ? rem : rem[0]
816
+ if (returns[TYPE] === ATOM) {
817
+ if (MAIN_TYPE !== ATOM) {
798
818
  errorStack.add(
799
- `Incorrect type of argument (${i}) for special form (${
819
+ `Incorrect type of argument ${i} for (${
800
820
  first[VALUE]
801
821
  }). Expected (${toTypeNames(
802
- EXPECTED_TYPE
803
- )}) but got (${toTypeNames(
804
- env[CAR][STATS][TYPE_PROP][0]
805
- )}) (${stringifyArgs(exp)}) (check #3)`
822
+ MAIN_TYPE
823
+ )}) but got an (${toTypeNames(
824
+ ATOM
825
+ )}) (${stringifyArgs(exp)}) (check #27)`
806
826
  )
807
827
  }
808
- } else if (env[CAR]) {
809
- if (isCast) {
810
- // CAST assigment
811
- env[rest[i][VALUE]][STATS][TYPE_PROP][0] =
812
- root[first[VALUE]][STATS][RETURNS][0]
813
-
814
- // root[first[VALUE]][STATS][RETURNS] =
815
- // root[first[VALUE]][STATS][RETURNS]
816
- } else {
817
- // VALUE assigment
818
- env[CAR][STATS][TYPE_PROP][0] = EXPECTED_TYPE
819
- }
828
+ } else if (
829
+ env[returns[VALUE]] &&
830
+ !isUnknownReturn(env[returns[VALUE]][STATS]) &&
831
+ getReturn(env[returns[VALUE]][STATS]) !== ATOM
832
+ ) {
833
+ errorStack.add(
834
+ `Incorrect type of argument ${i} for (${
835
+ first[VALUE]
836
+ }). Expected (${toTypeNames(
837
+ ATOM
838
+ )}) but got (${toTypeNames(
839
+ getReturn(env[returns[VALUE]][STATS])
840
+ )}) (${stringifyArgs(exp)}) (check #29)`
841
+ )
820
842
  }
821
843
  }
822
- break
823
- case ATOM: {
824
- if (rest[i][TYPE] !== EXPECTED_TYPE) {
844
+ }
845
+ }
846
+ const isCast = STATIC_TYPES_SET.has(first[VALUE])
847
+ const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
848
+ // IF UKNOWN andnot csted -we have nothing much to do
849
+ if (isUnknownType(expectedArgs[i][STATS]) && !isCast)
850
+ continue
851
+ if (!isRestILeaf) {
852
+ const CAR = rest[i][0][VALUE]
853
+ if (!env[CAR]) continue
854
+ const isKnown = !isUnknownReturn(env[CAR][STATS])
855
+ if (isKnown && !isCast) {
856
+ if (
857
+ !compareTypeWithReturn(
858
+ expectedArgs[i][STATS],
859
+ env[CAR][STATS]
860
+ )
861
+ ) {
825
862
  errorStack.add(
826
863
  `Incorrect type of argument (${i}) for special form (${
827
864
  first[VALUE]
828
865
  }). Expected (${toTypeNames(
829
- EXPECTED_TYPE
866
+ getType(expectedArgs[i][STATS])
830
867
  )}) but got (${toTypeNames(
831
- rest[i][TYPE]
832
- )}) (${stringifyArgs(exp)}) (check #2)`
868
+ getReturn(env[CAR][STATS])
869
+ )}) (${stringifyArgs(exp)}) (check #1)`
833
870
  )
834
871
  }
835
- break
872
+ // never reached because there is only 1 subtype at the moment
873
+ // else if (
874
+ // PRED_TYPE &&
875
+ // env[CAR][STATS][RETURNS][1] !== PRED_TYPE
876
+ // ) {
877
+ // }
878
+ } else if (!isKnown && !isCast) {
879
+ if (env[CAR] && getType(env[CAR][STATS]) === APPLY) {
880
+ switch (first[VALUE]) {
881
+ case KEYWORDS.IF:
882
+ break
883
+ case KEYWORDS.CALL_FUNCTION:
884
+ break
885
+ default:
886
+ // console.log(stringifyArgs(exp))
887
+ // TODO fix this assigment
888
+ // It turns out it's not possible to determine return type of function here
889
+ // what if it's a global function used elsewhere where the return type mwould be different
890
+ // THIS willgive lambda return types but refactor is needed still
891
+ setReturn(
892
+ env[CAR][STATS],
893
+ expectedArgs[i][STATS]
894
+ )
895
+ break
896
+ }
897
+ }
898
+
899
+ // TODO also handle casting
900
+ }
901
+ } else {
902
+ switch (rest[i][TYPE]) {
903
+ case WORD:
904
+ {
905
+ const CAR = rest[i][VALUE]
906
+ if (!env[CAR]) continue
907
+ const isKnown = !isUnknownType(env[CAR][STATS])
908
+ if (isKnown && !isCast) {
909
+ if (
910
+ !compareTypes(
911
+ expectedArgs[i][STATS],
912
+ env[CAR][STATS]
913
+ )
914
+ ) {
915
+ errorStack.add(
916
+ `Incorrect type of argument (${i}) for special form (${
917
+ first[VALUE]
918
+ }). Expected (${toTypeNames(
919
+ getType(expectedArgs[i][STATS])
920
+ )}) but got (${toTypeNames(
921
+ getType(env[CAR][STATS])
922
+ )}) (${stringifyArgs(exp)}) (check #3)`
923
+ )
924
+ }
925
+ } else if (env[CAR]) {
926
+ if (isCast) {
927
+ // CAST assigment
928
+ setTypeToReturn(
929
+ env[rest[i][VALUE]][STATS],
930
+ root[first[VALUE]][STATS]
931
+ )
932
+ // root[first[VALUE]][STATS][RETURNS] =
933
+ // root[first[VALUE]][STATS][RETURNS]
934
+ } else {
935
+ // VALUE assigment
936
+ setType(
937
+ env[CAR][STATS],
938
+ expectedArgs[i][STATS]
939
+ )
940
+ // env[CAR][STATS][TYPE_PROP][0] =
941
+ // expectedArgs[i][STATS][TYPE_PROP][0]
942
+ }
943
+ }
944
+ }
945
+ break
946
+ case ATOM: {
947
+ if (
948
+ rest[i][TYPE] !==
949
+ expectedArgs[i][STATS][TYPE_PROP][0]
950
+ ) {
951
+ errorStack.add(
952
+ `Incorrect type of argument (${i}) for special form (${
953
+ first[VALUE]
954
+ }). Expected (${toTypeNames(
955
+ expectedArgs[i][STATS][TYPE_PROP][0]
956
+ )}) but got (${toTypeNames(
957
+ rest[i][TYPE]
958
+ )}) (${stringifyArgs(exp)}) (check #2)`
959
+ )
960
+ }
961
+ break
962
+ }
836
963
  }
837
964
  }
838
965
  }
839
- }
840
- // type checking
841
- else if (isRestILeaf) {
842
- const T =
843
- rest[i][TYPE] === WORD && env[rest[i][VALUE]]
844
- ? env[rest[i][VALUE]][STATS][TYPE_PROP][0]
845
- : rest[i][TYPE]
846
- if (
847
- T === ATOM &&
848
- args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
849
- args[i][STATS][TYPE_PROP][0] !== ATOM
850
- ) {
851
- errorStack.add(
852
- `Incorrect type of arguments ${i} for (${
853
- first[VALUE]
854
- }). Expected (${toTypeNames(
855
- args[i][STATS][TYPE_PROP][0]
856
- )}) but got (${toTypeNames(T)}) (${stringifyArgs(
857
- exp
858
- )}) (check #10)`
859
- )
860
- } else if (
861
- T === APPLY &&
862
- args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
863
- env[rest[i][VALUE]][STATS][TYPE_PROP][0] !== UNKNOWN &&
864
- env[rest[i][VALUE]][STATS][ARG_COUNT] !== VARIADIC
865
- ) {
866
- // Handles words that are Lambdas
966
+ // type checking
967
+ else if (isRestILeaf) {
968
+ const T =
969
+ rest[i][TYPE] === WORD
970
+ ? env[rest[i][VALUE]]
971
+ ? getType(env[rest[i][VALUE]][STATS])
972
+ : UNKNOWN
973
+ : rest[i][TYPE]
867
974
  if (
868
- env[rest[i][VALUE]][STATS][ARG_COUNT] !==
869
- args[i][STATS][ARG_COUNT]
975
+ T === ATOM &&
976
+ !isUnknownType(args[i][STATS]) &&
977
+ getType(args[i][STATS]) !== ATOM
870
978
  ) {
871
979
  errorStack.add(
872
- `Incorrect number of arguments for (${
873
- args[i][STATS][SIGNATURE]
874
- }) the (lambda) argument of (${
980
+ `Incorrect type of arguments ${i} for (${
875
981
  first[VALUE]
876
- }) at position (${i}). Expected (= ${
877
- args[i][STATS][ARG_COUNT]
878
- }) but got ${
879
- env[rest[i][VALUE]][STATS][ARG_COUNT]
880
- } (${stringifyArgs(exp)}) (check #778)`
982
+ }). Expected (${toTypeNames(
983
+ getType(args[i][STATS])
984
+ )}) but got (${toTypeNames(T)}) (${stringifyArgs(
985
+ exp
986
+ )}) (check #10)`
881
987
  )
882
- } else {
883
- // DEFINED LAMBDAS TYPE CHECKING
884
- // TODO delete this maybe
885
- // It will not be possilbe to know return type
886
- // const match1 = () => {
887
- // const actual = env[rest[i][VALUE]]
888
- // const expected = args[i]
889
- // if (
890
- // expected[STATS][RETURNS][0] !== UNKNOWN &&
891
- // actual[STATS][RETURNS][0] !== UNKNOWN &&
892
- // expected[STATS][RETURNS][0] !==
893
- // actual[STATS][RETURNS][0]
894
- // ) {
895
- // errorStack.add(
896
- // `Incorrect return type for (${
897
- // expected[STATS][SIGNATURE]
898
- // }) the (lambda) argument of (${
899
- // first[VALUE]
900
- // }) at position (${i}). Expected (${toTypeNames(
901
- // expected[STATS][RETURNS][0]
902
- // )}) but got (${toTypeNames(
903
- // actual[STATS][RETURNS][0]
904
- // )}) (${stringifyArgs(exp)}) (check #782)`
905
- // )
906
- // } else if (
907
- // actual[STATS].retried < MAX_RETRY_DEFINITION
908
- // ) {
909
- // actual[STATS].retried += 1
910
- // stack.unshift(() => match1())
911
- // }
912
- // }
913
- // match1()
914
- for (
915
- let j = 0;
916
- j < args[i][STATS][ARGUMENTS].length;
917
- ++j
988
+ } else if (
989
+ T === APPLY &&
990
+ !isUnknownType(args[i][STATS]) &&
991
+ !isUnknownType(env[rest[i][VALUE]][STATS]) &&
992
+ env[rest[i][VALUE]][STATS][ARG_COUNT] !== VARIADIC
993
+ ) {
994
+ // Handles words that are Lambdas
995
+ if (
996
+ env[rest[i][VALUE]][STATS][ARG_COUNT] !==
997
+ args[i][STATS][ARG_COUNT]
918
998
  ) {
919
- const match2 = () => {
920
- const actual =
921
- env[rest[i][VALUE]][STATS][ARGUMENTS][j]
922
- const expected = args[i][STATS][ARGUMENTS][j]
999
+ errorStack.add(
1000
+ `Incorrect number of arguments for (${
1001
+ args[i][STATS][SIGNATURE]
1002
+ }) the (lambda) argument of (${
1003
+ first[VALUE]
1004
+ }) at position (${i}). Expected (= ${
1005
+ args[i][STATS][ARG_COUNT]
1006
+ }) but got ${
1007
+ env[rest[i][VALUE]][STATS][ARG_COUNT]
1008
+ } (${stringifyArgs(exp)}) (check #778)`
1009
+ )
1010
+ } else {
1011
+ // DEFINED LAMBDAS TYPE CHECKING
1012
+ // #C1
1013
+ // TODO delete this maybe
1014
+ // It will not be possilbe to know return type
1015
+ const match1 = () => {
1016
+ const actual = env[rest[i][VALUE]]
1017
+ const expected = args[i]
923
1018
  if (
924
- actual[STATS][TYPE_PROP][0] !== UNKNOWN &&
925
- expected[STATS][TYPE_PROP][0] !== UNKNOWN &&
926
- actual[STATS][TYPE_PROP][0] !==
927
- expected[STATS][TYPE_PROP][0]
928
- )
1019
+ !isUnknownReturn(expected[STATS]) &&
1020
+ !isUnknownReturn(actual[STATS]) &&
1021
+ !compareReturns(expected[STATS], actual[STATS])
1022
+ ) {
929
1023
  errorStack.add(
930
- `Incorrect type for (lambda) (${
931
- args[i][STATS][SIGNATURE]
932
- }) argument at position (${j}) named as (${
933
- env[rest[i][VALUE]][STATS][ARGUMENTS][j][
934
- STATS
935
- ][SIGNATURE]
936
- }). Expected (${toTypeNames(
937
- args[i][STATS][ARGUMENTS][j][STATS][
938
- TYPE_PROP
939
- ][0]
1024
+ `Incorrect return type for (${
1025
+ expected[STATS][SIGNATURE]
1026
+ }) the (lambda) argument of (${
1027
+ first[VALUE]
1028
+ }) at position (${i}). Expected (${toTypeNames(
1029
+ getReturn(expected[STATS])
940
1030
  )}) but got (${toTypeNames(
941
- env[rest[i][VALUE]][STATS][ARGUMENTS][j][
942
- STATS
943
- ][TYPE_PROP][0]
944
- )}) (${stringifyArgs(exp)}) (check #781)`
1031
+ getReturn(actual[STATS])
1032
+ )}) (${stringifyArgs(exp)}) (check #782)`
945
1033
  )
946
- else if (
1034
+ } else if (
947
1035
  actual[STATS].retried < MAX_RETRY_DEFINITION
948
1036
  ) {
949
1037
  actual[STATS].retried += 1
950
- stack.unshift(() => match2())
1038
+ stack.unshift(() => match1())
951
1039
  }
952
1040
  }
953
- match2()
1041
+ match1()
1042
+ for (
1043
+ let j = 0;
1044
+ j < args[i][STATS][ARGUMENTS].length;
1045
+ ++j
1046
+ ) {
1047
+ const match2 = () => {
1048
+ const actual =
1049
+ env[rest[i][VALUE]][STATS][ARGUMENTS][j]
1050
+ const expected = args[i][STATS][ARGUMENTS][j]
1051
+ if (
1052
+ !isUnknownType(actual[STATS]) &&
1053
+ !isUnknownType(expected[STATS]) &&
1054
+ !compareTypes(actual[STATS], expected[STATS])
1055
+ )
1056
+ errorStack.add(
1057
+ `Incorrect type for (lambda) (${
1058
+ args[i][STATS][SIGNATURE]
1059
+ }) argument at position (${j}) named as (${
1060
+ actual[STATS][SIGNATURE]
1061
+ }). Expected (${toTypeNames(
1062
+ getType(expected[STATS])
1063
+ )}) but got (${toTypeNames(
1064
+ getType(actual[STATS])
1065
+ )}) (${stringifyArgs(exp)}) (check #781)`
1066
+ )
1067
+ else if (
1068
+ actual[STATS].retried < MAX_RETRY_DEFINITION
1069
+ ) {
1070
+ actual[STATS].retried += 1
1071
+ stack.unshift(() => match2())
1072
+ }
1073
+ }
1074
+ match2()
1075
+ }
954
1076
  }
955
1077
  }
956
- }
957
- if (
958
- T === COLLECTION &&
959
- env[rest[i][VALUE]] &&
960
- env[rest[i][VALUE]][STATS][TYPE_PROP][0] !== UNKNOWN &&
961
- args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
962
- env[rest[i][VALUE]][STATS][TYPE_PROP][0] !==
963
- args[i][STATS][TYPE_PROP][0]
964
- ) {
965
- errorStack.add(
966
- `Incorrect type of arguments ${i} for (${
967
- first[VALUE]
968
- }). Expected (${toTypeNames(
969
- args[i][STATS][TYPE_PROP][0]
970
- )}) but got (${toTypeNames(T)}) (${stringifyArgs(
971
- exp
972
- )}) (check #30)`
973
- )
974
- } else if (
975
- args[i][STATS][TYPE_PROP][0] === UNKNOWN &&
976
- args[i][STATS].retried < MAX_RETRY_DEFINITION
977
- ) {
978
- args[i][STATS].retried += 1
979
- stack.unshift(() => check(exp, env, scope))
980
- } else {
981
1078
  if (
1079
+ T === COLLECTION &&
982
1080
  env[rest[i][VALUE]] &&
983
- args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
984
- env[rest[i][VALUE]][STATS][TYPE_PROP][0] === UNKNOWN &&
985
- args[i][STATS][TYPE_PROP][0] !== APPLY
1081
+ !isUnknownType(env[rest[i][VALUE]][STATS]) &&
1082
+ !isUnknownType(args[i][STATS]) &&
1083
+ !compareTypes(
1084
+ env[rest[i][VALUE]][STATS],
1085
+ args[i][STATS]
1086
+ )
986
1087
  ) {
987
- // REFF ASSIGMENT
988
- env[rest[i][VALUE]][STATS][TYPE_PROP] =
989
- args[i][STATS][TYPE_PROP]
990
- env[rest[i][VALUE]][STATS][RETURNS] =
991
- args[i][STATS][RETURNS]
992
- }
993
- }
994
- } else if (env[rest[i][0][VALUE]]) {
995
- const match = () => {
996
- const actual = env[rest[i][0][VALUE]][STATS][RETURNS]
997
- const expected = args[i][STATS][TYPE_PROP]
998
- if (args[i][STATS].counter < MAX_ARGUMENT_RETRY) {
999
- args[i][STATS].counter++
1000
- stack.unshift(() => match())
1088
+ errorStack.add(
1089
+ `Incorrect type of arguments ${i} for (${
1090
+ first[VALUE]
1091
+ }). Expected (${toTypeNames(
1092
+ getType(args[i][STATS])
1093
+ )}) but got (${toTypeNames(T)}) (${stringifyArgs(
1094
+ exp
1095
+ )}) (check #30)`
1096
+ )
1097
+ } else if (
1098
+ isUnknownType(args[i][STATS]) &&
1099
+ args[i][STATS].retried < MAX_RETRY_DEFINITION
1100
+ ) {
1101
+ args[i][STATS].retried += 1
1102
+ stack.unshift(() => check(exp, env, scope))
1103
+ } else {
1104
+ if (
1105
+ env[rest[i][VALUE]] &&
1106
+ !isUnknownType(args[i][STATS]) &&
1107
+ isUnknownType(env[rest[i][VALUE]][STATS]) &&
1108
+ getType(args[i][STATS]) !== APPLY
1109
+ ) {
1110
+ // REFF ASSIGMENT
1111
+ env[rest[i][VALUE]][STATS][TYPE_PROP] =
1112
+ args[i][STATS][TYPE_PROP]
1113
+ env[rest[i][VALUE]][STATS][RETURNS] =
1114
+ args[i][STATS][RETURNS]
1115
+ }
1001
1116
  }
1002
- if (expected[0] !== UNKNOWN && actual[0] !== UNKNOWN) {
1003
- if (expected[0] !== actual[0])
1004
- errorStack.add(
1005
- `Incorrect type of arguments ${i} for (${
1006
- first[VALUE]
1007
- }). Expected (${toTypeNames(
1008
- expected[0]
1009
- )}) but got (${toTypeNames(
1010
- actual[0]
1011
- )}) (${stringifyArgs(exp)}) (check #16)`
1012
- )
1013
- else {
1014
- switch (expected[0]) {
1015
- // almost exclusively for anonymous lambdas
1016
- case APPLY:
1017
- {
1018
- const argsN = rest[i].length - 2
1019
- if (
1020
- env[rest[i][0][VALUE]][STATS][SIGNATURE] ===
1021
- KEYWORDS.ANONYMOUS_FUNCTION
1022
- ) {
1023
- if (argsN !== args[i][STATS][ARG_COUNT]) {
1024
- errorStack.add(
1025
- `Incorrect number of arguments for (${
1026
- args[i][STATS][SIGNATURE]
1027
- }) the (lambda) argument of (${
1028
- first[VALUE]
1029
- }) at position (${i}). Expected (= ${
1030
- args[i][STATS][ARG_COUNT]
1031
- }) but got ${argsN} (${stringifyArgs(
1032
- exp
1033
- )}) (check #777)`
1034
- )
1035
- } else {
1036
- // ANONYMOUS LAMBDAS TYPE CHECKING
1037
- const local = Object.create(env)
1038
- const lambdaName = `lambda::annonymous::${i}::${performance
1039
- .now()
1040
- .toString()
1041
- .replace('.', 0)}*`
1042
- check(
1043
- [
1044
- [APPLY, KEYWORDS.DEFINE_VARIABLE],
1045
- [WORD, lambdaName],
1046
- rest[i]
1047
- ],
1048
- local,
1049
- scope
1050
- )
1051
- // TODO delete this maybe
1052
- // It will not be possilbe to know return type
1053
- // const match1 = () => {
1054
- // const actual = local[lambdaName]
1055
- // const expected = args[i]
1056
- // if (
1057
- // expected[STATS][RETURNS][0] !==
1058
- // UNKNOWN &&
1059
- // actual[STATS][RETURNS][0] !== UNKNOWN &&
1060
- // expected[STATS][RETURNS][0] !==
1061
- // actual[STATS][RETURNS][0]
1062
- // ) {
1063
- // errorStack.add(
1064
- // `Incorrect return type for (${
1065
- // expected[STATS][SIGNATURE]
1066
- // }) the (lambda) argument of (${
1067
- // first[VALUE]
1068
- // }) at position (${i}). Expected (${toTypeNames(
1069
- // expected[STATS][RETURNS][0]
1070
- // )}) but got (${toTypeNames(
1071
- // actual[STATS][RETURNS][0]
1072
- // )}) (${stringifyArgs(
1073
- // exp
1074
- // )}) (check #779)`
1075
- // )
1076
- // } else if (
1077
- // actual[STATS].retried <
1078
- // MAX_RETRY_DEFINITION
1079
- // ) {
1080
- // actual[STATS].retried += 1
1081
- // stack.unshift(() => match1())
1082
- // }
1083
- // }
1084
- // match1()
1085
- for (
1086
- let j = 0;
1087
- j < args[i][STATS][ARGUMENTS].length;
1088
- ++j
1089
- ) {
1090
- const match2 = () => {
1091
- const actual =
1092
- local[lambdaName][STATS][ARGUMENTS][j]
1093
- const expected =
1094
- args[i][STATS][ARGUMENTS][j]
1117
+ } else if (env[rest[i][0][VALUE]]) {
1118
+ const match = () => {
1119
+ const actual = env[rest[i][0][VALUE]][STATS]
1120
+ const expected = args[i][STATS]
1121
+ if (args[i][STATS].counter < MAX_ARGUMENT_RETRY) {
1122
+ args[i][STATS].counter++
1123
+ stack.unshift(() => match())
1124
+ }
1125
+ if (
1126
+ !isUnknownType(expected) &&
1127
+ !isUnknownReturn(actual)
1128
+ ) {
1129
+ if (!compareTypeWithReturn(expected, actual)) {
1130
+ errorStack.add(
1131
+ `Incorrect type of arguments ${i} for (${
1132
+ first[VALUE]
1133
+ }). Expected (${toTypeNames(
1134
+ getType(expected)
1135
+ )}) but got (${toTypeNames(
1136
+ getReturn(actual)
1137
+ )}) (${stringifyArgs(exp)}) (check #16)`
1138
+ )
1139
+ } else {
1140
+ switch (getType(expected)) {
1141
+ // almost exclusively for anonymous lambdas
1142
+ case APPLY:
1143
+ {
1144
+ const argsN = rest[i].length - 2
1145
+ if (
1146
+ env[rest[i][0][VALUE]][STATS][SIGNATURE] ===
1147
+ KEYWORDS.ANONYMOUS_FUNCTION
1148
+ ) {
1149
+ if (argsN !== args[i][STATS][ARG_COUNT]) {
1150
+ errorStack.add(
1151
+ `Incorrect number of arguments for (${
1152
+ args[i][STATS][SIGNATURE]
1153
+ }) the (lambda) argument of (${
1154
+ first[VALUE]
1155
+ }) at position (${i}). Expected (= ${
1156
+ args[i][STATS][ARG_COUNT]
1157
+ }) but got ${argsN} (${stringifyArgs(
1158
+ exp
1159
+ )}) (check #777)`
1160
+ )
1161
+ } else {
1162
+ // ANONYMOUS LAMBDAS TYPE CHECKING
1163
+ const local = Object.create(env)
1164
+ const lambdaName = `lambda::annonymous::${i}::${performance
1165
+ .now()
1166
+ .toString()
1167
+ .replace('.', 0)}*`
1168
+ check(
1169
+ [
1170
+ [APPLY, KEYWORDS.DEFINE_VARIABLE],
1171
+ [WORD, lambdaName],
1172
+ rest[i]
1173
+ ],
1174
+ local,
1175
+ scope
1176
+ )
1177
+ // TODO delete this maybe
1178
+ // #C2
1179
+ // It will not be possilbe to know return type
1180
+ const match1 = () => {
1181
+ const actual = local[lambdaName]
1182
+ const expected = args[i]
1095
1183
  if (
1096
- actual[STATS][TYPE_PROP][0] !==
1097
- UNKNOWN &&
1098
- expected[STATS][TYPE_PROP][0] !==
1099
- UNKNOWN &&
1100
- actual[STATS][TYPE_PROP][0] !==
1101
- expected[STATS][TYPE_PROP][0]
1184
+ !isUnknownReturn(expected[STATS]) &&
1185
+ !isUnknownReturn(actual[STATS]) &&
1186
+ !compareReturns(
1187
+ expected[STATS],
1188
+ actual[STATS]
1189
+ )
1102
1190
  ) {
1103
1191
  errorStack.add(
1104
- `Incorrect type for (lambda) (${
1105
- args[i][STATS][SIGNATURE]
1106
- }) argument at position (${j}) named as (${
1107
- local[lambdaName][STATS][
1108
- ARGUMENTS
1109
- ][j][STATS][SIGNATURE]
1110
- }). Expected (${toTypeNames(
1111
- args[i][STATS][ARGUMENTS][j][
1112
- STATS
1113
- ][TYPE_PROP][0]
1192
+ `Incorrect return type for (${
1193
+ expected[STATS][SIGNATURE]
1194
+ }) the (lambda) argument of (${
1195
+ first[VALUE]
1196
+ }) at position (${i}). Expected (${toTypeNames(
1197
+ getReturn(expected[STATS])
1114
1198
  )}) but got (${toTypeNames(
1115
- local[lambdaName][STATS][
1116
- ARGUMENTS
1117
- ][j][STATS][TYPE_PROP][0]
1199
+ getReturn(actual[STATS])
1118
1200
  )}) (${stringifyArgs(
1119
1201
  exp
1120
- )}) (check #780)`
1202
+ )}) (check #779)`
1121
1203
  )
1122
1204
  } else if (
1123
1205
  actual[STATS].retried <
1124
1206
  MAX_RETRY_DEFINITION
1125
1207
  ) {
1126
1208
  actual[STATS].retried += 1
1127
- stack.unshift(() => match2())
1209
+ stack.unshift(() => match1())
1210
+ }
1211
+ }
1212
+ match1()
1213
+ for (
1214
+ let j = 0;
1215
+ j < args[i][STATS][ARGUMENTS].length;
1216
+ ++j
1217
+ ) {
1218
+ const match2 = () => {
1219
+ const actual =
1220
+ local[lambdaName][STATS][ARGUMENTS][
1221
+ j
1222
+ ]
1223
+ const expected =
1224
+ args[i][STATS][ARGUMENTS][j]
1225
+ if (
1226
+ !isUnknownType(actual[STATS]) &&
1227
+ !isUnknownType(expected[STATS]) &&
1228
+ !compareTypes(
1229
+ actual[STATS],
1230
+ expected[STATS]
1231
+ )
1232
+ ) {
1233
+ errorStack.add(
1234
+ `Incorrect type for (lambda) (${
1235
+ args[i][STATS][SIGNATURE]
1236
+ }) argument at position (${j}) named as (${
1237
+ local[lambdaName][STATS][
1238
+ ARGUMENTS
1239
+ ][j][STATS][SIGNATURE]
1240
+ }). Expected (${toTypeNames(
1241
+ getType(expected[STATS])
1242
+ )}) but got (${toTypeNames(
1243
+ getType(actual[STATS])
1244
+ )}) (${stringifyArgs(
1245
+ exp
1246
+ )}) (check #780)`
1247
+ )
1248
+ } else if (
1249
+ actual[STATS].retried <
1250
+ MAX_RETRY_DEFINITION
1251
+ ) {
1252
+ actual[STATS].retried += 1
1253
+ stack.unshift(() => match2())
1254
+ }
1128
1255
  }
1256
+ match2()
1129
1257
  }
1130
- match2()
1131
1258
  }
1259
+ } else {
1260
+ // TODO fix curry: lambdas enter here as undefined
1132
1261
  }
1133
- } else {
1134
- // TODO fix curry: lambdas enter here as undefined
1135
1262
  }
1136
- }
1137
- break
1138
- // case ATOM:
1139
- // case COLLECTION:
1140
- // break
1263
+ break
1264
+ // case ATOM:
1265
+ // case COLLECTION:
1266
+ // break
1267
+ }
1141
1268
  }
1269
+ } else if (
1270
+ isUnknownType(expected) &&
1271
+ args[i][STATS].retried < MAX_RETRY_DEFINITION
1272
+ ) {
1273
+ args[i][STATS].retried += 1
1274
+ stack.unshift(() => match())
1142
1275
  }
1143
- } else if (
1144
- expected[0] === UNKNOWN &&
1145
- args[i][STATS].retried < MAX_RETRY_DEFINITION
1146
- ) {
1147
- args[i][STATS].retried += 1
1148
- stack.unshift(() => match())
1149
1276
  }
1277
+ match()
1150
1278
  }
1151
- match()
1152
1279
  }
1153
1280
  }
1154
- }
1155
- })
1281
+ })
1156
1282
  for (let i = 0; i < rest.length; ++i) {
1157
1283
  const r = rest[i]
1158
1284
  if (isLeaf(r) && r[TYPE] !== ATOM) {
@@ -1176,8 +1302,10 @@ export const typeCheck = (ast) => {
1176
1302
  const copy = JSON.parse(JSON.stringify(ast))
1177
1303
  check(copy, root, copy)
1178
1304
  while (stack.length) stack.pop()()
1179
- const issues = [...errorStack, ...warningStack]
1180
- if (issues.length) throw new TypeError(issues.join('\n'))
1305
+ if (error) {
1306
+ const issues = [...errorStack, ...warningStack]
1307
+ if (issues.length) throw new TypeError(issues.join('\n'))
1308
+ }
1181
1309
  return [ast, Types]
1182
1310
  }
1183
1311
  export const type = (ast) => typeCheck(ast)[0]