fez-lisp 1.5.130 → 1.5.131

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/check.js +172 -231
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.130",
5
+ "version": "1.5.131",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -716,11 +716,145 @@ const checkReturnType = ({ exp, stack, name, env }) => {
716
716
  stack
717
717
  })
718
718
  }
719
+
719
720
  export const typeCheck = (ast) => {
720
- let scopeIndex = 0
721
- const root = structuredClone(SPECIAL_FORM_TYPES)
722
721
  const Types = new Map()
723
722
  const stack = new Brr()
723
+ let scopeIndex = 0
724
+ // TODO also handle casting
725
+ const match = ({ rest, args, i, env, scope, exp }) => {
726
+ const first = exp[0]
727
+ const actual =
728
+ rest[i][0][VALUE] === KEYWORDS.CREATE_ARRAY
729
+ ? initArrayType({ rem: rest[i], env }) ?? env[rest[i][0][VALUE]][STATS]
730
+ : env[rest[i][0][VALUE]][STATS]
731
+ const expected = args[i][STATS]
732
+ retryArgs(args[i][STATS], stack, () =>
733
+ match({ rest, args, i, env, scope, exp })
734
+ )
735
+ if (!isUnknownType(expected) && !isUnknownReturn(actual))
736
+ if (!compareTypeWithReturn(expected, actual))
737
+ throw new TypeError(
738
+ `Incorrect type of argument (${i}) for (${
739
+ first[VALUE]
740
+ }). Expected (${toTypeNames(
741
+ getType(expected)
742
+ )}) but got (${toTypeNames(getReturn(actual))}) (${stringifyArgs(
743
+ exp
744
+ )}) (check #16)`
745
+ )
746
+ else if (notABooleanReturn(expected, actual)) {
747
+ throw new TypeError(
748
+ `Incorrect type of argument (${i}) for (${
749
+ first[VALUE]
750
+ }). Expected (${formatSubType(
751
+ getTypes(expected)
752
+ )}) but got (${formatSubType(getReturns(actual))}) (${stringifyArgs(
753
+ exp
754
+ )}) (check #206)`
755
+ )
756
+ } else {
757
+ switch (getType(expected)) {
758
+ // almost exclusively for anonymous lambdas
759
+ case APPLY:
760
+ {
761
+ const argsN = rest[i].length - 2
762
+ if (
763
+ env[rest[i][0][VALUE]][STATS][SIGNATURE] ===
764
+ KEYWORDS.ANONYMOUS_FUNCTION
765
+ ) {
766
+ if (argsN !== args[i][STATS][ARG_COUNT])
767
+ throw new TypeError(
768
+ `Incorrect number of arguments for (${
769
+ args[i][STATS][SIGNATURE]
770
+ }) the (${KEYWORDS.ANONYMOUS_FUNCTION}) argument of (${
771
+ first[VALUE]
772
+ }) at position (${i}). Expected (= ${
773
+ args[i][STATS][ARG_COUNT]
774
+ }) but got ${argsN} (${stringifyArgs(exp)}) (check #777)`
775
+ )
776
+ else {
777
+ // ANONYMOUS LAMBDAS TYPE CHECKING
778
+ const local = Object.create(env)
779
+ const lambdaName = `${ANONYMOUS_FUNCTION_TYPE_PREFIX}${i}::${++scopeIndex}`
780
+ check(
781
+ [
782
+ [APPLY, KEYWORDS.DEFINE_VARIABLE],
783
+ [WORD, lambdaName],
784
+ rest[i]
785
+ ],
786
+ local,
787
+ scope
788
+ )
789
+ // TODO delete this maybe
790
+ // #C2
791
+ // It will not be possilbe to know return type
792
+ const match1 = () => {
793
+ const actual = local[lambdaName]
794
+ const expected = args[i]
795
+ if (
796
+ !isUnknownReturn(expected[STATS]) &&
797
+ !isUnknownReturn(actual[STATS]) &&
798
+ !compareReturns(expected[STATS], actual[STATS])
799
+ )
800
+ throw new TypeError(
801
+ `Incorrect return type for (${
802
+ expected[STATS][SIGNATURE]
803
+ }) the (${KEYWORDS.ANONYMOUS_FUNCTION}) argument of (${
804
+ first[VALUE]
805
+ }) at position (${i}). Expected (${toTypeNames(
806
+ getReturn(expected[STATS])
807
+ )}) but got (${toTypeNames(
808
+ getReturn(actual[STATS])
809
+ )}) (${stringifyArgs(exp)}) (check #779)`
810
+ )
811
+ else retry(actual[STATS], stack, () => match1())
812
+ }
813
+ match1()
814
+ for (let j = 0; j < args[i][STATS][ARGUMENTS].length; ++j) {
815
+ const match2 = () => {
816
+ const actual = local[lambdaName][STATS][ARGUMENTS][j]
817
+ const expected = args[i][STATS][ARGUMENTS][j]
818
+ if (
819
+ !isUnknownType(actual[STATS]) &&
820
+ !isUnknownType(expected[STATS]) &&
821
+ !compareTypes(actual[STATS], expected[STATS])
822
+ )
823
+ throw new TypeError(
824
+ `Incorrect type for (${
825
+ KEYWORDS.ANONYMOUS_FUNCTION
826
+ }) (${
827
+ args[i][STATS][SIGNATURE]
828
+ }) argument at position (${j}) named as (${
829
+ local[lambdaName][STATS][ARGUMENTS][j][STATS][
830
+ SIGNATURE
831
+ ]
832
+ }). Expected (${toTypeNames(
833
+ getType(expected[STATS])
834
+ )}) but got (${toTypeNames(
835
+ getType(actual[STATS])
836
+ )}) (${stringifyArgs(exp)}) (check #780)`
837
+ )
838
+ else retry(actual[STATS], stack, () => match2())
839
+ }
840
+ match2()
841
+ }
842
+ }
843
+ } else {
844
+ // TODO fix curry: lambdas enter here as undefined
845
+ }
846
+ }
847
+ break
848
+ // case ATOM:
849
+ // case COLLECTION:
850
+ // break
851
+ }
852
+ }
853
+ else if (isUnknownType(expected))
854
+ retry(args[i][STATS], stack, () =>
855
+ match({ rest, args, i, env, scope, exp })
856
+ )
857
+ }
724
858
  const check = (exp, env, scope) => {
725
859
  const [first, ...rest] = isLeaf(exp) ? [exp] : exp
726
860
  if (first === undefined)
@@ -950,7 +1084,7 @@ export const typeCheck = (ast) => {
950
1084
  const ret = isLeaf(rest[0]) ? rest[0] : rest[0][0]
951
1085
  const ref = env[ret[VALUE]]
952
1086
  if (!ref) break
953
- const caster = root[first[VALUE]]
1087
+ const caster = SPECIAL_FORM_TYPES[first[VALUE]]
954
1088
  if (ret[TYPE] === APPLY && isUnknownReturn(ref[STATS]))
955
1089
  castReturn(ref[STATS], caster[STATS])
956
1090
  else if (isUnknownType(ref[STATS]))
@@ -1284,235 +1418,42 @@ export const typeCheck = (ast) => {
1284
1418
  } else {
1285
1419
  const name = rest[i][0][VALUE]
1286
1420
  if (!env[name]) continue
1287
- if (isSpecial) {
1288
- // there is a problem here with cond pr when passed as an argument
1289
- if (name === KEYWORDS.IF) {
1290
- const concequent = [...rest]
1291
- const alternative = [...rest]
1292
- concequent[i] = rest[i][1]
1293
- alternative[i] = rest[i][2]
1294
- check([first, ...concequent], env, scope)
1295
- check([first, ...alternative], env, scope)
1296
- } else if (
1297
- isUnknownReturn(env[name][STATS]) &&
1298
- !env[name][STATS][IS_ARGUMENT]
1299
- ) {
1300
- return retry(env[name][STATS], stack, () =>
1301
- check(exp, env, scope)
1302
- )
1303
- } else if (
1304
- !isUnknownType(args[i][STATS]) &&
1305
- !isUnknownReturn(env[name][STATS]) &&
1306
- !compareTypeWithReturn(
1307
- args[i][STATS],
1308
- env[name][STATS]
1309
- )
1310
- )
1311
- throw new TypeError(
1312
- `Incorrect type of argument (${i}) for (${
1313
- first[VALUE]
1314
- }). Expected (${toTypeNames(
1315
- getType(args[i][STATS])
1316
- )}) but got (${toTypeNames(
1317
- getReturn(env[name][STATS])
1318
- )}) (${stringifyArgs(exp)}) (check #1)`
1319
- )
1320
- else if (
1321
- !isUnknownReturn(args[i][STATS]) &&
1322
- !isUnknownReturn(env[name][STATS]) &&
1323
- notABooleanReturn(args[i][STATS], env[name][STATS])
1421
+ if (
1422
+ isUnknownReturn(env[name][STATS]) &&
1423
+ !env[name][STATS][IS_ARGUMENT]
1424
+ )
1425
+ return retry(env[name][STATS], stack, () =>
1426
+ check(exp, env, scope)
1324
1427
  )
1325
- throw new TypeError(
1326
- `Incorrect type of argument (${i}) for (${
1327
- first[VALUE]
1328
- }). Expected (${formatSubType(
1329
- getTypes(args[i][STATS])
1330
- )}) but got (${formatSubType(
1331
- getReturns(env[name][STATS])
1332
- )}) (${stringifyArgs(exp)}) (check #201)`
1333
- )
1334
- else {
1335
- if (env[name] && getType(env[name][STATS]) === APPLY)
1336
- switch (first[VALUE]) {
1337
- case KEYWORDS.IF:
1338
- break
1339
- default:
1340
- // TODO fix this assigment
1341
- // It turns out it's not possible to determine return type of function here
1342
- // what if it's a global function used elsewhere where the return type mwould be different
1343
- // THIS willgive lambda return types but refactor is needed still
1344
- if (!SPECIAL_FORMS_SET.has(name))
1345
- setReturnRef(env[name][STATS], args[i][STATS])
1346
- break
1347
- }
1348
- // TODO also handle casting
1349
- }
1350
- } else {
1351
- const match = () => {
1352
- const actual =
1353
- rest[i][0][VALUE] === KEYWORDS.CREATE_ARRAY
1354
- ? initArrayType({ rem: rest[i], env }) ??
1355
- env[rest[i][0][VALUE]][STATS]
1356
- : env[rest[i][0][VALUE]][STATS]
1357
- const expected = args[i][STATS]
1358
- retryArgs(args[i][STATS], stack, () => match())
1359
- if (
1360
- !isUnknownType(expected) &&
1361
- !isUnknownReturn(actual)
1362
- )
1363
- if (!compareTypeWithReturn(expected, actual))
1364
- throw new TypeError(
1365
- `Incorrect type of argument (${i}) for (${
1366
- first[VALUE]
1367
- }). Expected (${toTypeNames(
1368
- getType(expected)
1369
- )}) but got (${toTypeNames(
1370
- getReturn(actual)
1371
- )}) (${stringifyArgs(exp)}) (check #16)`
1372
- )
1373
- else if (notABooleanReturn(expected, actual)) {
1374
- throw new TypeError(
1375
- `Incorrect type of argument (${i}) for (${
1376
- first[VALUE]
1377
- }). Expected (${formatSubType(
1378
- getTypes(expected)
1379
- )}) but got (${formatSubType(
1380
- getReturns(actual)
1381
- )}) (${stringifyArgs(exp)}) (check #206)`
1382
- )
1383
- } else {
1384
- switch (getType(expected)) {
1385
- // almost exclusively for anonymous lambdas
1386
- case APPLY:
1387
- {
1388
- const argsN = rest[i].length - 2
1389
- if (
1390
- env[rest[i][0][VALUE]][STATS][
1391
- SIGNATURE
1392
- ] === KEYWORDS.ANONYMOUS_FUNCTION
1393
- ) {
1394
- if (argsN !== args[i][STATS][ARG_COUNT])
1395
- throw new TypeError(
1396
- `Incorrect number of arguments for (${
1397
- args[i][STATS][SIGNATURE]
1398
- }) the (${
1399
- KEYWORDS.ANONYMOUS_FUNCTION
1400
- }) argument of (${
1401
- first[VALUE]
1402
- }) at position (${i}). Expected (= ${
1403
- args[i][STATS][ARG_COUNT]
1404
- }) but got ${argsN} (${stringifyArgs(
1405
- exp
1406
- )}) (check #777)`
1407
- )
1408
- else {
1409
- // ANONYMOUS LAMBDAS TYPE CHECKING
1410
- const local = Object.create(env)
1411
- const lambdaName = `${ANONYMOUS_FUNCTION_TYPE_PREFIX}${i}::${++scopeIndex}`
1412
- check(
1413
- [
1414
- [APPLY, KEYWORDS.DEFINE_VARIABLE],
1415
- [WORD, lambdaName],
1416
- rest[i]
1417
- ],
1418
- local,
1419
- scope
1420
- )
1421
- // TODO delete this maybe
1422
- // #C2
1423
- // It will not be possilbe to know return type
1424
- const match1 = () => {
1425
- const actual = local[lambdaName]
1426
- const expected = args[i]
1427
- if (
1428
- !isUnknownReturn(expected[STATS]) &&
1429
- !isUnknownReturn(actual[STATS]) &&
1430
- !compareReturns(
1431
- expected[STATS],
1432
- actual[STATS]
1433
- )
1434
- )
1435
- throw new TypeError(
1436
- `Incorrect return type for (${
1437
- expected[STATS][SIGNATURE]
1438
- }) the (${
1439
- KEYWORDS.ANONYMOUS_FUNCTION
1440
- }) argument of (${
1441
- first[VALUE]
1442
- }) at position (${i}). Expected (${toTypeNames(
1443
- getReturn(expected[STATS])
1444
- )}) but got (${toTypeNames(
1445
- getReturn(actual[STATS])
1446
- )}) (${stringifyArgs(
1447
- exp
1448
- )}) (check #779)`
1449
- )
1450
- else
1451
- retry(actual[STATS], stack, () =>
1452
- match1()
1453
- )
1454
- }
1455
- match1()
1456
- for (
1457
- let j = 0;
1458
- j < args[i][STATS][ARGUMENTS].length;
1459
- ++j
1460
- ) {
1461
- const match2 = () => {
1462
- const actual =
1463
- local[lambdaName][STATS][
1464
- ARGUMENTS
1465
- ][j]
1466
- const expected =
1467
- args[i][STATS][ARGUMENTS][j]
1468
- if (
1469
- !isUnknownType(actual[STATS]) &&
1470
- !isUnknownType(expected[STATS]) &&
1471
- !compareTypes(
1472
- actual[STATS],
1473
- expected[STATS]
1474
- )
1475
- )
1476
- throw new TypeError(
1477
- `Incorrect type for (${
1478
- KEYWORDS.ANONYMOUS_FUNCTION
1479
- }) (${
1480
- args[i][STATS][SIGNATURE]
1481
- }) argument at position (${j}) named as (${
1482
- local[lambdaName][STATS][
1483
- ARGUMENTS
1484
- ][j][STATS][SIGNATURE]
1485
- }). Expected (${toTypeNames(
1486
- getType(expected[STATS])
1487
- )}) but got (${toTypeNames(
1488
- getType(actual[STATS])
1489
- )}) (${stringifyArgs(
1490
- exp
1491
- )}) (check #780)`
1492
- )
1493
- else
1494
- retry(actual[STATS], stack, () =>
1495
- match2()
1496
- )
1497
- }
1498
- match2()
1499
- }
1500
- }
1501
- } else {
1502
- // TODO fix curry: lambdas enter here as undefined
1503
- }
1504
- }
1505
- break
1506
- // case ATOM:
1507
- // case COLLECTION:
1508
- // break
1509
- }
1510
- }
1511
- else if (isUnknownType(expected))
1512
- retry(args[i][STATS], stack, () => match())
1513
- }
1514
- match()
1428
+
1429
+ if (isSpecial && name === KEYWORDS.IF) {
1430
+ const concequent = [...rest]
1431
+ const alternative = [...rest]
1432
+ concequent[i] = rest[i][1]
1433
+ alternative[i] = rest[i][2]
1434
+ check([first, ...concequent], env, scope)
1435
+ check([first, ...alternative], env, scope)
1515
1436
  }
1437
+
1438
+ if (
1439
+ env[name] &&
1440
+ getType(env[name][STATS]) === APPLY &&
1441
+ !SPECIAL_FORMS_SET.has(name)
1442
+ )
1443
+ switch (first[VALUE]) {
1444
+ case KEYWORDS.IF:
1445
+ break
1446
+ default:
1447
+ // TODO fix this assigment
1448
+ // It turns out it's not possible to determine return type of function here
1449
+ // what if it's a global function used elsewhere where the return type mwould be different
1450
+ // THIS willgive lambda return types but refactor is needed still
1451
+ // if (!SPECIAL_FORMS_SET.has(name))
1452
+ setReturnRef(env[name][STATS], args[i][STATS])
1453
+ break
1454
+ }
1455
+
1456
+ match({ rest, args, i, env, scope, exp })
1516
1457
  }
1517
1458
  }
1518
1459
  // REFACTORING
@@ -1538,7 +1479,7 @@ export const typeCheck = (ast) => {
1538
1479
  }
1539
1480
  }
1540
1481
  const copy = JSON.parse(JSON.stringify(ast))
1541
- check(copy, root, copy)
1482
+ check(copy, SPECIAL_FORM_TYPES, copy)
1542
1483
  while (stack.length) stack.cut()()
1543
1484
  return [ast, Types]
1544
1485
  }