fez-lisp 1.5.100 → 1.5.102

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
@@ -66,6 +66,10 @@ const deepLambdaReturn = (rest, condition) => {
66
66
  const rem = hasBlock(body) ? body.at(-1) : body
67
67
  return condition(rem) ? rem : deepLambdaReturn(rem, condition)
68
68
  }
69
+ export const isUnknownNotAnyType = (stats) =>
70
+ stats && !isAnyType(stats) && isUnknownType(stats)
71
+ export const isUnknownNotAnyReturn = (stats) =>
72
+ stats && !isAnyReturn(stats) && isUnknownReturn(stats)
69
73
  export const castType = (stats, type) =>
70
74
  (stats[TYPE_PROP][0] = type[RETURNS][0])
71
75
  export const castReturn = (stats, type) =>
@@ -142,12 +146,12 @@ export const compareReturns = (a, b) =>
142
146
  isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
143
147
  export const compareTypeWithReturn = (a, b) =>
144
148
  isAnyType(a) || isAnyReturn(b) || a[TYPE_PROP][0] === b[RETURNS][0]
145
- const checkPredicateName = (exp, rest, errors) => {
149
+ const checkPredicateName = (exp, rest) => {
146
150
  if (getSuffix(rest[0][VALUE]) === PREDICATE_SUFFIX) {
147
151
  const last = rest.at(-1)
148
152
  if (isLeaf(last)) {
149
153
  if (last[TYPE] === ATOM && last[VALUE] !== TRUE && last[VALUE] !== FALSE)
150
- errors.add(
154
+ throw new TypeError(
151
155
  `Assigning predicate (ending in ?) variable (${
152
156
  rest[0][VALUE]
153
157
  }) to an (${
@@ -159,7 +163,7 @@ const checkPredicateName = (exp, rest, errors) => {
159
163
  getSuffix(last[VALUE]) !== PREDICATE_SUFFIX &&
160
164
  !PREDICATES_OUTPUT_SET.has(last[VALUE])
161
165
  )
162
- errors.add(
166
+ throw new TypeError(
163
167
  `Assigning predicate (ending in ?) variable (${
164
168
  rest[0][VALUE]
165
169
  }) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
@@ -177,7 +181,7 @@ const checkPredicateName = (exp, rest, errors) => {
177
181
  getSuffix(application[VALUE]) !== PREDICATE_SUFFIX &&
178
182
  !PREDICATES_OUTPUT_SET.has(application[VALUE])
179
183
  )
180
- errors.add(
184
+ throw new TypeError(
181
185
  `Assigning predicate (ending in ?) variable (${
182
186
  application[VALUE]
183
187
  }) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
@@ -189,21 +193,17 @@ const checkPredicateName = (exp, rest, errors) => {
189
193
  }
190
194
  }
191
195
  }
192
- const checkPredicateNameDeep = (name, exp, rest, returns, errors) => {
196
+ const checkPredicateNameDeep = (name, exp, rest, returns) => {
193
197
  if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
194
198
  const fn = rest.at(-1).at(-1).at(-1)
195
- checkPredicateName(
196
- exp,
197
- [
198
- [WORD, name],
199
- isLeaf(fn)
200
- ? fn // when apply is a word (let x? (lambda (apply [] array:empty!)))
201
- : drillReturnType(fn, (r) => r[VALUE] === KEYWORDS.CALL_FUNCTION) // when apply is an annonymous lambda // (let fn? (lambda x (apply x (lambda x (array:empty! [])))))
202
- ],
203
- errors
204
- )
199
+ checkPredicateName(exp, [
200
+ [WORD, name],
201
+ isLeaf(fn)
202
+ ? fn // when apply is a word (let x? (lambda (apply [] array:empty!)))
203
+ : drillReturnType(fn, (r) => r[VALUE] === KEYWORDS.CALL_FUNCTION) // when apply is an annonymous lambda // (let fn? (lambda x (apply x (lambda x (array:empty! [])))))
204
+ ])
205
205
  } else {
206
- checkPredicateName(exp, [[WORD, name], returns], errors)
206
+ checkPredicateName(exp, [[WORD, name], returns])
207
207
  }
208
208
  }
209
209
  const fillUknownArgs = (n) =>
@@ -234,7 +234,21 @@ const withScope = (name, scope) => {
234
234
  const chain = getScopeNames(scope)
235
235
  return `${chain.length === 1 ? '; ' : ''}${chain.join(' ')} ${name}`
236
236
  }
237
-
237
+ const retry = (stats, stack, cb) => {
238
+ if (
239
+ (isUnknownNotAnyType(stats) || isUnknownNotAnyReturn(stats)) &&
240
+ stats.retried < MAX_RETRY_DEFINITION
241
+ ) {
242
+ stats.retried += 1
243
+ stack.unshift(() => cb())
244
+ }
245
+ }
246
+ const retryArgs = (stats, stack, cb) => {
247
+ if (stats.counter < MAX_ARGUMENT_RETRY) {
248
+ stats.counter++
249
+ stack.unshift(cb)
250
+ }
251
+ }
238
252
  const ifExpression = ({ re, env, ref }) => {
239
253
  if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) setReturnToAtom(ref[STATS])
240
254
  // TODO check that both brancehs are predicates if one is
@@ -259,18 +273,23 @@ const ifExpression = ({ re, env, ref }) => {
259
273
  }
260
274
  }
261
275
  }
262
- const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
276
+ const resolveApplyAssigment = (re, name, env) => {
277
+ if (re[0][TYPE] === APPLY) {
278
+ switch (re[0][VALUE]) {
279
+ case KEYWORDS.ANONYMOUS_FUNCTION:
280
+ // FN ASSIGMENT
281
+ env[name][STATS][TYPE_PROP] = [APPLY]
282
+ env[name][STATS][RETURNS] = [UNKNOWN]
283
+ env[name][STATS][ARG_COUNT] = re.length - 2
284
+ env[name][STATS][ARGUMENTS] = fillUknownArgs(re.length - 2)
285
+ break
286
+ }
287
+ }
288
+ }
289
+ const resolveIfAssigment = ({ rem, name, env, exp, prop }) => {
263
290
  const re = rem.slice(2)
264
- checkPredicateName(
265
- exp,
266
- [[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]],
267
- errors
268
- )
269
- checkPredicateName(
270
- exp,
271
- [[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]],
272
- errors
273
- )
291
+ checkPredicateName(exp, [[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]])
292
+ checkPredicateName(exp, [[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]])
274
293
  if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM)
275
294
  // ATOM ASSIGMENT
276
295
  setPropToAtom(env[name][STATS], prop)
@@ -280,17 +299,7 @@ const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
280
299
  !isUnknownReturn(env[re[0][0][VALUE]][STATS])
281
300
  ) {
282
301
  setPropToReturnRef(env[name][STATS], prop, env[re[0][0][VALUE]][STATS])
283
- if (re[0][0][TYPE] === APPLY) {
284
- switch (re[0][0][VALUE]) {
285
- case KEYWORDS.ANONYMOUS_FUNCTION:
286
- // FN UKNONW ASSIGMENT
287
- env[name][STATS][TYPE_PROP] = [APPLY]
288
- env[name][STATS][RETURNS] = [UNKNOWN]
289
- env[name][STATS][ARG_COUNT] = re[0].length - 2
290
- env[name][STATS][ARGUMENTS] = fillUknownArgs(re[0].length - 2)
291
- break
292
- }
293
- }
302
+ resolveApplyAssigment(re[0], name, env)
294
303
  // env[name][STATS] = env[re[0][0][VALUE]][STATS]
295
304
  } else if (
296
305
  !isLeaf(re[1]) &&
@@ -298,17 +307,7 @@ const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
298
307
  !isUnknownReturn(env[re[1][0][VALUE]][STATS])
299
308
  ) {
300
309
  setPropToReturnRef(env[name][STATS], prop, env[re[1][0][VALUE]][STATS])
301
- if (re[1][0][TYPE] === APPLY) {
302
- switch (re[1][0][VALUE]) {
303
- case KEYWORDS.ANONYMOUS_FUNCTION:
304
- // FN ASSIGMENT
305
- env[name][STATS][TYPE_PROP] = [APPLY]
306
- env[name][STATS][RETURNS] = [UNKNOWN]
307
- env[name][STATS][ARG_COUNT] = re[1].length - 2
308
- env[name][STATS][ARGUMENTS] = fillUknownArgs(re[1].length - 2)
309
- break
310
- }
311
- }
310
+ resolveApplyAssigment(re[1], name, env)
312
311
  } else if (env[re[0][VALUE]])
313
312
  // ASSIGMENT
314
313
  setPropRef(env[name][STATS], prop, env[re[0][VALUE]][STATS])
@@ -316,20 +315,13 @@ const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
316
315
  // ASSIGMENT
317
316
  setPropRef(env[name][STATS], prop, env[re[1][VALUE]][STATS])
318
317
  }
319
- const resolveCondition = ({ rem, name, env, exp, errors }) => {
318
+ const resolveCondition = ({ rem, name, env, exp }) => {
320
319
  const ret = rem[0]
321
320
  const re = rem.slice(2)
321
+ resolveApplyAssigment(re, name, env)
322
322
  const ref = env[name]
323
- checkPredicateName(
324
- exp,
325
- [[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]],
326
- errors
327
- )
328
- checkPredicateName(
329
- exp,
330
- [[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]],
331
- errors
332
- )
323
+ checkPredicateName(exp, [[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]])
324
+ checkPredicateName(exp, [[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]])
333
325
  switch (ret[VALUE]) {
334
326
  case KEYWORDS.IF:
335
327
  ifExpression({ re, env, ref })
@@ -343,27 +335,18 @@ const resolveCondition = ({ rem, name, env, exp, errors }) => {
343
335
  break
344
336
  }
345
337
  }
346
- const resolveRetunType = ({
347
- returns,
348
- rem,
349
- stack,
350
- prop,
351
- exp,
352
- name,
353
- errors,
354
- env
355
- }) => {
338
+ const resolveRetunType = ({ returns, rem, stack, prop, exp, name, env }) => {
356
339
  if (returns[TYPE] === ATOM) {
357
340
  // ATOM ASSIGMENT
358
341
  setPropToAtom(env[name][STATS], prop)
359
- checkPredicateName(exp, [[WORD, name], returns], errors)
342
+ checkPredicateName(exp, [[WORD, name], returns])
360
343
  } else {
361
344
  switch (returns[VALUE]) {
362
345
  case KEYWORDS.IF:
363
- resolveIfAssigment({ rem, name, env, exp, errors, prop })
346
+ resolveIfAssigment({ rem, name, env, exp, prop })
364
347
  break
365
348
  default:
366
- checkPredicateNameDeep(name, exp, exp.slice(1), returns, errors)
349
+ checkPredicateNameDeep(name, exp, exp.slice(1), returns)
367
350
  if (!env[returns[VALUE]]) return false
368
351
  else if (getType(env[returns[VALUE]][STATS]) === APPLY) {
369
352
  if (returns[TYPE] === WORD) setReturnToAbbstraction(env[name][STATS])
@@ -388,7 +371,7 @@ const resolveRetunType = ({
388
371
  }
389
372
  return true
390
373
  }
391
- const checkReturnType = ({ exp, stack, name, errors, env }) => {
374
+ const checkReturnType = ({ exp, stack, name, env }) => {
392
375
  const last = exp.at(-1).at(-1)
393
376
  const body = hasApplyLambdaBlock(last) ? last.at(-1).at(-1) : last
394
377
  const rem = hasBlock(body) ? body.at(-1) : body
@@ -399,7 +382,6 @@ const checkReturnType = ({ exp, stack, name, errors, env }) => {
399
382
  prop: RETURNS,
400
383
  exp,
401
384
  name,
402
- errors,
403
385
  env,
404
386
  stack
405
387
  })
@@ -407,7 +389,6 @@ const checkReturnType = ({ exp, stack, name, errors, env }) => {
407
389
  export const typeCheck = (ast, error = true) => {
408
390
  let scopeIndex = 0
409
391
  const root = structuredClone(SPECIAL_FORM_TYPES)
410
- const errors = new Set()
411
392
  const Types = new Map()
412
393
  const stack = []
413
394
  const check = (exp, env, scope) => {
@@ -421,14 +402,14 @@ export const typeCheck = (ast, error = true) => {
421
402
  switch (first[TYPE]) {
422
403
  case WORD:
423
404
  if (!isSpecial)
424
- stack.push(
425
- () =>
426
- // Figure out how to determine if varible is define after it's used
427
- env[first[VALUE]] === undefined &&
428
- errors.add(
405
+ stack.push(() => {
406
+ // Figure out how to determine if varible is define after it's used
407
+ if (env[first[VALUE]] === undefined) {
408
+ throw new TypeError(
429
409
  `Trying to access undefined variable ${first[VALUE]} (check #11)`
430
410
  )
431
- )
411
+ }
412
+ })
432
413
  break
433
414
  case ATOM:
434
415
  break
@@ -470,35 +451,30 @@ export const typeCheck = (ast, error = true) => {
470
451
  stack,
471
452
  exp,
472
453
  env,
473
- name,
474
- errors
454
+ name
475
455
  }) ||
476
- (isUnknownReturn(env[name][STATS]) &&
477
- env[name][STATS].retried < MAX_RETRY_DEFINITION)
456
+ isUnknownReturn(env[name][STATS])
478
457
  ) {
479
- env[name][STATS].retried += 1
480
- stack.unshift(() => {
458
+ retry(env[name][STATS], stack, () => {
481
459
  checkReturnType({
482
460
  stack,
483
461
  exp,
484
462
  env,
485
- name,
486
- errors
463
+ name
487
464
  })
488
465
  check(rightHand, env, exp)
489
466
  })
490
467
  check(rightHand, env, exp)
491
468
  } else check(rightHand, env, exp)
492
469
  } else {
493
- checkPredicateName(exp, rest, errors)
470
+ checkPredicateName(exp, rest)
494
471
  const isLeafNode = isLeaf(rightHand)
495
472
  if (isLeafNode && rightHand[TYPE] === WORD) {
496
473
  // TODO make sure this prevents the assigment all together
497
474
  if (env[rest[1][VALUE]] === undefined)
498
- errors.add(
475
+ throw new TypeError(
499
476
  `Trying to access undefined variable ${rest[1][VALUE]} (check #22)`
500
477
  )
501
-
502
478
  // Used to be checkin if it's an assigment to a special form
503
479
  // but this should not cause problems
504
480
  // env[name] = SPECIAL_FORMS_SET.has(rest[1][VALUE])
@@ -519,7 +495,7 @@ export const typeCheck = (ast, error = true) => {
519
495
  }
520
496
  } else if (rightHand[0]) {
521
497
  const right = rightHand[0]
522
- //DECLARATION
498
+ // DECLARATION
523
499
  env[name] = {
524
500
  [STATS]: {
525
501
  retried: 0,
@@ -545,8 +521,7 @@ export const typeCheck = (ast, error = true) => {
545
521
  prop: TYPE_PROP,
546
522
  exp,
547
523
  env,
548
- name,
549
- errors
524
+ name
550
525
  })
551
526
  }
552
527
  check(rightHand, env, scope)
@@ -564,7 +539,7 @@ export const typeCheck = (ast, error = true) => {
564
539
  const param = params[i]
565
540
  // TODO move this somewhere else
566
541
  if (!isLeaf(param))
567
- errors.add(
542
+ throw new TypeError(
568
543
  `Invalid body for (${
569
544
  first[VALUE]
570
545
  }) if it takes more than one expression it must be wrapped in a (${
@@ -607,7 +582,6 @@ export const typeCheck = (ast, error = true) => {
607
582
  name: ref[STATS][SIGNATURE],
608
583
  env: copy,
609
584
  exp,
610
- errors,
611
585
  stack
612
586
  })
613
587
  break
@@ -619,7 +593,6 @@ export const typeCheck = (ast, error = true) => {
619
593
  if (copy[ret[VALUE]])
620
594
  setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
621
595
  })
622
-
623
596
  break
624
597
  }
625
598
  }
@@ -648,7 +621,7 @@ export const typeCheck = (ast, error = true) => {
648
621
  default:
649
622
  stack.push(() => {
650
623
  if (!isSpecial && env[first[VALUE]] === undefined)
651
- errors.add(
624
+ throw new TypeError(
652
625
  `Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
653
626
  )
654
627
  else if (
@@ -656,7 +629,7 @@ export const typeCheck = (ast, error = true) => {
656
629
  env[first[VALUE]][STATS][ARG_COUNT] !== VARIADIC &&
657
630
  env[first[VALUE]][STATS][ARG_COUNT] !== rest.length
658
631
  )
659
- errors.add(
632
+ throw new TypeError(
660
633
  `Incorrect number of arguments for (${
661
634
  first[VALUE]
662
635
  }). Expected (= ${
@@ -666,7 +639,7 @@ export const typeCheck = (ast, error = true) => {
666
639
  else {
667
640
  if (first[TYPE] === APPLY && !isSpecial) {
668
641
  if (getType(env[first[VALUE]][STATS]) === ATOM)
669
- errors.add(
642
+ throw new TypeError(
670
643
  `(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
671
644
  exp
672
645
  )}) (check #12)`
@@ -737,7 +710,7 @@ export const typeCheck = (ast, error = true) => {
737
710
  const fnName = rest[i].at(-1)[VALUE]
738
711
  const fn = env[fnName]
739
712
  if (fn && getReturn(fn[STATS]) !== ATOM)
740
- errors.add(
713
+ throw new TypeError(
741
714
  `Incorrect type of argument (${i}) for (${
742
715
  first[VALUE]
743
716
  }). Expected (${toTypeNames(
@@ -752,7 +725,7 @@ export const typeCheck = (ast, error = true) => {
752
725
  const returns = isLeaf(rem) ? rem : rem[0]
753
726
  if (returns[TYPE] === ATOM) {
754
727
  if (MAIN_TYPE !== ATOM)
755
- errors.add(
728
+ throw new TypeError(
756
729
  `Incorrect type of argument ${i} for (${
757
730
  first[VALUE]
758
731
  }). Expected (${toTypeNames(
@@ -766,7 +739,7 @@ export const typeCheck = (ast, error = true) => {
766
739
  !isUnknownReturn(env[returns[VALUE]][STATS]) &&
767
740
  getReturn(env[returns[VALUE]][STATS]) !== ATOM
768
741
  )
769
- errors.add(
742
+ throw new TypeError(
770
743
  `Incorrect type of argument ${i} for (${
771
744
  first[VALUE]
772
745
  }). Expected (${toTypeNames(
@@ -789,7 +762,7 @@ export const typeCheck = (ast, error = true) => {
789
762
  env[name][STATS]
790
763
  )
791
764
  )
792
- errors.add(
765
+ throw new TypeError(
793
766
  `Incorrect type of argument (${i}) for special form (${
794
767
  first[VALUE]
795
768
  }). Expected (${toTypeNames(
@@ -829,7 +802,7 @@ export const typeCheck = (ast, error = true) => {
829
802
  env[name][STATS]
830
803
  )
831
804
  )
832
- errors.add(
805
+ throw new TypeError(
833
806
  `Incorrect type of argument (${i}) for special form (${
834
807
  first[VALUE]
835
808
  }). Expected (${toTypeNames(
@@ -847,7 +820,7 @@ export const typeCheck = (ast, error = true) => {
847
820
  rest[i][TYPE] !==
848
821
  expectedArgs[i][STATS][TYPE_PROP][0]
849
822
  )
850
- errors.add(
823
+ throw new TypeError(
851
824
  `Incorrect type of argument (${i}) for special form (${
852
825
  first[VALUE]
853
826
  }). Expected (${toTypeNames(
@@ -874,7 +847,7 @@ export const typeCheck = (ast, error = true) => {
874
847
  !isUnknownType(args[i][STATS]) &&
875
848
  getType(args[i][STATS]) !== ATOM
876
849
  ) {
877
- errors.add(
850
+ throw new TypeError(
878
851
  `Incorrect type of arguments ${i} for (${
879
852
  first[VALUE]
880
853
  }). Expected (${toTypeNames(
@@ -894,7 +867,7 @@ export const typeCheck = (ast, error = true) => {
894
867
  env[rest[i][VALUE]][STATS][ARG_COUNT] !==
895
868
  args[i][STATS][ARG_COUNT]
896
869
  ) {
897
- errors.add(
870
+ throw new TypeError(
898
871
  `Incorrect number of arguments for (${
899
872
  args[i][STATS][SIGNATURE]
900
873
  }) the (lambda) argument of (${
@@ -918,7 +891,7 @@ export const typeCheck = (ast, error = true) => {
918
891
  !isUnknownReturn(actual[STATS]) &&
919
892
  !compareReturns(expected[STATS], actual[STATS])
920
893
  ) {
921
- errors.add(
894
+ throw new TypeError(
922
895
  `Incorrect return type for (${
923
896
  expected[STATS][SIGNATURE]
924
897
  }) the (lambda) argument of (${
@@ -929,12 +902,7 @@ export const typeCheck = (ast, error = true) => {
929
902
  getReturn(actual[STATS])
930
903
  )}) (${stringifyArgs(exp)}) (check #782)`
931
904
  )
932
- } else if (
933
- actual[STATS].retried < MAX_RETRY_DEFINITION
934
- ) {
935
- actual[STATS].retried += 1
936
- stack.unshift(() => match1())
937
- }
905
+ } else retry(actual[STATS], stack, () => match1())
938
906
  }
939
907
  match1()
940
908
  for (
@@ -951,7 +919,7 @@ export const typeCheck = (ast, error = true) => {
951
919
  !isUnknownType(expected[STATS]) &&
952
920
  !compareTypes(actual[STATS], expected[STATS])
953
921
  )
954
- errors.add(
922
+ throw new TypeError(
955
923
  `Incorrect type for (lambda) (${
956
924
  args[i][STATS][SIGNATURE]
957
925
  }) argument at position (${j}) named as (${
@@ -962,12 +930,7 @@ export const typeCheck = (ast, error = true) => {
962
930
  getType(actual[STATS])
963
931
  )}) (${stringifyArgs(exp)}) (check #781)`
964
932
  )
965
- else if (
966
- actual[STATS].retried < MAX_RETRY_DEFINITION
967
- ) {
968
- actual[STATS].retried += 1
969
- stack.unshift(() => match2())
970
- }
933
+ else retry(actual[STATS], stack, () => match2())
971
934
  }
972
935
  match2()
973
936
  }
@@ -980,7 +943,7 @@ export const typeCheck = (ast, error = true) => {
980
943
  !isUnknownType(args[i][STATS]) &&
981
944
  !compareTypes(env[rest[i][VALUE]][STATS], args[i][STATS])
982
945
  ) {
983
- errors.add(
946
+ throw new TypeError(
984
947
  `Incorrect type of arguments ${i} for (${
985
948
  first[VALUE]
986
949
  }). Expected (${toTypeNames(
@@ -989,37 +952,28 @@ export const typeCheck = (ast, error = true) => {
989
952
  exp
990
953
  )}) (check #30)`
991
954
  )
992
- } else if (
993
- isUnknownType(args[i][STATS]) &&
994
- args[i][STATS].retried < MAX_RETRY_DEFINITION
955
+ } else if (isUnknownType(args[i][STATS]))
956
+ retry(args[i][STATS], stack, () => check(exp, env, scope))
957
+ else if (
958
+ env[rest[i][VALUE]] &&
959
+ !isUnknownType(args[i][STATS]) &&
960
+ isUnknownType(env[rest[i][VALUE]][STATS]) &&
961
+ getType(args[i][STATS]) !== APPLY
995
962
  ) {
996
- args[i][STATS].retried += 1
997
- stack.unshift(() => check(exp, env, scope))
998
- } else {
999
- if (
1000
- env[rest[i][VALUE]] &&
1001
- !isUnknownType(args[i][STATS]) &&
1002
- isUnknownType(env[rest[i][VALUE]][STATS]) &&
1003
- getType(args[i][STATS]) !== APPLY
1004
- ) {
1005
- // REFF ASSIGMENT
1006
- env[rest[i][VALUE]][STATS][TYPE_PROP] =
1007
- args[i][STATS][TYPE_PROP]
1008
- env[rest[i][VALUE]][STATS][RETURNS] =
1009
- args[i][STATS][RETURNS]
1010
- }
963
+ // REFF ASSIGMENT
964
+ env[rest[i][VALUE]][STATS][TYPE_PROP] =
965
+ args[i][STATS][TYPE_PROP]
966
+ env[rest[i][VALUE]][STATS][RETURNS] =
967
+ args[i][STATS][RETURNS]
1011
968
  }
1012
969
  } else if (env[rest[i][0][VALUE]]) {
1013
970
  const match = () => {
1014
971
  const actual = env[rest[i][0][VALUE]][STATS]
1015
972
  const expected = args[i][STATS]
1016
- if (args[i][STATS].counter < MAX_ARGUMENT_RETRY) {
1017
- args[i][STATS].counter++
1018
- stack.unshift(() => match())
1019
- }
973
+ retryArgs(args[i][STATS], stack, () => match())
1020
974
  if (!isUnknownType(expected) && !isUnknownReturn(actual))
1021
975
  if (!compareTypeWithReturn(expected, actual))
1022
- errors.add(
976
+ throw new TypeError(
1023
977
  `Incorrect type of arguments ${i} for (${
1024
978
  first[VALUE]
1025
979
  }). Expected (${toTypeNames(
@@ -1039,7 +993,7 @@ export const typeCheck = (ast, error = true) => {
1039
993
  KEYWORDS.ANONYMOUS_FUNCTION
1040
994
  ) {
1041
995
  if (argsN !== args[i][STATS][ARG_COUNT])
1042
- errors.add(
996
+ throw new TypeError(
1043
997
  `Incorrect number of arguments for (${
1044
998
  args[i][STATS][SIGNATURE]
1045
999
  }) the (lambda) argument of (${
@@ -1077,7 +1031,7 @@ export const typeCheck = (ast, error = true) => {
1077
1031
  actual[STATS]
1078
1032
  )
1079
1033
  )
1080
- errors.add(
1034
+ throw new TypeError(
1081
1035
  `Incorrect return type for (${
1082
1036
  expected[STATS][SIGNATURE]
1083
1037
  }) the (lambda) argument of (${
@@ -1090,13 +1044,10 @@ export const typeCheck = (ast, error = true) => {
1090
1044
  exp
1091
1045
  )}) (check #779)`
1092
1046
  )
1093
- else if (
1094
- actual[STATS].retried <
1095
- MAX_RETRY_DEFINITION
1096
- ) {
1097
- actual[STATS].retried += 1
1098
- stack.unshift(() => match1())
1099
- }
1047
+ else
1048
+ retry(actual[STATS], stack, () =>
1049
+ match1()
1050
+ )
1100
1051
  }
1101
1052
  match1()
1102
1053
  for (
@@ -1117,7 +1068,7 @@ export const typeCheck = (ast, error = true) => {
1117
1068
  expected[STATS]
1118
1069
  )
1119
1070
  )
1120
- errors.add(
1071
+ throw new TypeError(
1121
1072
  `Incorrect type for (lambda) (${
1122
1073
  args[i][STATS][SIGNATURE]
1123
1074
  }) argument at position (${j}) named as (${
@@ -1132,13 +1083,10 @@ export const typeCheck = (ast, error = true) => {
1132
1083
  exp
1133
1084
  )}) (check #780)`
1134
1085
  )
1135
- else if (
1136
- actual[STATS].retried <
1137
- MAX_RETRY_DEFINITION
1138
- ) {
1139
- actual[STATS].retried += 1
1140
- stack.unshift(() => match2())
1141
- }
1086
+ else
1087
+ retry(actual[STATS], stack, () =>
1088
+ match2()
1089
+ )
1142
1090
  }
1143
1091
  match2()
1144
1092
  }
@@ -1153,24 +1101,20 @@ export const typeCheck = (ast, error = true) => {
1153
1101
  // break
1154
1102
  }
1155
1103
  }
1156
- else if (
1157
- isUnknownType(expected) &&
1158
- args[i][STATS].retried < MAX_RETRY_DEFINITION
1159
- ) {
1160
- args[i][STATS].retried += 1
1161
- stack.unshift(() => match())
1162
- }
1104
+ else if (isUnknownType(expected))
1105
+ retry(args[i][STATS], stack, () => match())
1163
1106
  }
1164
1107
  match()
1165
1108
  }
1166
1109
  }
1167
1110
  }
1168
1111
  })
1112
+
1169
1113
  for (let i = 0; i < rest.length; ++i) {
1170
1114
  const r = rest[i]
1171
1115
  if (isLeaf(r) && r[TYPE] !== ATOM)
1172
1116
  if (env[r[VALUE]] == undefined)
1173
- errors.add(
1117
+ throw new TypeError(
1174
1118
  `(${
1175
1119
  first[VALUE]
1176
1120
  }) is trying to access undefined variable (${
@@ -1187,7 +1131,6 @@ export const typeCheck = (ast, error = true) => {
1187
1131
  const copy = JSON.parse(JSON.stringify(ast))
1188
1132
  check(copy, root, copy)
1189
1133
  while (stack.length) stack.pop()()
1190
- if (error && errors.size) throw new TypeError([...errors.values()].join('\n'))
1191
1134
  return [ast, Types]
1192
1135
  }
1193
1136
  export const type = (ast) => typeCheck(ast)[0]