fez-lisp 1.5.160 → 1.5.162

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.160",
5
+ "version": "1.5.162",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -309,7 +309,22 @@ export const equalTypes = (a, b) => {
309
309
  if (!isSameType) return false
310
310
  return true
311
311
  }
312
-
312
+ const isRedifinedInLambda = (env, name, exp) => {
313
+ if (exp.slice(1, -1).some((x) => x[VALUE] === name)) return true
314
+ else if (
315
+ exp
316
+ .at(-1)
317
+ .some(
318
+ (x) =>
319
+ !isLeaf(x) &&
320
+ x[0][TYPE] === APPLY &&
321
+ x[0][VALUE] === KEYWORDS.DEFINE_VARIABLE &&
322
+ x[1][VALUE] === name
323
+ )
324
+ )
325
+ return true
326
+ else return false
327
+ }
313
328
  export const equalReturns = (a, b) =>
314
329
  isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
315
330
  export const equalsTypeWithReturn = (a, b) =>
@@ -336,7 +351,7 @@ const equalSubTypes = (a, b) => {
336
351
  getSubType(a).difference(getSubType(b)).size === 0
337
352
  )
338
353
  }
339
- const eualSubReturn = (a, b) => {
354
+ const equalSubReturns = (a, b) => {
340
355
  return (
341
356
  !hasSubReturn(a) ||
342
357
  !hasSubReturn(b) ||
@@ -523,7 +538,6 @@ const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
523
538
  const alt = isLeaf(re[1]) ? re[1] : re[1][0]
524
539
  const concequent = env[conc[VALUE]]
525
540
  const alternative = env[alt[VALUE]]
526
-
527
541
  // TODO make this more simple - it's so many different things just because types are functions or not
528
542
  // WHY not consiter making return types for everything
529
543
  if (concequent)
@@ -608,7 +622,11 @@ const resolveSetter = (first, rest, env, stack) => {
608
622
  : new Set([UNKNOWN])
609
623
  switch (right[TYPE]) {
610
624
  case ATOM:
611
- if (!currentSubType.has(UNKNOWN) && !currentSubType.has(NUMBER))
625
+ if (
626
+ !currentSubType.has(ANY) &&
627
+ !currentSubType.has(UNKNOWN) &&
628
+ !currentSubType.has(NUMBER)
629
+ )
612
630
  throw new TypeError(
613
631
  `Incorrect array type at (${
614
632
  first[VALUE]
@@ -642,7 +660,7 @@ const resolveSetter = (first, rest, env, stack) => {
642
660
  getSubType(env[right[VALUE]][STATS])
643
661
  )
644
662
  } else
645
- once(env[right[VALUE]][STATS], [first[VALUE], rest], stack, () =>
663
+ retry(env[right[VALUE]][STATS], [first[VALUE], rest], stack, () =>
646
664
  resolveSetter(first, rest, env, stack)
647
665
  )
648
666
  }
@@ -773,9 +791,31 @@ const resolveReturnType = ({
773
791
  check
774
792
  }) => {
775
793
  if (returns[TYPE] === ATOM) setPropToAtom(env[name][STATS], prop)
776
- else {
794
+ else if (returns[TYPE] === WORD) {
795
+ if (env[returns[VALUE]]) {
796
+ if (!isUnknownType(env[returns[VALUE]][STATS]))
797
+ setPropToType(env[name][STATS], prop, env[returns[VALUE]][STATS])
798
+ else
799
+ once(env[name][STATS], exp, stack, () => {
800
+ setPropToTypeRef(env[name][STATS], prop, env[returns[VALUE]][STATS])
801
+ if (isUnknownProp(env[name][STATS], prop)) {
802
+ // TODO: DRY
803
+ const index = env[name][STATS][ARGUMENTS]
804
+ ? env[name][STATS][ARGUMENTS].findIndex(
805
+ (x) => x[STATS][SIGNATURE] === returns[VALUE]
806
+ )
807
+ : -1
808
+ if (index >= 0) {
809
+ setReturnToGeneric(env[name][STATS], index)
810
+ return true
811
+ } else if (!env[returns[VALUE]]) return false
812
+ }
813
+ })
814
+ }
815
+ } else {
777
816
  switch (returns[VALUE]) {
778
817
  case KEYWORDS.CREATE_ARRAY:
818
+ setPropToCollection(env[name][STATS], prop)
779
819
  setPropToSubReturn(env[name][STATS], prop, initArrayType({ rem, env }))
780
820
  break
781
821
  case KEYWORDS.IF:
@@ -800,11 +840,13 @@ const resolveReturnType = ({
800
840
  })
801
841
  })
802
842
  checkPredicateNameDeep(name, exp, exp.slice(1), returns)
843
+ // TODO: DRY
803
844
  const index = env[name][STATS][ARGUMENTS]
804
845
  ? env[name][STATS][ARGUMENTS].findIndex(
805
846
  (x) => x[STATS][SIGNATURE] === returns[VALUE]
806
847
  )
807
848
  : -1
849
+
808
850
  if (index >= 0) {
809
851
  setReturnToGeneric(env[name][STATS], index)
810
852
  return true
@@ -892,7 +934,12 @@ const resolveReturnType = ({
892
934
  env[returns[VALUE]][STATS]
893
935
  )
894
936
  })
895
- else setReturnRef(env[name][STATS], env[returns[VALUE]][STATS])
937
+ else {
938
+ // if (SPECIAL_FORMS_SET.has(returns[VALUE]))
939
+ // setReturn(env[name][STATS], env[returns[VALUE]][STATS])
940
+ // else
941
+ setReturnRef(env[name][STATS], env[returns[VALUE]][STATS])
942
+ }
896
943
  }
897
944
  }
898
945
  }
@@ -1011,7 +1058,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1011
1058
  getReturn(actual[STATS])
1012
1059
  )}) (${stringifyArgs(exp)}) (check #779)`
1013
1060
  )
1014
- else if (!eualSubReturn(expected[STATS], actual[STATS]))
1061
+ else if (!equalSubReturns(expected[STATS], actual[STATS]))
1015
1062
  throw new TypeError(
1016
1063
  `Incorrect return type for (${
1017
1064
  expected[STATS][SIGNATURE]
@@ -1053,7 +1100,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1053
1100
  getType(actual[STATS])
1054
1101
  )}) (${stringifyArgs(exp)}) (check #780)`
1055
1102
  )
1056
- else if (!eualSubReturn(expected[STATS], actual[STATS]))
1103
+ else if (!equalSubReturns(expected[STATS], actual[STATS]))
1057
1104
  throw new TypeError(
1058
1105
  `Incorrect return type for (${
1059
1106
  expected[STATS][SIGNATURE]
@@ -1132,8 +1179,37 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1132
1179
  exp
1133
1180
  )})`
1134
1181
  )
1135
-
1136
1182
  if (name in env) {
1183
+ // const [head, ...tail] = isLeaf(rest.at(-1))
1184
+ // ? [rest.at(-1)]
1185
+ // : rest.at(-1)
1186
+ // const ref = env[name]
1187
+ // if (ref) {
1188
+ // if (getType(ref[STATS]) === APPLY && head[TYPE] !== APPLY)
1189
+ // throw new TypeError(
1190
+ // `Miss-matching type for (${name}) predifined expected type is (${toTypeNames(
1191
+ // APPLY
1192
+ // )}) but got (${stringifyArgs(exp)})`
1193
+ // )
1194
+ // const returns = deepLambdaReturn(
1195
+ // hasBlock(tail) ? tail.at(-1) : tail,
1196
+ // (result) => result[VALUE] !== KEYWORDS.IF
1197
+ // )
1198
+ // const [rhead] = isLeaf(returns) ? [returns] : returns
1199
+ // const rightRef = env[rhead[VALUE]]
1200
+ // if (rightRef)
1201
+ // if (
1202
+ // !equalReturns(ref[STATS], rightRef[STATS]) ||
1203
+ // !equalSubReturns(ref[STATS], rightRef[STATS])
1204
+ // )
1205
+ // throw new TypeError(
1206
+ // `Miss-matching return type for (${name}) predifined expected return is (${formatSubType(
1207
+ // getReturns(ref[STATS])
1208
+ // )}) but got (${formatSubType(
1209
+ // getReturns(rightRef[STATS])
1210
+ // )}) (${stringifyArgs(exp)})`
1211
+ // )
1212
+ // }
1137
1213
  Types.set(withScope(name, env), () => formatType(name, env))
1138
1214
  break
1139
1215
  }
@@ -1158,29 +1234,11 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1158
1234
  [RETURNS]: [UNKNOWN]
1159
1235
  }
1160
1236
  }
1161
- if (
1162
- !checkReturnType({
1163
- stack,
1164
- exp,
1165
- env,
1166
- name,
1167
- check
1168
- }) ||
1169
- isUnknownReturn(env[name][STATS])
1170
- ) {
1171
- retry(env[name][STATS], [first, env], stack, () => {
1172
- checkReturnType({
1173
- stack,
1174
- exp,
1175
- env,
1176
- name,
1177
- check
1178
- })
1179
- // TODO: remove this as maybe it is not needed
1237
+ check(rightHand, env, exp)
1238
+ if (isUnknownReturn(env[name][STATS]))
1239
+ retry(env[name][STATS], exp, stack, () =>
1180
1240
  check(rightHand, env, exp)
1181
- })
1182
- check(rightHand, env, exp)
1183
- } else check(rightHand, env, exp)
1241
+ )
1184
1242
  } else {
1185
1243
  checkPredicateName(exp, rest)
1186
1244
  const isLeafNode = isLeaf(rightHand)
@@ -1227,105 +1285,146 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1227
1285
  : env[right[VALUE]][STATS][RETURNS][0]
1228
1286
  if (type !== UNKNOWN)
1229
1287
  setTypeToReturn(env[name][STATS], env[right[VALUE]][STATS])
1230
- const body = rightHand
1231
- const rem = hasBlock(body) ? body.at(-1) : body
1232
- const returns = isLeaf(rem) ? rem : rem[0]
1233
- resolveReturnType({
1234
- stack,
1235
- returns,
1236
- rem,
1237
- prop: TYPE_PROP,
1238
- exp,
1239
- env,
1240
- name,
1241
- check
1242
- })
1288
+ const resolve = () => {
1289
+ const body = rightHand
1290
+ const rem = hasBlock(body) ? body.at(-1) : body
1291
+ const returns = isLeaf(rem) ? rem : rem[0]
1292
+ resolveReturnType({
1293
+ stack,
1294
+ returns,
1295
+ rem,
1296
+ prop: TYPE_PROP,
1297
+ exp,
1298
+ env,
1299
+ name,
1300
+ check
1301
+ })
1302
+ }
1303
+ resolve()
1304
+ if (isUnknownType(env[name][STATS]))
1305
+ once(env[name][STATS], exp, stack, () => resolve())
1243
1306
  }
1244
1307
  check(rightHand, env, scope)
1245
1308
  }
1246
1309
  Types.set(withScope(name, env), () => formatType(name, env))
1247
1310
  break
1248
1311
  case KEYWORDS.ANONYMOUS_FUNCTION:
1249
- validateLambda(exp)
1250
- const params = exp.slice(1, -1)
1251
- const copy = Object.create(env)
1252
- if (Array.isArray(scope[1]) && scope[1][TYPE] === WORD)
1253
- copy[SCOPE_NAME] = scope[1][VALUE]
1254
- else copy[SCOPE_NAME] = ++scopeIndex
1255
- for (let i = 0; i < params.length; ++i) {
1256
- const param = params[i]
1257
- // TODO move this somewhere else
1258
- if (!isLeaf(param))
1259
- throw new TypeError(
1260
- `Invalid body for (${
1261
- first[VALUE]
1262
- }) if it takes more than one expression it must be wrapped in a (${
1263
- KEYWORDS.BLOCK
1264
- }) (${stringifyArgs(exp)}) (check #666)`
1265
- )
1266
- copy[param[VALUE]] = {
1267
- [STATS]: {
1268
- [IS_ARGUMENT]: true,
1269
- [SIGNATURE]: param[VALUE],
1270
- [TYPE_PROP]: [UNKNOWN],
1271
- [RETURNS]: [UNKNOWN],
1272
- [ARGUMENTS]: [],
1273
- argIndex: i,
1274
- retried: 0,
1275
- counter: 0
1312
+ {
1313
+ validateLambda(exp)
1314
+ const params = exp.slice(1, -1)
1315
+ const copy = Object.create(env)
1316
+ if (Array.isArray(scope[1]) && scope[1][TYPE] === WORD)
1317
+ copy[SCOPE_NAME] = scope[1][VALUE]
1318
+ else copy[SCOPE_NAME] = ++scopeIndex
1319
+ const ref = env[copy[SCOPE_NAME]]
1320
+ for (let i = 0; i < params.length; ++i) {
1321
+ const param = params[i]
1322
+ // TODO move this somewhere else
1323
+ if (!isLeaf(param))
1324
+ throw new TypeError(
1325
+ `Invalid body for (${
1326
+ first[VALUE]
1327
+ }) if it takes more than one expression it must be wrapped in a (${
1328
+ KEYWORDS.BLOCK
1329
+ }) (${stringifyArgs(exp)}) (check #666)`
1330
+ )
1331
+ copy[param[VALUE]] = {
1332
+ [STATS]: {
1333
+ [IS_ARGUMENT]: true,
1334
+ [SIGNATURE]: param[VALUE],
1335
+ [TYPE_PROP]: [UNKNOWN],
1336
+ [RETURNS]: [UNKNOWN],
1337
+ [ARGUMENTS]: [],
1338
+ argIndex: i,
1339
+ retried: 0,
1340
+ counter: 0
1341
+ }
1276
1342
  }
1343
+ if (!ref) continue
1344
+ ref[STATS][ARGUMENTS][i] = copy[param[VALUE]]
1345
+ // TODO overwrite return type check here
1277
1346
  }
1278
- const ref = env[copy[SCOPE_NAME]]
1279
- if (!ref) continue
1280
- ref[STATS][ARGUMENTS][i] = copy[param[VALUE]]
1281
- // TODO overwrite return type check here
1282
- }
1283
- const returns = deepLambdaReturn(
1284
- hasBlock(exp) ? exp.at(-1) : exp,
1285
- (result) => result[VALUE] !== KEYWORDS.IF
1286
- )
1287
- const ref = env[copy[SCOPE_NAME]]
1288
- if (ref)
1289
- if (isLeaf(returns))
1290
- // TODO figure out what we do here
1291
- // this here is a variable WORD
1292
- // so return type of that function is that varible type
1293
- stagger(
1294
- stack,
1295
- 'append',
1296
- [returns, copy],
1297
- () =>
1298
- copy[returns[VALUE]] &&
1299
- setReturnToType(ref[STATS], copy[returns[VALUE]][STATS])
1300
- )
1301
- else {
1302
- stagger(stack, 'append', [returns, copy], () => {
1303
- const ret = returns[0]
1304
- switch (ret[VALUE]) {
1305
- case KEYWORDS.IF:
1306
- resolveCondition({
1307
- rem: returns,
1308
- name: ref[STATS][SIGNATURE],
1309
- env: copy,
1310
- exp,
1311
- stack,
1312
- prop: RETURNS,
1313
- check
1314
- })
1347
+ const returns = deepLambdaReturn(
1348
+ hasBlock(exp) ? exp.at(-1) : exp,
1349
+ (result) => result[VALUE] !== KEYWORDS.IF
1350
+ )
1351
+ if (ref)
1352
+ if (isLeaf(returns)) {
1353
+ // TODO figure out what we do here
1354
+ // this here is a variable WORD
1355
+ // so return type of that function is that varible type
1356
+ switch (returns[TYPE]) {
1357
+ case ATOM:
1358
+ setReturnToAtom(ref[STATS])
1315
1359
  break
1316
- default:
1317
- if (copy[ret[VALUE]]) {
1318
- setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
1319
- } else
1320
- stagger(stack, 'append', [ret, copy], () => {
1321
- if (copy[ret[VALUE]])
1322
- setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
1323
- })
1360
+ case WORD:
1361
+ stagger(stack, 'append', [returns, copy], () => {
1362
+ copy[returns[VALUE]] &&
1363
+ checkReturnType({
1364
+ stack,
1365
+ exp: [
1366
+ [APPLY, KEYWORDS.DEFINE_VARIABLE],
1367
+ [WORD, ref[STATS][SIGNATURE]],
1368
+ exp
1369
+ ],
1370
+ env: copy,
1371
+ name: ref[STATS][SIGNATURE],
1372
+ check
1373
+ })
1374
+ // setReturnToType(
1375
+ // ref[STATS],
1376
+ // copy[returns[VALUE]][STATS]
1377
+ // )
1378
+ })
1324
1379
  break
1325
1380
  }
1326
- })
1327
- }
1328
- check(rest.at(-1), copy, copy)
1381
+ } else {
1382
+ stagger(stack, 'append', [returns, copy], () => {
1383
+ retry(ref[STATS], exp, stack, () => {
1384
+ checkReturnType({
1385
+ stack,
1386
+ exp: [
1387
+ [APPLY, KEYWORDS.DEFINE_VARIABLE],
1388
+ [WORD, ref[STATS][SIGNATURE]],
1389
+ exp
1390
+ ],
1391
+ env: copy,
1392
+ name: ref[STATS][SIGNATURE],
1393
+ check
1394
+ })
1395
+ })
1396
+ // const ret = returns[0]
1397
+ // switch (ret[VALUE]) {
1398
+ // case KEYWORDS.IF:
1399
+ // resolveCondition({
1400
+ // rem: returns,
1401
+ // name: ref[STATS][SIGNATURE],
1402
+ // env: copy,
1403
+ // exp,
1404
+ // stack,
1405
+ // prop: RETURNS,
1406
+ // check
1407
+ // })
1408
+ // break
1409
+ // default:
1410
+ // if (copy[ret[VALUE]]) {
1411
+ // if (isUnknownReturn(copy[ret[VALUE]][STATS])) {
1412
+ // once(ref[STATS], [returns, copy], stack, () => {
1413
+ // setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
1414
+ // })
1415
+ // } else setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
1416
+ // } else
1417
+ // stagger(stack, 'append', [ret, copy], () => {
1418
+ // if (copy[ret[VALUE]])
1419
+ // setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
1420
+ // })
1421
+ // break
1422
+ // }
1423
+ })
1424
+ }
1425
+ check(rest.at(-1), copy, copy)
1426
+ }
1427
+
1329
1428
  break
1330
1429
  case STATIC_TYPES.ABSTRACTION:
1331
1430
  case STATIC_TYPES.COLLECTION:
package/src/keywords.js CHANGED
@@ -113,6 +113,10 @@ export const MUTATORS_SET = new Set([
113
113
  ])
114
114
  export const GETTERS_SET = new Set([
115
115
  KEYWORDS.GET_ARRAY,
116
+ 'array:first',
117
+ 'array:second',
118
+ 'array:third',
119
+ 'array:last',
116
120
  'matrix:get',
117
121
  'matrix:set-and-get!',
118
122
  'array:set-and-get!',
package/src/types.js CHANGED
@@ -76,7 +76,8 @@ export const toTypeCodes = (type) => {
76
76
  case 'Unknown':
77
77
  return [UNKNOWN]
78
78
  case 'Unknowns':
79
- return [COLLECTION]
79
+ case 'Collection':
80
+ return [COLLECTION, new Set([ANY])]
80
81
  case 'Numbers':
81
82
  return [COLLECTION, NUMBER_SUBTYPE()]
82
83
  case 'Booleans':