fez-lisp 1.5.91 → 1.5.93

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