fez-lisp 1.6.84 → 1.6.87

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.6.84",
5
+ "version": "1.6.87",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -47,7 +47,9 @@ import {
47
47
  NUMBER_SUBTYPE,
48
48
  SubType,
49
49
  GET_ARRAY_INFERENCE_SET,
50
- GENERIC
50
+ GENERIC,
51
+ TYPE_NAME,
52
+ RETURN_NAME
51
53
  } from './types.js'
52
54
  import {
53
55
  Brr,
@@ -58,6 +60,7 @@ import {
58
60
  logExp,
59
61
  stringifyArgs,
60
62
  wrapInApplyLambda,
63
+ wrapInArray,
61
64
  wrapInBlock
62
65
  } from './utils.js'
63
66
 
@@ -110,6 +113,8 @@ export const isGenericReturn = (stats) =>
110
113
  stats[RETURNS].length === 3 && stats[RETURNS][2][0] !== -1
111
114
  export const isGenericType = (stats) =>
112
115
  stats[TYPE_PROP].length === 3 && stats[TYPE_PROP][2][0] !== -1
116
+ export const isGenericProp = (stats, prop) =>
117
+ stats[prop].length === 3 && stats[prop][2][0] !== -1
113
118
 
114
119
  export const isTypeAbstraction = (stats) => stats[TYPE_PROP] === APPLY
115
120
  export const setPropToAtom = (stats, prop) => {
@@ -340,6 +345,69 @@ const isRedefinedInLambda = (env, name, exp) => {
340
345
  return true
341
346
  else return false
342
347
  }
348
+ const getGenericPropNest = (ref, prop) =>
349
+ ref[STATS][prop][0] === COLLECTION
350
+ ? isSubType(ref[STATS][prop][1])
351
+ ? ref[STATS][prop][1].nestedLevels()
352
+ : 0
353
+ : 0
354
+ const getGenericProp = (ref, rem, prop) => {
355
+ const [index, multiplier] = ref[STATS][prop][2]
356
+ const generic = rem.slice(1)[index]
357
+ const nestGeneric = getGenericPropNest(ref, prop)
358
+ return [
359
+ generic,
360
+ isLeaf(generic) ? generic : generic[0],
361
+ nestGeneric,
362
+ multiplier
363
+ ]
364
+ }
365
+ const getGenericReturn = (ref, rem) => getGenericProp(ref, rem, RETURNS)
366
+ const getGenericType = (ref, rem) => getGenericProp(ref, rem, TYPE_PROP)
367
+ const resolveGenericNest = (ref, prop, nestGeneric, multiplier) => {
368
+ const T = isSubType(ref[STATS][prop][1])
369
+ ? ref[STATS][prop][1].types
370
+ : [ref[STATS][prop][0]]
371
+ if (multiplier === -1) {
372
+ if (nestGeneric === 0) {
373
+ if (T.at(-1) === NUMBER || T.at(-1) === BOOLEAN) {
374
+ if (isSubType(ref[STATS][prop][1])) {
375
+ if (ref[STATS][prop][1].types.length === 1) ref[STATS][prop][0] = ATOM
376
+ else {
377
+ ref[STATS][prop][1] = new SubType(
378
+ ref[STATS][prop][1].types.slice(1)
379
+ )
380
+ ref[STATS][prop][0] = COLLECTION
381
+ ref[STATS][prop].length = 2
382
+ }
383
+ } else ref[STATS][prop][0] = ATOM
384
+ }
385
+ } else {
386
+ if (T.length - nestGeneric - 1) {
387
+ for (let i = 0; i < nestGeneric + 1; ++i)
388
+ ref[STATS][prop][1].types.shift()
389
+ ref[STATS][prop].length = 2
390
+ } else {
391
+ if (T.at(-1) === NUMBER || T.at(-1) === BOOLEAN) {
392
+ ref[STATS][prop][0] = ATOM
393
+ ref[STATS][prop][1] = new SubType([T.at(-1)])
394
+ ref[STATS][prop].length = 2
395
+ } else {
396
+ ref[STATS][prop][0] = APPLY
397
+ ref[STATS][prop].length = 1
398
+ }
399
+ }
400
+ }
401
+ } else if (multiplier === 1) {
402
+ const st = new SubType([])
403
+ for (let i = 0; i < nestGeneric; ++i) st.add(COLLECTION)
404
+ if (ref[STATS][prop][0] === COLLECTION) st.add(COLLECTION)
405
+ st.add(...T)
406
+ ref[STATS][prop][0] = COLLECTION
407
+ ref[STATS][prop][1] = st
408
+ }
409
+ }
410
+
343
411
  export const equalReturns = (a, b) =>
344
412
  isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
345
413
  export const equalsTypeWithReturn = (a, b) =>
@@ -470,6 +538,12 @@ const once = (stats, ctx, stack, cb, method = 'prepend') => {
470
538
  stagger(stack, method, ctx, cb)
471
539
  }
472
540
  }
541
+ const doOnce = (stats, ctx, stack, cb, method = 'prepend') => {
542
+ if (!stats.tried) {
543
+ stats.tried = true
544
+ stagger(stack, method, ctx, cb)
545
+ }
546
+ }
473
547
  const retryArgs = (stats, ctx, stack, cb) => {
474
548
  if (stats.counter < MAX_ARGUMENT_RETRY) {
475
549
  stats.counter++
@@ -652,31 +726,29 @@ const resolveGetter = ({ rem, prop, name, env, caller, exp }) => {
652
726
  const rec = resolveGetterRec(rem, env)
653
727
  if (!rec) return true
654
728
  const [times, level, type, types] = resolveGetterRec(rem, env)
655
- const isUnknown = types.at(-1) === UNKNOWN
729
+ const isUnknown =
730
+ types.at(-1) === UNKNOWN || types.at(-1) === COLLECTION
656
731
  if (!isUnknown && times >= level)
657
732
  throw new RangeError(
658
733
  `(${caller}) is trying to access nested structure at level (${level}) which is deeper than it's (${
659
734
  times - 1
660
735
  }) levels at (${stringifyArgs(exp)}) (check #1003)`
661
736
  )
662
- if (times === level - 1) {
737
+ if (times === level - 1)
663
738
  setPropToType(env[name][STATS], prop, {
664
- [TYPE_PROP]: types.length
665
- ? [
666
- type,
667
- new SubType([
668
- types.at(-1) === COLLECTION ? UNKNOWN : types.at(-1)
669
- ])
670
- ]
671
- : [UNKNOWN]
739
+ [TYPE_PROP]:
740
+ types.length && !isUnknown
741
+ ? [type, new SubType([types.at(-1)])]
742
+ : types.at(-1) === COLLECTION
743
+ ? [COLLECTION]
744
+ : [UNKNOWN]
672
745
  })
673
- } else {
746
+ else
674
747
  setPropToType(env[name][STATS], prop, {
675
748
  [TYPE_PROP]: types.length
676
749
  ? [COLLECTION, new SubType(types.slice(times))]
677
750
  : [UNKNOWN]
678
751
  })
679
- }
680
752
  return true
681
753
  }
682
754
  if (
@@ -704,11 +776,10 @@ const resolveGetter = ({ rem, prop, name, env, caller, exp }) => {
704
776
  setPropToReturn(env[name][STATS], prop, {
705
777
  [RETURNS]: [f, new SubType(r)]
706
778
  })
707
- } else if (rightSub.has(APPLY)) {
779
+ } else if (rightSub.has(APPLY))
708
780
  // TODOD: abstractions go here but what can we do with them
709
781
  // perhaps show the signature?
710
782
  setPropToAbstraction(env[name][STATS], prop)
711
- }
712
783
  }
713
784
  break
714
785
  case WORD:
@@ -739,11 +810,10 @@ const resolveGetter = ({ rem, prop, name, env, caller, exp }) => {
739
810
  setPropToType(env[name][STATS], prop, {
740
811
  [TYPE_PROP]: [f, new SubType(r)]
741
812
  })
742
- } else if (rightSub.has(APPLY)) {
813
+ } else if (rightSub.has(APPLY))
743
814
  // TODOD: abstractions go here but what can we do with them
744
815
  // perhaps show the signature?
745
816
  setPropToAbstraction(env[name][STATS], prop)
746
- }
747
817
  }
