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/lib/baked/std-T.js +1 -1
- package/lib/baked/std.js +1 -1
- package/package.json +1 -1
- package/src/check.js +219 -120
- package/src/keywords.js +4 -0
- package/src/types.js +2 -1
package/package.json
CHANGED
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
|
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 (
|
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
|
-
|
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
|
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 (!
|
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 (!
|
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
|
-
|
1162
|
-
|
1163
|
-
|
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
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
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
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
const
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
[
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
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
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
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
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
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
|
-
|
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
|
-
|
79
|
+
case 'Collection':
|
80
|
+
return [COLLECTION, new Set([ANY])]
|
80
81
|
case 'Numbers':
|
81
82
|
return [COLLECTION, NUMBER_SUBTYPE()]
|
82
83
|
case 'Booleans':
|