fez-lisp 1.5.161 → 1.5.163

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.161",
5
+ "version": "1.5.163",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -351,7 +351,7 @@ const equalSubTypes = (a, b) => {
351
351
  getSubType(a).difference(getSubType(b)).size === 0
352
352
  )
353
353
  }
354
- const eualSubReturn = (a, b) => {
354
+ const equalSubReturns = (a, b) => {
355
355
  return (
356
356
  !hasSubReturn(a) ||
357
357
  !hasSubReturn(b) ||
@@ -660,7 +660,7 @@ const resolveSetter = (first, rest, env, stack) => {
660
660
  getSubType(env[right[VALUE]][STATS])
661
661
  )
662
662
  } else
663
- once(env[right[VALUE]][STATS], [first[VALUE], rest], stack, () =>
663
+ retry(env[right[VALUE]][STATS], [first[VALUE], rest], stack, () =>
664
664
  resolveSetter(first, rest, env, stack)
665
665
  )
666
666
  }
@@ -791,9 +791,31 @@ const resolveReturnType = ({
791
791
  check
792
792
  }) => {
793
793
  if (returns[TYPE] === ATOM) setPropToAtom(env[name][STATS], prop)
794
- 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 {
795
816
  switch (returns[VALUE]) {
796
817
  case KEYWORDS.CREATE_ARRAY:
818
+ setPropToCollection(env[name][STATS], prop)
797
819
  setPropToSubReturn(env[name][STATS], prop, initArrayType({ rem, env }))
798
820
  break
799
821
  case KEYWORDS.IF:
@@ -818,11 +840,13 @@ const resolveReturnType = ({
818
840
  })
819
841
  })
820
842
  checkPredicateNameDeep(name, exp, exp.slice(1), returns)
843
+ // TODO: DRY
821
844
  const index = env[name][STATS][ARGUMENTS]
822
845
  ? env[name][STATS][ARGUMENTS].findIndex(
823
846
  (x) => x[STATS][SIGNATURE] === returns[VALUE]
824
847
  )
825
848
  : -1
849
+
826
850
  if (index >= 0) {
827
851
  setReturnToGeneric(env[name][STATS], index)
828
852
  return true
@@ -910,7 +934,12 @@ const resolveReturnType = ({
910
934
  env[returns[VALUE]][STATS]
911
935
  )
912
936
  })
913
- 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
+ }
914
943
  }
915
944
  }
916
945
  }
@@ -1029,7 +1058,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1029
1058
  getReturn(actual[STATS])
1030
1059
  )}) (${stringifyArgs(exp)}) (check #779)`
1031
1060
  )
1032
- else if (!eualSubReturn(expected[STATS], actual[STATS]))
1061
+ else if (!equalSubReturns(expected[STATS], actual[STATS]))
1033
1062
  throw new TypeError(
1034
1063
  `Incorrect return type for (${
1035
1064
  expected[STATS][SIGNATURE]
@@ -1042,7 +1071,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1042
1071
  )}) (${stringifyArgs(exp)}) (check #783)`
1043
1072
  )
1044
1073
  else
1045
- once(
1074
+ retry(
1046
1075
  actual[STATS],
1047
1076
  [[WORD, lambdaName], local],
1048
1077
  stack,
@@ -1071,7 +1100,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1071
1100
  getType(actual[STATS])
1072
1101
  )}) (${stringifyArgs(exp)}) (check #780)`
1073
1102
  )
1074
- else if (!eualSubReturn(expected[STATS], actual[STATS]))
1103
+ else if (!equalSubReturns(expected[STATS], actual[STATS]))
1075
1104
  throw new TypeError(
1076
1105
  `Incorrect return type for (${
1077
1106
  expected[STATS][SIGNATURE]
@@ -1151,6 +1180,36 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1151
1180
  )})`
1152
1181
  )
1153
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
+ // }
1154
1213
  Types.set(withScope(name, env), () => formatType(name, env))
1155
1214
  break
1156
1215
  }
@@ -1175,36 +1234,11 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1175
1234
  [RETURNS]: [UNKNOWN]
1176
1235
  }
1177
1236
  }
1178
- if (
1179
- !checkReturnType({
1180
- stack,
1181
- exp,
1182
- env,
1183
- name,
1184
- check
1185
- }) ||
1186
- isUnknownReturn(env[name][STATS])
1187
- ) {
1188
- retry(env[name][STATS], [first, env], stack, () => {
1189
- checkReturnType({
1190
- stack,
1191
- exp,
1192
- env,
1193
- name,
1194
- check
1195
- })
1196
- // TODO: remove this as maybe it is not needed
1197
- check(rightHand, env, exp)
1198
- })
1199
- check(rightHand, env, exp)
1200
- }
1201
-
1202
1237
  check(rightHand, env, exp)