748
818
  }
749
819
  break
@@ -874,6 +944,8 @@ const resolveSetter = (first, rest, env, stack) => {
874
944
  // )
875
945
  }
876
946
  }
947
+ const countLevels = (arr, lvl = -1) =>
948
+ Array.isArray(arr[0]) ? countLevels(arr[0], ++lvl) : lvl
877
949
  const initArrayTypeRec = ({ rem, env }) =>
878
950
  rem.slice(1).map((x) => {
879
951
  if (isLeaf(x))
@@ -906,14 +978,15 @@ const initArrayTypeRec = ({ rem, env }) =>
906
978
  })
907
979
  const initArrayType = ({ rem, env }) => {
908
980
  const ret = initArrayTypeRec({ rem, env })
909
- const known = ret.find((x) => x[0] !== ANY && x[0] !== UNKNOWN)
910
- const isCollection = ret.length && ret[0] && ret[0][0] === COLLECTION
981
+ const flat = ret.flat(Infinity).filter((x) => !isSubType(x))
982
+ const subTypes = ret.flat(Infinity).filter((x) => isSubType(x))
983
+ const known = flat.find((x) => x !== ANY && x !== UNKNOWN)
984
+ const isCollection = ret.length && Array.isArray(ret[0])
911
985
  if (
912
986
  known &&
913
987
  ret.length &&
914
- (Array.isArray(known[0])
915
- ? !ret.some((x) => known[0][0] !== x[0][0])
916
- : !ret.some((x) => known[0] !== x[0]))
988
+ !flat.some((x) => known !== x) &&
989
+ !subTypes.some((x) => subTypes[0].types[0] !== x.types[0])
917
990
  ) {
918
991
  if (Array.isArray(ret[0][0])) {
919
992
  let head = ret[0][0]
@@ -934,7 +1007,7 @@ const initArrayType = ({ rem, env }) => {
934
1007
  [RETURNS]: [
935
1008
  COLLECTION,
936
1009
  isCollection
937
- ? new SubType(isSubType(sub) ? [COLLECTION, ...sub] : [COLLECTION])
1010
+ ? new SubType(isSubType(sub) ? [...sub] : [COLLECTION])
938
1011
  : new SubType(isSubType(sub) ? [...sub] : [main])
939
1012
  ]
940
1013
  }
@@ -944,7 +1017,10 @@ const initArrayType = ({ rem, env }) => {
944
1017
  [RETURNS]: [
945
1018
  COLLECTION,
946
1019
  isCollection
947
- ? new SubType([COLLECTION, UNKNOWN])
1020
+ ? new SubType([
1021
+ ...Array.from({ length: countLevels(ret) }).fill(COLLECTION),
1022
+ UNKNOWN
1023
+ ])
948
1024
  : new SubType([UNKNOWN])
949
1025
  ]
950
1026
  }
@@ -1021,18 +1097,9 @@ const resolveReturnType = ({
1021
1097
  // Here is upon application to store the result in the variable
1022
1098
  if (isGenericReturn(env[returns[VALUE]][STATS])) {
1023
1099
  // env[name][STATS][TYPE_PROP] =
1024
- const [index, multiplier] = env[returns[VALUE]][STATS][RETURNS][2]
1025
- const genericReturn = rem.slice(1)[index]
1026
- const nestGeneric =
1027
- env[returns[VALUE]][STATS][RETURNS][0] === COLLECTION
1028
- ? isSubType(env[returns[VALUE]][STATS][RETURNS][1])
1029
- ? env[returns[VALUE]][STATS][RETURNS][1].nestedLevels()
1030
- : 0
1031
- : 0
1032
1100
 
1033
- const head = isLeaf(genericReturn)
1034
- ? genericReturn
1035
- : genericReturn[0]
1101
+ const [genericReturn, head, nestGeneric, multiplier] =
1102
+ getGenericReturn(env[returns[VALUE]], rem)
1036
1103
 
1037
1104
  switch (head[TYPE]) {
1038
1105
  case ATOM:
@@ -1100,47 +1167,9 @@ const resolveReturnType = ({
1100
1167
  setTypeToReturn(env[name][STATS], env[head[VALUE]][STATS])
1101
1168
  break
1102
1169
  }
1170
+
1103
1171
  if (env[returns[VALUE]][STATS][RETURNS][0] === COLLECTION) {
1104
- const T = isSubType(env[name][STATS][prop][1])
1105
- ? env[name][STATS][prop][1].types
1106
- : [env[name][STATS][prop][0]]
1107
- if (multiplier === -1) {
1108
- if (nestGeneric === 0) {
1109
- if (T.at(-1) === NUMBER || T.at(-1) === BOOLEAN) {
1110
- if (isSubType(env[name][STATS][prop][1])) {
1111
- if (env[name][STATS][prop][1].types.length === 1)
1112
- env[name][STATS][prop][0] = ATOM
1113
- else {
1114
- env[name][STATS][prop][1] = new SubType(
1115
- env[name][STATS][prop][1].types.slice(1)
1116
- )
1117
- env[name][STATS][prop][0] = COLLECTION
1118
- }
1119
- } else env[name][STATS][prop][0] = ATOM
1120
- }
1121
- } else {
1122
- if (T.length - nestGeneric - 1) {
1123
- for (let i = 0; i < nestGeneric + 1; ++i)
1124
- env[name][STATS][prop][1].types.shift()
1125
- } else {
1126
- if (T.at(-1) === NUMBER || T.at(-1) === BOOLEAN) {
1127
- env[name][STATS][prop][0] = ATOM
1128
- env[name][STATS][prop][1] = new SubType([T.at(-1)])
1129
- } else {
1130
- env[name][STATS][prop][0] = APPLY
1131
- env[name][STATS][prop].length = 1
1132
- }
1133
- }
1134
- }
1135
- } else {
1136
- const st = new SubType([])
1137
- for (let i = 0; i < nestGeneric; ++i) st.add(COLLECTION)
1138
- if (env[name][STATS][prop][0] === COLLECTION)
1139
- st.add(COLLECTION)
1140
- st.add(...T)
1141
- env[name][STATS][prop][0] = COLLECTION
1142
- env[name][STATS][prop][1] = st
1143
- }
1172
+ resolveGenericNest(env[name], prop, nestGeneric, multiplier)
1144
1173
  }
1145
1174
  }
1146
1175
  if (isUnknownType(env[name][STATS]))
@@ -1262,6 +1291,8 @@ export const typeCheck = (
1262
1291
  const match1 = () => {
1263
1292
  const actual = local[lambdaName]
1264
1293
  const expected = args[i]
1294
+ if (isGenericReturn(expected[STATS])) return
1295
+
1265
1296
  // if (
1266
1297
  // isGenericReturn(args[i][STATS]) &&
1267
1298
  // !isUnknownReturn(actual[STATS]) &&
@@ -1312,6 +1343,7 @@ export const typeCheck = (
1312
1343
  for (let j = 0; j < args[i][STATS][ARGUMENTS].length; ++j) {
1313
1344
  const actual = local[lambdaName][STATS][ARGUMENTS][j]
1314
1345
  const expected = args[i][STATS][ARGUMENTS][j]
1346
+ if (isGenericType(expected[STATS])) continue
1315
1347
  // TODO: after refactoring the generic nesting and unnesting logic
1316
1348
  // apply it here to judge lambda arguments based on the signature
1317
1349
  // if (
@@ -1322,7 +1354,6 @@ export const typeCheck = (
1322
1354
  // expected[STATS][TYPE_PROP] = actual[STATS][TYPE_PROP]
1323
1355
  // return
1324
1356
  // }
1325
-
1326
1357
  if (
1327
1358
  !isUnknownType(actual[STATS]) &&
1328
1359
  !isUnknownType(expected[STATS]) &&
@@ -1855,7 +1886,6 @@ export const typeCheck = (
1855
1886
  }
1856
1887
  // also type of arg
1857
1888
  const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
1858
- const generics = Array.from(args).fill(null)
1859
1889
  for (let i = 0; i < args.length; ++i) {
1860
1890
  // type check
1861
1891
  // TODO get rof pred type
@@ -1959,8 +1989,6 @@ export const typeCheck = (
1959
1989
  )}) (${stringifyArgs(exp)}) (check #203)`
1960
1990
  )
1961
1991
  }
1962
- if (isGenericType(args[i][STATS]))
1963
- generics[i] = [ATOM]
1964
1992
  break
1965
1993
  case APPLY:
1966
1994
  {
@@ -2030,12 +2058,6 @@ export const typeCheck = (
2030
2058
  setTypeRef(env[name][STATS], args[i][STATS])
2031
2059
  else setStatsRef(env[rest[i][VALUE]], args[i])
2032
2060
  }
2033
- if (
2034
- isGenericType(args[i][STATS]) &&
2035
- !isUnknownNotAnyType(env[name][STATS])
2036
- ) {
2037
- generics[i] = env[name][STATS][TYPE_PROP]
2038
- }
2039
2061
  }
2040
2062
  if (isUnknownType(args[i][STATS])) {
2041
2063
  retry(args[i][STATS], [first, env], stack, () =>
@@ -2081,46 +2103,162 @@ export const typeCheck = (
2081
2103
  break
2082
2104
  }
2083
2105
  match({ rest, args, i, env, scope, exp })
2084
-
2085
- if (
2086
- isGenericType(args[i][STATS]) &&
2087
- !isUnknownNotAnyReturn(env[name][STATS])
2088
- )
2089
- generics[i] = env[name][STATS][RETURNS]
2090
2106
  }
2091
2107
  }
2092
2108
  }
2093
- if (generics.some((x) => x !== null && x[0] !== UNKNOWN)) {
2109
+ // GENERICS CODE START
2110
+ if (
2111
+ first[VALUE][0] !== PLACEHOLDER &&
2112
+ env[first[VALUE]][STATS].source &&
2113
+ env[first[VALUE]][STATS][ARGUMENTS].length &&
2114
+ env[first[VALUE]][STATS][ARGUMENTS].some(
2115
+ (x) => isGenericType(x[STATS]) || isGenericReturn(x[STATS])
2116
+ )
2117
+ ) {
2118
+ const rec = (ref) => {
2119
+ if (isGenericReturn(ref[STATS])) {
2120
+ const [index, multiplier] = ref[STATS][RETURNS][2]
2121
+ const desiredTypeIndex = env[first[VALUE]][STATS][
2122
+ ARGUMENTS
2123
+ ].findIndex(
2124
+ (x) => x[STATS][TYPE_NAME] === ref[STATS][RETURN_NAME]
2125
+ )
2126
+ const isCollection = ref[STATS][RETURNS][0] === COLLECTION
2127
+ if (desiredTypeIndex !== -1) {
2128
+ const desiredType = isLeaf(rest[desiredTypeIndex])
2129
+ ? rest[desiredTypeIndex]
2130
+ : rest[desiredTypeIndex][0]
2131
+ switch (desiredType[TYPE]) {
2132
+ case ATOM:
2133
+ ref[STATS][RETURNS] = [ATOM, NUMBER_SUBTYPE()]
2134
+ break
2135
+ case WORD:
2136
+ ref[STATS][RETURNS][0] =
2137
+ env[desiredType[VALUE]][STATS][TYPE_PROP][0]
2138
+ ref[STATS][RETURNS][1] =
2139
+ env[desiredType[VALUE]][STATS][TYPE_PROP][1]
2140
+ break
2141
+ case APPLY:
2142
+ switch (desiredType[VALUE]) {
2143
+ case KEYWORDS.CREATE_ARRAY:
2144
+ ref[STATS][RETURNS] = initArrayType({
2145
+ rem: rest[desiredTypeIndex],
2146
+ env
2147
+ })[RETURNS]
2148
+ break
2149
+ default:
2150
+ ref[STATS][RETURNS] =
2151
+ env[desiredType[VALUE]][STATS][RETURNS]
2152
+ break
2153
+ }
2154
+ break
2155
+ default:
2156
+ break
2157
+ }
2158
+ if (isCollection) {
2159
+ const nest = getGenericPropNest(
2160
+ env[desiredType[VALUE]],
2161
+ TYPE_PROP
2162
+ )
2163
+ resolveGenericNest(ref, RETURNS, nest, multiplier)
2164
+ }
2165
+ ref[STATS][RETURNS].length = 2
2166
+ }
2167
+ }
2168
+ const args = ref[STATS][ARGUMENTS]
2169
+ for (const expected of args) {
2170
+ if (isGenericType(expected[STATS])) {
2171
+ const [index, multiplier] =
2172
+ expected[STATS][TYPE_PROP][2]
2173
+ const desiredTypeIndex = env[first[VALUE]][STATS][
2174
+ ARGUMENTS
2175
+ ].findIndex(
2176
+ (x) =>
2177
+ x[STATS][TYPE_NAME] === expected[STATS][TYPE_NAME]
2178
+ )
2179
+ if (desiredTypeIndex !== -1) {
2180
+ const desiredType = isLeaf(rest[desiredTypeIndex])
2181
+ ? rest[desiredTypeIndex]
2182
+ : rest[desiredTypeIndex][0]
2183
+
2184
+ switch (desiredType[TYPE]) {
2185
+ case ATOM:
2186
+ expected[STATS][TYPE_PROP] = [
2187
+ ATOM,
2188
+ NUMBER_SUBTYPE()
2189
+ ]
2190
+ break
2191
+ case WORD:
2192
+ expected[STATS][TYPE_PROP][0] =
2193
+ env[desiredType[VALUE]][STATS][TYPE_PROP][0]
2194
+ expected[STATS][TYPE_PROP][1] =
2195
+ env[desiredType[VALUE]][STATS][TYPE_PROP][1]
2196
+ break
2197
+ case APPLY:
2198
+ switch (desiredType[VALUE]) {
2199
+ case KEYWORDS.CREATE_ARRAY:
2200
+ expected[STATS][TYPE_PROP] = initArrayType({
2201
+ rem: rest[desiredTypeIndex],
2202
+ env
2203
+ })[RETURNS]
2204
+ break
2205
+ default:
2206
+ expected[STATS][ARG_COUNT] =
2207
+ env[desiredType[VALUE]][STATS][ARG_COUNT]
2208
+ expected[STATS][TYPE_PROP][0] =
2209
+ env[desiredType[VALUE]][STATS][RETURNS][0]
2210
+ expected[STATS][TYPE_PROP][1] =
2211
+ env[desiredType[VALUE]][STATS][RETURNS][1]
2212
+ break
2213
+ }
2214
+ break
2215
+ default:
2216
+ break
2217
+ }
2218
+ if (expected[STATS][TYPE_PROP][0] === COLLECTION) {
2219
+ const nest = getGenericPropNest(
2220
+ env[desiredType[VALUE]],
2221
+ TYPE_PROP
2222
+ )
2223
+
2224
+ resolveGenericNest(
2225
+ expected,
2226
+ TYPE_PROP,
2227
+ nest,
2228
+ multiplier === 1 ? 0 : multiplier
2229
+ )
2230
+ }
2231
+ expected[STATS][TYPE_PROP].length = 2
2232
+ }
2233
+ }
2234
+ if (expected[STATS][ARGUMENTS].length) rec(expected)
2235
+ }
2236
+ }
2094
2237
  const copy = Object.create(env)
2095
2238
  const newName = `${PLACEHOLDER}${first[VALUE]}`
2096
- // copy[newName] = structuredClone(copy[first[VALUE]])
2239
+ copy[newName] = null
2097
2240
  copy[newName] = {
2098
2241
  [STATS]: structuredClone(env[first[VALUE]][STATS])
2099
2242
  }
2100
- for (let i = 0; i < generics.length; ++i) {
2101
- if (!generics[i]) continue
2102
- copy[newName][STATS][ARGUMENTS][i] = {
2103
- [STATS]: {
2104
- [ARG_COUNT]: VARIADIC,
2105
- [ARGUMENTS]: [],
2106
- [TYPE_PROP]: generics[i],
2107
- [RETURNS]: generics[i]
2108
- }
2109
- }
2110
- }
2243
+ copy[newName][STATS][SIGNATURE] = newName
2244
+
2245
+ rec(copy[newName])
2246
+
2111
2247
  const cexp = structuredClone(exp)
2112
2248
  copy[newName][STATS].source = structuredClone(
2113
2249
  copy[newName][STATS].source
2114
2250
  )
2115
2251
  cexp[0][VALUE] = newName
2116
2252
  copy[newName][STATS].source[1][VALUE] = newName
2117
- once(copy[newName][STATS], exp, stack, () => {
2253
+
2254
+ doOnce(copy[newName][STATS], cexp, stack, () => {
2118
2255
  check(
2119
- wrapInBlock([copy[newName][STATS].source, cexp]),
2256
+ wrapInArray([copy[newName][STATS].source, cexp]),
2120
2257
  copy,
2121
2258
  scope
2122
2259
  )
2123
2260
  })
2261
+ // GENERICS END END
2124
2262
  return
2125
2263
  }
2126
2264
  }
package/src/types.js CHANGED
@@ -23,6 +23,8 @@ export const RETURNS = 'returns'
23
23
  export const SCOPE_NAME = '__scope__'
24
24
  export const TYPE_PROP = 'type'
25
25
  export const SIGNATURE = 'name'
26
+ export const TYPE_NAME = 'type_name'
27
+ export const RETURN_NAME = 'return_name'
26
28
  export const UNBOUND_VARIABLE = '__unbound__'
27
29
  export const UNKNOWN = -1
28
30
  export const COLLECTION = 3
@@ -1508,6 +1510,8 @@ export const toArgType = (A, i) => {
1508
1510
  [IS_ARGUMENT]: true,
1509
1511
  [SIGNATURE]: PLACEHOLDER,
1510
1512
  [TYPE_PROP]: [APPLY],
1513
+ [TYPE_NAME]: PLACEHOLDER,
1514
+ [RETURN_NAME]: returns[VALUE].replaceAll('[', '').replaceAll(']', ''),
1511
1515
  [RETURNS]: toTypeCodes(returns[VALUE], i),
1512
1516
  [ARGUMENTS]: args.map(toArgType).flat(1),
1513
1517
  [ARG_COUNT]: args.length
@@ -1519,7 +1523,8 @@ export const toArgType = (A, i) => {
1519
1523
  argIndex: i,
1520
1524
  retried: Infinity,
1521
1525
  [IS_ARGUMENT]: true,
1522
- [SIGNATURE]: arg[VALUE].replaceAll('[', '').replaceAll(']', ''),
1526
+ [SIGNATURE]: PLACEHOLDER,
1527
+ [TYPE_NAME]: arg[VALUE].replaceAll('[', '').replaceAll(']', ''),
1523
1528
  [TYPE_PROP]: toTypeCodes(arg[VALUE], i),
1524
1529
  [RETURNS]: toTypeCodes(arg[VALUE], i),
1525
1530
  [ARGUMENTS]: [],
@@ -1539,6 +1544,8 @@ export const fromSourceToType = (T) => {
1539
1544
  retried: Infinity,
1540
1545
  [TYPE_PROP]: [APPLY],
1541
1546
  [SIGNATURE]: name,
1547
+ [TYPE_NAME]: name,
1548
+ [RETURN_NAME]: returns[VALUE].replaceAll('[', '').replaceAll(']', ''),
1542
1549
  [ARG_COUNT]: args.length,
1543
1550
  [ARGUMENTS]: args.map(toArgType).flat(1),
1544
1551
  [RETURNS]: toTypeCodes(
package/src/utils.js CHANGED
@@ -297,6 +297,7 @@ export const dfs = (tree, callback) => {
297
297
  if (!isLeaf(tree)) for (const leaf of tree) dfs(leaf)
298
298
  else callback(tree)
299
299
  }
300
+ export const wrapInArray = (ast) => [[APPLY, KEYWORDS.CREATE_ARRAY], ...ast]
300
301
  export const wrapInBlock = (ast) => [
301
302
  [APPLY, KEYWORDS.CALL_FUNCTION],
302
303
  [
@@ -389,63 +390,63 @@ export const init = () => {
389
390
  // console.log('Added file types.lisp in src')
390
391
  writeFileSync(
391
392
  'index.js',
392
- `import { compile, enhance, parse, LISP, UTILS, verify } from '../index.js'
393
- import { readFileSync, writeFileSync } from 'fs'
394
- export const dev = (source, types) => {
395
- try {
396
- const parsed = parse(source)
397
- const { evaluated, type, error } = UTILS.debug(parsed, true, types)
398
- if (error == null) {
399
- if (type) {
400
- UTILS.logType(type)
401
- }
402
- UTILS.logResult(LISP.serialise(evaluated))
403
- } else UTILS.logError(error.message)
404
- } catch (error) {
405
- UTILS.logError(error.message)
406
- }
407
- }
408
- export const run = (source) => {
409
- try {
410
- const parsed = parse(source)
411
- const { evaluated, error } = UTILS.debug(parsed, false)
412
- if (error == null) {
413
- UTILS.logResult(LISP.serialise(evaluated))
414
- } else UTILS.logError(error.message)
415
- } catch (error) {
416
- UTILS.logError(error.message)
417
- }
418
- }
419
- export const check = (source, types) => {
420
- try {
421
- const parsed = parse(source)
422
- const error = verify(parsed, types)
423
- if (error != null) UTILS.logError(error)
424
- } catch (error) {
425
- UTILS.logError(error.message)
426
- }
393
+ `import { compile, enhance, parse, LISP, UTILS, verify } from 'fez-lisp'
394
+ import { readFileSync, writeFileSync } from 'fs'
395
+ export const dev = (source, types) => {
396
+ try {
397
+ const parsed = parse(source)
398
+ const { evaluated, type, error } = UTILS.debug(parsed, true, types)
399
+ if (error == null) {
400
+ if (type) {
401
+ UTILS.logType(type)
427
402
  }
428
- export const comp = (source) => compile(enhance(parse(source)))
429
- const file = readFileSync('./src/main.lisp', 'utf-8')
430
- const [src, typ] = UTILS.extractTypes(file)
431
- switch (process.argv[2]) {
432
- case 'check':
433
- check(src, typ)
434
- break
435
- case 'run':
436
- run(src, typ)
437
- break
438
- case 'comp':
439
- writeFileSync(
440
- './src/main.js',
441
- 'var _ = ' + comp(src) + '; console.log(_)'
442
- )
443
- break
444
- case 'dev':
445
- default:
446
- dev(src, typ)
447
- break
448
- }`
403
+ UTILS.logResult(LISP.serialise(evaluated))
404
+ } else UTILS.logError(error.message)
405
+ } catch (error) {
406
+ UTILS.logError(error.message)
407
+ }
408
+ }
409
+ export const run = (source) => {
410
+ try {
411
+ const parsed = parse(source)
412
+ const { evaluated, error } = UTILS.debug(parsed, false)
413
+ if (error == null) {
414
+ UTILS.logResult(LISP.serialise(evaluated))
415
+ } else UTILS.logError(error.message)
416
+ } catch (error) {
417
+ UTILS.logError(error.message)
418
+ }
419
+ }
420
+ export const check = (source, types) => {
421
+ try {
422
+ const parsed = parse(source)
423
+ const error = verify(parsed, types)
424
+ if (error != null) UTILS.logError(error)
425
+ } catch (error) {
426
+ UTILS.logError(error.message)
427
+ }
428
+ }
429
+ export const comp = (source) => compile(enhance(parse(source)))
430
+ const file = readFileSync('./src/main.lisp', 'utf-8')
431
+ const [src, typ] = UTILS.extractTypes(file)
432
+ switch (process.argv[2]) {
433
+ case 'check':
434
+ check(src, typ)
435
+ break
436
+ case 'run':
437
+ run(src, typ)
438
+ break
439
+ case 'comp':
440
+ writeFileSync(
441
+ './src/main.js',
442
+ 'var _ = ' + comp(src) + '; console.log(_)'
443
+ )
444
+ break
445
+ case 'dev':
446
+ default:
447
+ dev(src, typ)
448
+ break
449
+ }`
449
450
  )
450
451
  console.log('Added file index.js in root')
451
452
  console.log(