fez-lisp 1.5.101 → 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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "fez-lisp",
3
3
  "description": "Lisp interpreted & compiled to JavaScript",
4
4
  "author": "AT290690",
5
- "version": "1.5.101",
5
+ "version": "1.5.102",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -146,12 +146,12 @@ export const compareReturns = (a, b) =>
146
146
  isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
147
147
  export const compareTypeWithReturn = (a, b) =>
148
148
  isAnyType(a) || isAnyReturn(b) || a[TYPE_PROP][0] === b[RETURNS][0]
149
- const checkPredicateName = (exp, rest, errors) => {
149
+ const checkPredicateName = (exp, rest) => {
150
150
  if (getSuffix(rest[0][VALUE]) === PREDICATE_SUFFIX) {
151
151
  const last = rest.at(-1)
152
152
  if (isLeaf(last)) {
153
153
  if (last[TYPE] === ATOM && last[VALUE] !== TRUE && last[VALUE] !== FALSE)
154
- errors.add(
154
+ throw new TypeError(
155
155
  `Assigning predicate (ending in ?) variable (${
156
156
  rest[0][VALUE]
157
157
  }) to an (${
@@ -163,7 +163,7 @@ const checkPredicateName = (exp, rest, errors) => {
163
163
  getSuffix(last[VALUE]) !== PREDICATE_SUFFIX &&
164
164
  !PREDICATES_OUTPUT_SET.has(last[VALUE])
165
165
  )
166
- errors.add(
166
+ throw new TypeError(
167
167
  `Assigning predicate (ending in ?) variable (${
168
168
  rest[0][VALUE]
169
169
  }) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
@@ -181,7 +181,7 @@ const checkPredicateName = (exp, rest, errors) => {
181
181
  getSuffix(application[VALUE]) !== PREDICATE_SUFFIX &&
182
182
  !PREDICATES_OUTPUT_SET.has(application[VALUE])
183
183
  )
184
- errors.add(
184
+ throw new TypeError(
185
185
  `Assigning predicate (ending in ?) variable (${
186
186
  application[VALUE]
187
187
  }) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
@@ -193,21 +193,17 @@ const checkPredicateName = (exp, rest, errors) => {
193
193
  }
194
194
  }
195
195
  }
196
- const checkPredicateNameDeep = (name, exp, rest, returns, errors) => {
196
+ const checkPredicateNameDeep = (name, exp, rest, returns) => {
197
197
  if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
198
198
  const fn = rest.at(-1).at(-1).at(-1)
199
- checkPredicateName(
200
- exp,
201
- [
202
- [WORD, name],
203
- isLeaf(fn)
204
- ? fn // when apply is a word (let x? (lambda (apply [] array:empty!)))
205
- : drillReturnType(fn, (r) => r[VALUE] === KEYWORDS.CALL_FUNCTION) // when apply is an annonymous lambda // (let fn? (lambda x (apply x (lambda x (array:empty! [])))))
206
- ],
207
- errors
208
- )
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
+ ])
209
205
  } else {
210
- checkPredicateName(exp, [[WORD, name], returns], errors)
206
+ checkPredicateName(exp, [[WORD, name], returns])
211
207
  }
212
208
  }
213
209
  const fillUknownArgs = (n) =>
@@ -238,9 +234,8 @@ const withScope = (name, scope) => {
238
234
  const chain = getScopeNames(scope)
239
235
  return `${chain.length === 1 ? '; ' : ''}${chain.join(' ')} ${name}`
240
236
  }
241
- const retry = (stats, stack, errors, cb) => {
237
+ const retry = (stats, stack, cb) => {
242
238
  if (
243
- errors.size === 0 &&
244
239
  (isUnknownNotAnyType(stats) || isUnknownNotAnyReturn(stats)) &&
245
240
  stats.retried < MAX_RETRY_DEFINITION
246
241
  ) {
@@ -248,8 +243,8 @@ const retry = (stats, stack, errors, cb) => {
248
243
  stack.unshift(() => cb())
249
244
  }
250
245
  }
251
- const retryArgs = (stats, stack, errors, cb) => {
252
- if (errors.size === 0 && stats.counter < MAX_ARGUMENT_RETRY) {
246
+ const retryArgs = (stats, stack, cb) => {
247
+ if (stats.counter < MAX_ARGUMENT_RETRY) {
253
248
  stats.counter++
254
249
  stack.unshift(cb)
255
250
  }
@@ -291,18 +286,10 @@ const resolveApplyAssigment = (re, name, env) => {
291
286
  }
292
287
  }
293
288
  }
294
- const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
289
+ const resolveIfAssigment = ({ rem, name, env, exp, prop }) => {
295
290
  const re = rem.slice(2)
296
- checkPredicateName(
297
- exp,
298
- [[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]],
299
- errors
300
- )
301
- checkPredicateName(
302
- exp,
303
- [[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]],
304
- errors
305
- )
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]])
306
293
  if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM)
307
294
  // ATOM ASSIGMENT
308
295
  setPropToAtom(env[name][STATS], prop)
@@ -328,21 +315,13 @@ const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
328
315
  // ASSIGMENT
329
316
  setPropRef(env[name][STATS], prop, env[re[1][VALUE]][STATS])
330
317
  }
331
- const resolveCondition = ({ rem, name, env, exp, errors }) => {
318
+ const resolveCondition = ({ rem, name, env, exp }) => {
332
319
  const ret = rem[0]
333
320
  const re = rem.slice(2)
334
321
  resolveApplyAssigment(re, name, env)
335
322
  const ref = env[name]
336
- checkPredicateName(
337
- exp,
338
- [[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]],
339
- errors
340
- )
341
- checkPredicateName(
342
- exp,
343
- [[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]],
344
- errors
345
- )
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]])
346
325
  switch (ret[VALUE]) {
347
326
  case KEYWORDS.IF:
348
327
  ifExpression({ re, env, ref })
@@ -356,27 +335,18 @@ const resolveCondition = ({ rem, name, env, exp, errors }) => {
356
335
  break
357
336
  }
358
337
  }
359
- const resolveRetunType = ({
360
- returns,
361
- rem,
362
- stack,
363
- prop,
364
- exp,
365
- name,
366
- errors,
367
- env
368
- }) => {
338
+ const resolveRetunType = ({ returns, rem, stack, prop, exp, name, env }) => {
369
339
  if (returns[TYPE] === ATOM) {
370
340
  // ATOM ASSIGMENT
371
341
  setPropToAtom(env[name][STATS], prop)
372
- checkPredicateName(exp, [[WORD, name], returns], errors)
342
+ checkPredicateName(exp, [[WORD, name], returns])
373
343
  } else {
374
344
  switch (returns[VALUE]) {
375
345
  case KEYWORDS.IF:
376
- resolveIfAssigment({ rem, name, env, exp, errors, prop })
346
+ resolveIfAssigment({ rem, name, env, exp, prop })
377
347
  break
378
348
  default:
379
- checkPredicateNameDeep(name, exp, exp.slice(1), returns, errors)
349
+ checkPredicateNameDeep(name, exp, exp.slice(1), returns)
380
350
  if (!env[returns[VALUE]]) return false
381
351
  else if (getType(env[returns[VALUE]][STATS]) === APPLY) {
382
352
  if (returns[TYPE] === WORD) setReturnToAbbstraction(env[name][STATS])
@@ -401,7 +371,7 @@ const resolveRetunType = ({
401
371
  }
402
372
  return true
403
373
  }
404
- const checkReturnType = ({ exp, stack, name, errors, env }) => {
374
+ const checkReturnType = ({ exp, stack, name, env }) => {
405
375
  const last = exp.at(-1).at(-1)
406
376
  const body = hasApplyLambdaBlock(last) ? last.at(-1).at(-1) : last
407
377
  const rem = hasBlock(body) ? body.at(-1) : body
@@ -412,7 +382,6 @@ const checkReturnType = ({ exp, stack, name, errors, env }) => {
412
382
  prop: RETURNS,
413
383
  exp,
414
384
  name,
415
- errors,
416
385
  env,
417
386
  stack
418
387
  })
@@ -420,7 +389,6 @@ const checkReturnType = ({ exp, stack, name, errors, env }) => {
420
389
  export const typeCheck = (ast, error = true) => {
421
390
  let scopeIndex = 0
422
391
  const root = structuredClone(SPECIAL_FORM_TYPES)
423
- const errors = new Set()
424
392
  const Types = new Map()
425
393
  const stack = []
426
394
  const check = (exp, env, scope) => {
@@ -434,14 +402,14 @@ export const typeCheck = (ast, error = true) => {
434
402
  switch (first[TYPE]) {
435
403
  case WORD:
436
404
  if (!isSpecial)
437
- stack.push(
438
- () =>
439
- // Figure out how to determine if varible is define after it's used
440
- env[first[VALUE]] === undefined &&
441
- 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(
442
409
  `Trying to access undefined variable ${first[VALUE]} (check #11)`
443
410
  )
444
- )
411
+ }
412
+ })
445
413
  break
446
414
  case ATOM:
447
415
  break
@@ -483,30 +451,28 @@ export const typeCheck = (ast, error = true) => {
483
451
  stack,
484
452
  exp,
485
453
  env,
486
- name,
487
- errors
454
+ name
488
455
  }) ||
489
456
  isUnknownReturn(env[name][STATS])
490
457
  ) {
491
- retry(env[name][STATS], stack, errors, () => {
458
+ retry(env[name][STATS], stack, () => {
492
459
  checkReturnType({
493
460
  stack,
494
461
  exp,
495
462
  env,
496
- name,
497
- errors
463
+ name
498
464
  })
499
465
  check(rightHand, env, exp)
500
466
  })
501
467
  check(rightHand, env, exp)
502
468
  } else check(rightHand, env, exp)
503
469
  } else {
504
- checkPredicateName(exp, rest, errors)
470
+ checkPredicateName(exp, rest)
505
471
  const isLeafNode = isLeaf(rightHand)
506
472
  if (isLeafNode && rightHand[TYPE] === WORD) {
507
473
  // TODO make sure this prevents the assigment all together
508
474
  if (env[rest[1][VALUE]] === undefined)
509
- errors.add(
475
+ throw new TypeError(
510
476
  `Trying to access undefined variable ${rest[1][VALUE]} (check #22)`
511
477
  )
512
478
  // Used to be checkin if it's an assigment to a special form
@@ -555,8 +521,7 @@ export const typeCheck = (ast, error = true) => {
555
521
  prop: TYPE_PROP,
556
522
  exp,
557
523
  env,
558
- name,
559
- errors
524
+ name
560
525
  })
561
526
  }
562
527
  check(rightHand, env, scope)
@@ -574,7 +539,7 @@ export const typeCheck = (ast, error = true) => {
574
539
  const param = params[i]
575
540
  // TODO move this somewhere else
576
541
  if (!isLeaf(param))
577
- errors.add(
542
+ throw new TypeError(
578
543
  `Invalid body for (${
579
544
  first[VALUE]
580
545
  }) if it takes more than one expression it must be wrapped in a (${
@@ -617,7 +582,6 @@ export const typeCheck = (ast, error = true) => {
617
582
  name: ref[STATS][SIGNATURE],
618
583
  env: copy,
619
584
  exp,
620
- errors,
621
585
  stack
622
586
  })
623
587
  break
@@ -657,7 +621,7 @@ export const typeCheck = (ast, error = true) => {
657
621
  default:
658
622
  stack.push(() => {
659
623
  if (!isSpecial && env[first[VALUE]] === undefined)
660
- errors.add(
624
+ throw new TypeError(
661
625
  `Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
662
626
  )
663
627
  else if (
@@ -665,7 +629,7 @@ export const typeCheck = (ast, error = true) => {
665
629
  env[first[VALUE]][STATS][ARG_COUNT] !== VARIADIC &&
666
630
  env[first[VALUE]][STATS][ARG_COUNT] !== rest.length
667
631
  )
668
- errors.add(
632
+ throw new TypeError(
669
633
  `Incorrect number of arguments for (${
670
634
  first[VALUE]
671
635
  }). Expected (= ${
@@ -675,7 +639,7 @@ export const typeCheck = (ast, error = true) => {
675
639
  else {
676
640
  if (first[TYPE] === APPLY && !isSpecial) {
677
641
  if (getType(env[first[VALUE]][STATS]) === ATOM)
678
- errors.add(
642
+ throw new TypeError(
679
643
  `(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
680
644
  exp
681
645
  )}) (check #12)`
@@ -746,7 +710,7 @@ export const typeCheck = (ast, error = true) => {
746
710
  const fnName = rest[i].at(-1)[VALUE]
747
711
  const fn = env[fnName]
748
712
  if (fn && getReturn(fn[STATS]) !== ATOM)
749
- errors.add(
713
+ throw new TypeError(
750
714
  `Incorrect type of argument (${i}) for (${
751
715
  first[VALUE]
752
716
  }). Expected (${toTypeNames(
@@ -761,7 +725,7 @@ export const typeCheck = (ast, error = true) => {
761
725
  const returns = isLeaf(rem) ? rem : rem[0]
762
726
  if (returns[TYPE] === ATOM) {
763
727
  if (MAIN_TYPE !== ATOM)
764
- errors.add(
728
+ throw new TypeError(
765
729
  `Incorrect type of argument ${i} for (${
766
730
  first[VALUE]
767
731
  }). Expected (${toTypeNames(
@@ -775,7 +739,7 @@ export const typeCheck = (ast, error = true) => {
775
739
  !isUnknownReturn(env[returns[VALUE]][STATS]) &&
776
740
  getReturn(env[returns[VALUE]][STATS]) !== ATOM
777
741
  )
778
- errors.add(
742
+ throw new TypeError(
779
743
  `Incorrect type of argument ${i} for (${
780
744
  first[VALUE]
781
745
  }). Expected (${toTypeNames(
@@ -798,7 +762,7 @@ export const typeCheck = (ast, error = true) => {
798
762
  env[name][STATS]
799
763
  )
800
764
  )
801
- errors.add(
765
+ throw new TypeError(
802
766
  `Incorrect type of argument (${i}) for special form (${
803
767
  first[VALUE]
804
768
  }). Expected (${toTypeNames(
@@ -838,7 +802,7 @@ export const typeCheck = (ast, error = true) => {
838
802
  env[name][STATS]
839
803
  )
840
804
  )
841
- errors.add(
805
+ throw new TypeError(
842
806
  `Incorrect type of argument (${i}) for special form (${
843
807
  first[VALUE]
844
808
  }). Expected (${toTypeNames(
@@ -856,7 +820,7 @@ export const typeCheck = (ast, error = true) => {
856
820
  rest[i][TYPE] !==
857
821
  expectedArgs[i][STATS][TYPE_PROP][0]
858
822
  )
859
- errors.add(
823
+ throw new TypeError(
860
824
  `Incorrect type of argument (${i}) for special form (${
861
825
  first[VALUE]
862
826
  }). Expected (${toTypeNames(
@@ -883,7 +847,7 @@ export const typeCheck = (ast, error = true) => {
883
847
  !isUnknownType(args[i][STATS]) &&
884
848
  getType(args[i][STATS]) !== ATOM
885
849
  ) {
886
- errors.add(
850
+ throw new TypeError(
887
851
  `Incorrect type of arguments ${i} for (${
888
852
  first[VALUE]
889
853
  }). Expected (${toTypeNames(
@@ -903,7 +867,7 @@ export const typeCheck = (ast, error = true) => {
903
867
  env[rest[i][VALUE]][STATS][ARG_COUNT] !==
904
868
  args[i][STATS][ARG_COUNT]
905
869
  ) {
906
- errors.add(
870
+ throw new TypeError(
907
871
  `Incorrect number of arguments for (${
908
872
  args[i][STATS][SIGNATURE]
909
873
  }) the (lambda) argument of (${
@@ -927,7 +891,7 @@ export const typeCheck = (ast, error = true) => {
927
891
  !isUnknownReturn(actual[STATS]) &&
928
892
  !compareReturns(expected[STATS], actual[STATS])
929
893
  ) {
930
- errors.add(
894
+ throw new TypeError(
931
895
  `Incorrect return type for (${
932
896
  expected[STATS][SIGNATURE]
933
897
  }) the (lambda) argument of (${
@@ -938,8 +902,7 @@ export const typeCheck = (ast, error = true) => {
938
902
  getReturn(actual[STATS])
939
903
  )}) (${stringifyArgs(exp)}) (check #782)`
940
904
  )
941
- } else
942
- retry(actual[STATS], stack, errors, () => match1())
905
+ } else retry(actual[STATS], stack, () => match1())
943
906
  }
944
907
  match1()
945
908
  for (
@@ -956,7 +919,7 @@ export const typeCheck = (ast, error = true) => {
956
919
  !isUnknownType(expected[STATS]) &&
957
920
  !compareTypes(actual[STATS], expected[STATS])
958
921
  )
959
- errors.add(
922
+ throw new TypeError(
960
923
  `Incorrect type for (lambda) (${
961
924
  args[i][STATS][SIGNATURE]
962
925
  }) argument at position (${j}) named as (${
@@ -967,14 +930,7 @@ export const typeCheck = (ast, error = true) => {
967
930
  getType(actual[STATS])
968
931
  )}) (${stringifyArgs(exp)}) (check #781)`
969
932
  )
970
- else
971
- retry(
972
- actual[STATS],
973
- stack,
974
- errors,
975
-
976
- () => match2()
977
- )
933
+ else retry(actual[STATS], stack, () => match2())
978
934
  }
979
935
  match2()
980
936
  }
@@ -987,7 +943,7 @@ export const typeCheck = (ast, error = true) => {
987
943
  !isUnknownType(args[i][STATS]) &&
988
944
  !compareTypes(env[rest[i][VALUE]][STATS], args[i][STATS])
989
945
  ) {
990
- errors.add(
946
+ throw new TypeError(
991
947
  `Incorrect type of arguments ${i} for (${
992
948
  first[VALUE]
993
949
  }). Expected (${toTypeNames(
@@ -997,9 +953,7 @@ export const typeCheck = (ast, error = true) => {
997
953
  )}) (check #30)`
998
954
  )
999
955
  } else if (isUnknownType(args[i][STATS]))
1000
- retry(args[i][STATS], stack, errors, () =>
1001
- check(exp, env, scope)
1002
- )
956
+ retry(args[i][STATS], stack, () => check(exp, env, scope))
1003
957
  else if (
1004
958
  env[rest[i][VALUE]] &&
1005
959
  !isUnknownType(args[i][STATS]) &&
@@ -1016,10 +970,10 @@ export const typeCheck = (ast, error = true) => {
1016
970
  const match = () => {
1017
971
  const actual = env[rest[i][0][VALUE]][STATS]
1018
972
  const expected = args[i][STATS]
1019
- retryArgs(args[i][STATS], stack, errors, () => match())
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 (${
@@ -1091,12 +1045,8 @@ export const typeCheck = (ast, error = true) => {
1091
1045
  )}) (check #779)`
1092
1046
  )
1093
1047
  else
1094
- retry(
1095
- actual[STATS],
1096
- stack,
1097
- errors,
1098
-
1099
- () => match1()
1048
+ retry(actual[STATS], stack, () =>
1049
+ match1()
1100
1050
  )
1101
1051
  }
1102
1052
  match1()
@@ -1118,7 +1068,7 @@ export const typeCheck = (ast, error = true) => {
1118
1068
  expected[STATS]
1119
1069
  )
1120
1070
  )
1121
- errors.add(
1071
+ throw new TypeError(
1122
1072
  `Incorrect type for (lambda) (${
1123
1073
  args[i][STATS][SIGNATURE]
1124
1074
  }) argument at position (${j}) named as (${
@@ -1134,12 +1084,8 @@ export const typeCheck = (ast, error = true) => {
1134
1084
  )}) (check #780)`
1135
1085
  )
1136
1086
  else
1137
- retry(
1138
- actual[STATS],
1139
- stack,
1140
- errors,
1141
-
1142
- () => match2()
1087
+ retry(actual[STATS], stack, () =>
1088
+ match2()
1143
1089
  )
1144
1090
  }
1145
1091
  match2()
@@ -1156,7 +1102,7 @@ export const typeCheck = (ast, error = true) => {
1156
1102
  }
1157
1103
  }
1158
1104
  else if (isUnknownType(expected))
1159
- retry(args[i][STATS], stack, errors, () => match())
1105
+ retry(args[i][STATS], stack, () => match())
1160
1106
  }
1161
1107
  match()
1162
1108
  }
@@ -1168,7 +1114,7 @@ export const typeCheck = (ast, error = true) => {
1168
1114
  const r = rest[i]
1169
1115
  if (isLeaf(r) && r[TYPE] !== ATOM)
1170
1116
  if (env[r[VALUE]] == undefined)
1171
- errors.add(
1117
+ throw new TypeError(
1172
1118
  `(${
1173
1119
  first[VALUE]
1174
1120
  }) is trying to access undefined variable (${
@@ -1185,7 +1131,6 @@ export const typeCheck = (ast, error = true) => {
1185
1131
  const copy = JSON.parse(JSON.stringify(ast))
1186
1132
  check(copy, root, copy)
1187
1133
  while (stack.length) stack.pop()()
1188
- if (error && errors.size) throw new TypeError([...errors.values()].join('\n'))
1189
1134
  return [ast, Types]
1190
1135
  }
1191
1136
  export const type = (ast) => typeCheck(ast)[0]