1203
-
1204
- // if (isUnknownReturn(env[name][STATS]))
1205
- // retry(env[name][STATS], exp, stack, () =>
1206
- // check(rightHand, env, exp)
1207
- // )
1238
+ if (isUnknownReturn(env[name][STATS]))
1239
+ retry(env[name][STATS], exp, stack, () =>
1240
+ check(rightHand, env, exp)
1241
+ )
1208
1242
  } else {
1209
1243
  checkPredicateName(exp, rest)
1210
1244
  const isLeafNode = isLeaf(rightHand)
@@ -1275,90 +1309,122 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1275
1309
  Types.set(withScope(name, env), () => formatType(name, env))
1276
1310
  break
1277
1311
  case KEYWORDS.ANONYMOUS_FUNCTION:
1278
- validateLambda(exp)
1279
- const params = exp.slice(1, -1)
1280
- const copy = Object.create(env)
1281
- if (Array.isArray(scope[1]) && scope[1][TYPE] === WORD)
1282
- copy[SCOPE_NAME] = scope[1][VALUE]
1283
- else copy[SCOPE_NAME] = ++scopeIndex
1284
- for (let i = 0; i < params.length; ++i) {
1285
- const param = params[i]
1286
- // TODO move this somewhere else
1287
- if (!isLeaf(param))
1288
- throw new TypeError(
1289
- `Invalid body for (${
1290
- first[VALUE]
1291
- }) if it takes more than one expression it must be wrapped in a (${
1292
- KEYWORDS.BLOCK
1293
- }) (${stringifyArgs(exp)}) (check #666)`
1294
- )
1295
- copy[param[VALUE]] = {
1296
- [STATS]: {
1297
- [IS_ARGUMENT]: true,
1298
- [SIGNATURE]: param[VALUE],
1299
- [TYPE_PROP]: [UNKNOWN],
1300
- [RETURNS]: [UNKNOWN],
1301
- [ARGUMENTS]: [],
1302
- argIndex: i,
1303
- retried: 0,
1304
- 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
+ }
1305
1342
  }
1343
+ if (!ref) continue
1344
+ ref[STATS][ARGUMENTS][i] = copy[param[VALUE]]
1345
+ // TODO overwrite return type check here
1306
1346
  }
1307
- const ref = env[copy[SCOPE_NAME]]
1308
- if (!ref) continue
1309
- ref[STATS][ARGUMENTS][i] = copy[param[VALUE]]
1310
- // TODO overwrite return type check here
1311
- }
1312
- const returns = deepLambdaReturn(
1313
- hasBlock(exp) ? exp.at(-1) : exp,
1314
- (result) => result[VALUE] !== KEYWORDS.IF
1315
- )
1316
- const ref = env[copy[SCOPE_NAME]]
1317
- if (ref)
1318
- if (isLeaf(returns))
1319
- // TODO figure out what we do here
1320
- // this here is a variable WORD
1321
- // so return type of that function is that varible type
1322
- stagger(
1323
- stack,
1324
- 'append',
1325
- [returns, copy],
1326
- () =>
1327
- copy[returns[VALUE]] &&
1328
- setReturnToType(ref[STATS], copy[returns[VALUE]][STATS])
1329
- )
1330
- else {
1331
- stagger(stack, 'append', [returns, copy], () => {
1332
- const ret = returns[0]
1333
- switch (ret[VALUE]) {
1334
- case KEYWORDS.IF:
1335
- resolveCondition({
1336
- rem: returns,
1337
- name: ref[STATS][SIGNATURE],
1338
- env: copy,
1339
- exp,
1340
- stack,
1341
- prop: RETURNS,
1342
- check
1343
- })
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])
1344
1359
  break
1345
- default:
1346
- if (copy[ret[VALUE]]) {
1347
- if (isUnknownReturn(copy[ret[VALUE]][STATS])) {
1348
- once(ref[STATS], [returns, copy], stack, () => {
1349
- setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
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
1350
1373
  })
1351
- } else setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
1352
- } else
1353
- stagger(stack, 'append', [ret, copy], () => {
1354
- if (copy[ret[VALUE]])
1355
- setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
1356
- })
1374
+ // setReturnToType(
1375
+ // ref[STATS],
1376
+ // copy[returns[VALUE]][STATS]
1377
+ // )
1378
+ })
1357
1379
  break
1358
1380
  }
1359
- })
1360
- }
1361
- 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
+
1362
1428
  break
1363
1429
  case STATIC_TYPES.ABSTRACTION:
1364
1430
  case STATIC_TYPES.COLLECTION:
@@ -1669,7 +1735,6 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1669
1735
  // It turns out it's not possible to determine return type of function here
1670
1736
  // what if it's a global function used elsewhere where the return type mwould be different
1671
1737
  // THIS willgive lambda return types but refactor is needed still
1672
- // if (!SPECIAL_FORMS_SET.has(name))
1673
1738
  setReturnRef(env[name][STATS], args[i][STATS])
1674
1739
  break
1675
1740
  }
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!',