fez-lisp 1.5.129 → 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.
- package/package.json +1 -1
- package/src/check.js +337 -435
package/package.json
CHANGED
package/src/check.js
CHANGED
@@ -315,21 +315,10 @@ const notABooleanType = (a, b) => {
|
|
315
315
|
getSubType(a).has(PREDICATE) &&
|
316
316
|
!isUnknownType(b) &&
|
317
317
|
!isAnyType(b) &&
|
318
|
-
(!hasSubType(b)
|
318
|
+
((!hasSubType(b) && getType(b) !== COLLECTION) ||
|
319
|
+
(hasSubType(b) && getSubType(a).difference(getSubType(b)).size !== 0))
|
319
320
|
)
|
320
321
|
}
|
321
|
-
// const notABooleanReturn = (a, b) => {
|
322
|
-
// return (
|
323
|
-
// hasSubType(a) &&
|
324
|
-
// getSubType(a).has(PREDICATE) &&
|
325
|
-
// !isUnknownReturn(b) &&
|
326
|
-
// !isAnyReturn(b) &&
|
327
|
-
// (
|
328
|
-
// !isAtomReturn(b) ||
|
329
|
-
// !hasSubReturn(b) ||
|
330
|
-
// getSubType(a).difference(getSubReturn(b)).size !== 0)
|
331
|
-
// )
|
332
|
-
// }
|
333
322
|
const notABooleanReturn = (a, b) => {
|
334
323
|
return (
|
335
324
|
hasSubType(a) &&
|
@@ -727,11 +716,145 @@ const checkReturnType = ({ exp, stack, name, env }) => {
|
|
727
716
|
stack
|
728
717
|
})
|
729
718
|
}
|
719
|
+
|
730
720
|
export const typeCheck = (ast) => {
|
731
|
-
let scopeIndex = 0
|
732
|
-
const root = structuredClone(SPECIAL_FORM_TYPES)
|
733
721
|
const Types = new Map()
|
734
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
|
+
}
|
735
858
|
const check = (exp, env, scope) => {
|
736
859
|
const [first, ...rest] = isLeaf(exp) ? [exp] : exp
|
737
860
|
if (first === undefined)
|
@@ -961,7 +1084,7 @@ export const typeCheck = (ast) => {
|
|
961
1084
|
const ret = isLeaf(rest[0]) ? rest[0] : rest[0][0]
|
962
1085
|
const ref = env[ret[VALUE]]
|
963
1086
|
if (!ref) break
|
964
|
-
const caster =
|
1087
|
+
const caster = SPECIAL_FORM_TYPES[first[VALUE]]
|
965
1088
|
if (ret[TYPE] === APPLY && isUnknownReturn(ref[STATS]))
|
966
1089
|
castReturn(ref[STATS], caster[STATS])
|
967
1090
|
else if (isUnknownType(ref[STATS]))
|
@@ -1049,89 +1172,54 @@ export const typeCheck = (ast) => {
|
|
1049
1172
|
// also type of arg
|
1050
1173
|
const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
|
1051
1174
|
for (let i = 0; i < args.length; ++i) {
|
1052
|
-
const isResLeaf = isLeaf(rest[i])
|
1053
1175
|
// type check
|
1054
1176
|
// TODO get rof pred type
|
1055
1177
|
// const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
|
1056
1178
|
const MAIN_TYPE = getType(args[i][STATS])
|
1057
1179
|
if (MAIN_TYPE === ANY) continue
|
1058
1180
|
// TODO - try to merge special and non special
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
if (!env[name]) continue
|
1063
|
-
// there is a problem here with cond pr when passed as an argument
|
1064
|
-
if (name === KEYWORDS.IF) {
|
1065
|
-
const concequent = [...rest]
|
1066
|
-
const alternative = [...rest]
|
1067
|
-
concequent[i] = rest[i][1]
|
1068
|
-
alternative[i] = rest[i][2]
|
1069
|
-
check([first, ...concequent], env, scope)
|
1070
|
-
check([first, ...alternative], env, scope)
|
1071
|
-
} else if (
|
1072
|
-
isUnknownReturn(env[name][STATS]) &&
|
1073
|
-
!env[name][STATS][IS_ARGUMENT]
|
1074
|
-
) {
|
1075
|
-
return retry(env[name][STATS], stack, () =>
|
1076
|
-
check(exp, env, scope)
|
1077
|
-
)
|
1078
|
-
} else if (
|
1079
|
-
!isUnknownType(args[i][STATS]) &&
|
1080
|
-
!isUnknownReturn(env[name][STATS]) &&
|
1081
|
-
!compareTypeWithReturn(args[i][STATS], env[name][STATS])
|
1082
|
-
)
|
1083
|
-
throw new TypeError(
|
1084
|
-
`Incorrect type of argument (${i}) for special form (${
|
1085
|
-
first[VALUE]
|
1086
|
-
}). Expected (${toTypeNames(
|
1087
|
-
getType(args[i][STATS])
|
1088
|
-
)}) but got (${toTypeNames(
|
1089
|
-
getReturn(env[name][STATS])
|
1090
|
-
)}) (${stringifyArgs(exp)}) (check #1)`
|
1091
|
-
)
|
1092
|
-
else if (
|
1093
|
-
!isUnknownReturn(args[i][STATS]) &&
|
1094
|
-
!isUnknownReturn(env[name][STATS]) &&
|
1095
|
-
notABooleanReturn(args[i][STATS], env[name][STATS])
|
1096
|
-
)
|
1097
|
-
throw new TypeError(
|
1098
|
-
`Incorrect type of argument (${i}) for special form (${
|
1099
|
-
first[VALUE]
|
1100
|
-
}). Expected (${formatSubType(
|
1101
|
-
getTypes(args[i][STATS])
|
1102
|
-
)}) but got (${formatSubType(
|
1103
|
-
getReturns(env[name][STATS])
|
1104
|
-
)}) (${stringifyArgs(exp)}) (check #201)`
|
1105
|
-
)
|
1106
|
-
else {
|
1107
|
-
if (env[name] && getType(env[name][STATS]) === APPLY)
|
1108
|
-
switch (first[VALUE]) {
|
1109
|
-
case KEYWORDS.IF:
|
1110
|
-
break
|
1111
|
-
default:
|
1112
|
-
// TODO fix this assigment
|
1113
|
-
// It turns out it's not possible to determine return type of function here
|
1114
|
-
// what if it's a global function used elsewhere where the return type mwould be different
|
1115
|
-
// THIS willgive lambda return types but refactor is needed still
|
1116
|
-
if (!SPECIAL_FORMS_SET.has(name))
|
1117
|
-
setReturnRef(env[name][STATS], args[i][STATS])
|
1118
|
-
break
|
1119
|
-
}
|
1120
|
-
// TODO also handle casting
|
1121
|
-
}
|
1122
|
-
} else {
|
1181
|
+
// REFACTORING
|
1182
|
+
if (first[TYPE] === APPLY) {
|
1183
|
+
if (isLeaf(rest[i])) {
|
1123
1184
|
switch (rest[i][TYPE]) {
|
1124
1185
|
case WORD:
|
1125
1186
|
{
|
1126
1187
|
const name = rest[i][VALUE]
|
1127
1188
|
if (!env[name]) continue
|
1128
|
-
|
1189
|
+
const isKnown =
|
1129
1190
|
!isUnknownType(args[i][STATS]) &&
|
1130
|
-
!isUnknownType(env[name][STATS])
|
1191
|
+
!isUnknownType(env[name][STATS])
|
1192
|
+
if (
|
1193
|
+
isKnown &&
|
1194
|
+
env[name][STATS][ARG_COUNT] !== VARIADIC
|
1195
|
+
) {
|
1196
|
+
if (
|
1197
|
+
env[name][STATS][ARG_COUNT] !==
|
1198
|
+
args[i][STATS][ARG_COUNT]
|
1199
|
+
) {
|
1200
|
+
// TODO: Investigate why there used to be and error called #111 with this condition if (args[i][STATS][ARG_COUNT] === undefined)
|
1201
|
+
if (getType(args[i][STATS]) === APPLY)
|
1202
|
+
throw new TypeError(
|
1203
|
+
`Incorrect number of arguments for (${
|
1204
|
+
args[i][STATS][SIGNATURE]
|
1205
|
+
}) the (${
|
1206
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
1207
|
+
}) argument of (${
|
1208
|
+
first[VALUE]
|
1209
|
+
}) at position (${i}). Expected (= ${
|
1210
|
+
args[i][STATS][ARG_COUNT]
|
1211
|
+
}) but got ${
|
1212
|
+
env[name][STATS][ARG_COUNT]
|
1213
|
+
} (${stringifyArgs(exp)}) (check #778)`
|
1214
|
+
)
|
1215
|
+
}
|
1216
|
+
}
|
1217
|
+
if (
|
1218
|
+
isKnown &&
|
1131
1219
|
!compareTypes(args[i][STATS], env[name][STATS])
|
1132
1220
|
)
|
1133
1221
|
throw new TypeError(
|
1134
|
-
`Incorrect type of argument (${i}) for
|
1222
|
+
`Incorrect type of argument (${i}) for (${
|
1135
1223
|
first[VALUE]
|
1136
1224
|
}). Expected (${toTypeNames(
|
1137
1225
|
getType(args[i][STATS])
|
@@ -1140,12 +1228,12 @@ export const typeCheck = (ast) => {
|
|
1140
1228
|
)}) (${stringifyArgs(exp)}) (check #3)`
|
1141
1229
|
)
|
1142
1230
|
else if (
|
1143
|
-
|
1144
|
-
!isUnknownType(env[name][STATS]) &&
|
1231
|
+
isKnown &&
|
1145
1232
|
notABooleanType(args[i][STATS], env[name][STATS])
|
1233
|
+
// TODO: Add a check if subtype is a UKNOWN (for uknown array)
|
1146
1234
|
)
|
1147
1235
|
throw new TypeError(
|
1148
|
-
`Incorrect type of argument (${i}) for
|
1236
|
+
`Incorrect type of argument (${i}) for (${
|
1149
1237
|
first[VALUE]
|
1150
1238
|
}). Expected (${formatSubType(
|
1151
1239
|
getTypes(args[i][STATS])
|
@@ -1166,7 +1254,8 @@ export const typeCheck = (ast) => {
|
|
1166
1254
|
// check(exp, env, scope)
|
1167
1255
|
// )
|
1168
1256
|
// } else
|
1169
|
-
|
1257
|
+
if (isSpecial)
|
1258
|
+
setType(env[name][STATS], args[i][STATS])
|
1170
1259
|
}
|
1171
1260
|
}
|
1172
1261
|
break
|
@@ -1176,7 +1265,7 @@ export const typeCheck = (ast) => {
|
|
1176
1265
|
rest[i][TYPE] !== args[i][STATS][TYPE_PROP][0]
|
1177
1266
|
)
|
1178
1267
|
throw new TypeError(
|
1179
|
-
`Incorrect type of argument (${i}) for
|
1268
|
+
`Incorrect type of argument (${i}) for (${
|
1180
1269
|
first[VALUE]
|
1181
1270
|
}). Expected (${toTypeNames(
|
1182
1271
|
args[i][STATS][TYPE_PROP][0]
|
@@ -1190,371 +1279,184 @@ export const typeCheck = (ast) => {
|
|
1190
1279
|
!isAtomABoolean(rest[i][VALUE])
|
1191
1280
|
)
|
1192
1281
|
throw new TypeError(
|
1193
|
-
`Incorrect type of argument (${i}) for
|
1282
|
+
`Incorrect type of argument (${i}) for (${
|
1194
1283
|
first[VALUE]
|
1195
1284
|
}). Expected (${formatSubType(
|
1196
1285
|
getTypes(args[i][STATS])
|
1197
|
-
)}) but got (${
|
1198
|
-
|
1199
|
-
|
1286
|
+
)}) but got (${
|
1287
|
+
rest[i][TYPE] === ATOM
|
1288
|
+
? toTypeNames(rest[i][TYPE])
|
1289
|
+
: formatSubType(
|
1290
|
+
getTypes(env[rest[i][VALUE]][STATS])
|
1291
|
+
)
|
1292
|
+
}) (${stringifyArgs(exp)}) (check #203)`
|
1200
1293
|
)
|
1201
1294
|
break
|
1202
1295
|
}
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
// type checking
|
1207
|
-
else if (isResLeaf) {
|
1208
|
-
const T =
|
1209
|
-
rest[i][TYPE] === WORD
|
1210
|
-
? env[rest[i][VALUE]]
|
1211
|
-
? getType(env[rest[i][VALUE]][STATS])
|
1212
|
-
: UNKNOWN
|
1213
|
-
: rest[i][TYPE]
|
1214
|
-
|
1215
|
-
if (T === ATOM && !isUnknownType(args[i][STATS])) {
|
1216
|
-
if (getType(args[i][STATS]) !== ATOM)
|
1217
|
-
throw new TypeError(
|
1218
|
-
`Incorrect type of argument (${i}) for (${
|
1219
|
-
first[VALUE]
|
1220
|
-
}). Expected (${toTypeNames(
|
1221
|
-
getType(args[i][STATS])
|
1222
|
-
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
1223
|
-
exp
|
1224
|
-
)}) (check #10)`
|
1225
|
-
)
|
1226
|
-
else if (
|
1227
|
-
rest[i][TYPE] === ATOM
|
1228
|
-
? hasSubType(args[i][STATS]) &&
|
1229
|
-
getSubType(args[i][STATS]).has(PREDICATE) &&
|
1230
|
-
!isAtomABoolean(rest[i][VALUE])
|
1231
|
-
: notABooleanType(
|
1232
|
-
args[i][STATS],
|
1233
|
-
env[rest[i][VALUE]][STATS]
|
1234
|
-
)
|
1235
|
-
)
|
1236
|
-
throw new TypeError(
|
1237
|
-
`Incorrect type of argument (${i}) for special form (${
|
1238
|
-
first[VALUE]
|
1239
|
-
}). Expected (${formatSubType(
|
1240
|
-
getTypes(args[i][STATS])
|
1241
|
-
)}) but got (${
|
1242
|
-
rest[i][TYPE] === ATOM
|
1243
|
-
? toTypeNames(rest[i][TYPE])
|
1244
|
-
: formatSubType(
|
1245
|
-
getTypes(env[rest[i][VALUE]][STATS])
|
1246
|
-
)
|
1247
|
-
}) (${stringifyArgs(exp)}) (check #205)`
|
1248
|
-
)
|
1249
|
-
} else if (
|
1250
|
-
T === APPLY &&
|
1251
|
-
!isUnknownType(args[i][STATS]) &&
|
1252
|
-
!isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
1253
|
-
env[rest[i][VALUE]][STATS][ARG_COUNT] !== VARIADIC
|
1254
|
-
) {
|
1255
|
-
// if (
|
1256
|
-
// getType(args[i][STATS]) !==
|
1257
|
-
// getType(env[rest[i][VALUE]][STATS][ARGUMENTS][i][STATS])
|
1258
|
-
// )
|
1259
|
-
// // TODO this should really happen in 10 or 16
|
1260
|
-
// throw new TypeError(
|
1261
|
-
// `Incorrect type for argument of (${
|
1262
|
-
// first[VALUE]
|
1263
|
-
// }) at position (${i}). Expected (${
|
1264
|
-
// STATIC_TYPES.ABSTRACTION
|
1265
|
-
// }) but got (${toTypeNames(
|
1266
|
-
// getType(
|
1267
|
-
// env[rest[i][VALUE]][STATS][ARGUMENTS][i][STATS]
|
1268
|
-
// )
|
1269
|
-
// )}) (${stringifyArgs(exp)}) (check #111)`
|
1270
|
-
// )
|
1271
|
-
// // Handles words that are Lambdas
|
1272
|
-
// else
|
1273
|
-
if (
|
1274
|
-
env[rest[i][VALUE]][STATS][ARG_COUNT] !==
|
1275
|
-
args[i][STATS][ARG_COUNT]
|
1276
|
-
) {
|
1277
|
-
if (args[i][STATS][ARG_COUNT] === undefined)
|
1278
|
-
throw new TypeError(
|
1279
|
-
`Incorrect type for argument of (${
|
1280
|
-
first[VALUE]
|
1281
|
-
}) at position (${i}). Expected (${
|
1282
|
-
STATIC_TYPES.ABSTRACTION
|
1283
|
-
}) but got (${toTypeNames(
|
1284
|
-
getType(args[i][STATS])
|
1285
|
-
)}) (${stringifyArgs(exp)}) (check #111)`
|
1286
|
-
)
|
1287
|
-
else if (getType(args[i][STATS]) === APPLY)
|
1288
|
-
throw new TypeError(
|
1289
|
-
`Incorrect number of arguments for (${
|
1290
|
-
args[i][STATS][SIGNATURE]
|
1291
|
-
}) the (${
|
1292
|
-
KEYWORDS.ANONYMOUS_FUNCTION
|
1293
|
-
}) argument of (${
|
1294
|
-
first[VALUE]
|
1295
|
-
}) at position (${i}). Expected (= ${
|
1296
|
-
args[i][STATS][ARG_COUNT]
|
1297
|
-
}) but got ${
|
1298
|
-
env[rest[i][VALUE]][STATS][ARG_COUNT]
|
1299
|
-
} (${stringifyArgs(exp)}) (check #778)`
|
1300
|
-
)
|
1301
|
-
} else {
|
1302
|
-
// DEFINED LAMBDAS TYPE CHECKING
|
1303
|
-
// #C1
|
1304
|
-
// TODO delete this maybe
|
1305
|
-
// It will not be possilbe to know return type
|
1306
|
-
const match1 = () => {
|
1307
|
-
const actual = env[rest[i][VALUE]]
|
1308
|
-
const expected = args[i]
|
1296
|
+
case APPLY: {
|
1297
|
+
const name = rest[i][VALUE]
|
1298
|
+
if (!env[name]) continue
|
1309
1299
|
if (
|
1310
|
-
!
|
1311
|
-
!
|
1312
|
-
|
1300
|
+
!isUnknownType(args[i][STATS]) &&
|
1301
|
+
!isUnknownType(env[name][STATS]) &&
|
1302
|
+
env[name][STATS][ARG_COUNT] !== VARIADIC
|
1313
1303
|
) {
|
1314
|
-
throw new TypeError(
|
1315
|
-
`Incorrect return type for (${
|
1316
|
-
expected[STATS][SIGNATURE]
|
1317
|
-
}) the (${
|
1318
|
-
KEYWORDS.ANONYMOUS_FUNCTION
|
1319
|
-
}) argument of (${
|
1320
|
-
first[VALUE]
|
1321
|
-
}) at position (${i}). Expected (${toTypeNames(
|
1322
|
-
getReturn(expected[STATS])
|
1323
|
-
)}) but got (${toTypeNames(
|
1324
|
-
getReturn(actual[STATS])
|
1325
|
-
)}) (${stringifyArgs(exp)}) (check #782)`
|
1326
|
-
)
|
1327
|
-
} else retry(actual[STATS], stack, () => match1())
|
1328
|
-
}
|
1329
|
-
match1()
|
1330
|
-
for (
|
1331
|
-
let j = 0;
|
1332
|
-
j < args[i][STATS][ARGUMENTS].length;
|
1333
|
-
++j
|
1334
|
-
) {
|
1335
|
-
const match2 = () => {
|
1336
|
-
const actual =
|
1337
|
-
env[rest[i][VALUE]][STATS][ARGUMENTS][j]
|
1338
|
-
const expected = args[i][STATS][ARGUMENTS][j]
|
1339
1304
|
if (
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1305
|
+
env[name][STATS][ARG_COUNT] !==
|
1306
|
+
args[i][STATS][ARG_COUNT]
|
1307
|
+
) {
|
1308
|
+
if (args[i][STATS][ARG_COUNT] === undefined)
|
1309
|
+
throw new TypeError(
|
1310
|
+
`Incorrect type for argument of (${
|
1311
|
+
first[VALUE]
|
1312
|
+
}) at position (${i}). Expected (${
|
1313
|
+
STATIC_TYPES.ABSTRACTION
|
1314
|
+
}) but got (${toTypeNames(
|
1315
|
+
getType(args[i][STATS])
|
1316
|
+
)}) (${stringifyArgs(exp)}) (check #111)`
|
1317
|
+
)
|
1318
|
+
else if (getType(args[i][STATS]) === APPLY)
|
1319
|
+
throw new TypeError(
|
1320
|
+
`Incorrect number of arguments for (${
|
1321
|
+
args[i][STATS][SIGNATURE]
|
1322
|
+
}) the (${
|
1323
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
1324
|
+
}) argument of (${
|
1325
|
+
first[VALUE]
|
1326
|
+
}) at position (${i}). Expected (= ${
|
1327
|
+
args[i][STATS][ARG_COUNT]
|
1328
|
+
}) but got ${
|
1329
|
+
env[name][STATS][ARG_COUNT]
|
1330
|
+
} (${stringifyArgs(exp)}) (check #778)`
|
1331
|
+
)
|
1332
|
+
}
|
1333
|
+
}
|
1334
|
+
// DEFINED LAMBDAS TYPE CHECKING
|
1335
|
+
// #C1
|
1336
|
+
// TODO delete this maybe
|
1337
|
+
// It will not be possilbe to know return type
|
1338
|
+
const match1 = () => {
|
1339
|
+
const actual = env[name]
|
1340
|
+
const expected = args[i]
|
1341
|
+
if (
|
1342
|
+
!isUnknownReturn(expected[STATS]) &&
|
1343
|
+
!isUnknownReturn(actual[STATS]) &&
|
1344
|
+
!compareReturns(expected[STATS], actual[STATS])
|
1345
|
+
) {
|
1344
1346
|
throw new TypeError(
|
1345
|
-
`Incorrect type for (${
|
1347
|
+
`Incorrect return type for (${
|
1348
|
+
expected[STATS][SIGNATURE]
|
1349
|
+
}) the (${
|
1346
1350
|
KEYWORDS.ANONYMOUS_FUNCTION
|
1347
|
-
}) (${
|
1348
|
-
|
1349
|
-
})
|
1350
|
-
|
1351
|
-
}). Expected (${toTypeNames(
|
1352
|
-
getType(expected[STATS])
|
1351
|
+
}) argument of (${
|
1352
|
+
first[VALUE]
|
1353
|
+
}) at position (${i}). Expected (${toTypeNames(
|
1354
|
+
getReturn(expected[STATS])
|
1353
1355
|
)}) but got (${toTypeNames(
|
1354
|
-
|
1355
|
-
)}) (${stringifyArgs(exp)}) (check #
|
1356
|
+
getReturn(actual[STATS])
|
1357
|
+
)}) (${stringifyArgs(exp)}) (check #782)`
|
1356
1358
|
)
|
1357
|
-
else retry(actual[STATS], stack, () =>
|
1359
|
+
} else retry(actual[STATS], stack, () => match1())
|
1360
|
+
}
|
1361
|
+
match1()
|
1362
|
+
for (
|
1363
|
+
let j = 0;
|
1364
|
+
j < args[i][STATS][ARGUMENTS].length;
|
1365
|
+
++j
|
1366
|
+
) {
|
1367
|
+
const match2 = () => {
|
1368
|
+
const actual = env[name][STATS][ARGUMENTS][j]
|
1369
|
+
const expected = args[i][STATS][ARGUMENTS][j]
|
1370
|
+
if (
|
1371
|
+
!isUnknownType(actual[STATS]) &&
|
1372
|
+
!isUnknownType(expected[STATS]) &&
|
1373
|
+
!compareTypes(actual[STATS], expected[STATS])
|
1374
|
+
)
|
1375
|
+
throw new TypeError(
|
1376
|
+
`Incorrect type for (${
|
1377
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
1378
|
+
}) (${
|
1379
|
+
args[i][STATS][SIGNATURE]
|
1380
|
+
}) argument at position (${j}) named as (${
|
1381
|
+
actual[STATS][SIGNATURE]
|
1382
|
+
}). Expected (${toTypeNames(
|
1383
|
+
getType(expected[STATS])
|
1384
|
+
)}) but got (${toTypeNames(
|
1385
|
+
getType(actual[STATS])
|
1386
|
+
)}) (${stringifyArgs(exp)}) (check #781)`
|
1387
|
+
)
|
1388
|
+
else retry(actual[STATS], stack, () => match2())
|
1389
|
+
}
|
1390
|
+
match2()
|
1358
1391
|
}
|
1359
|
-
match2()
|
1360
1392
|
}
|
1361
1393
|
}
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
!isUnknownType(args[i][STATS]) &&
|
1368
|
-
!compareTypes(env[rest[i][VALUE]][STATS], args[i][STATS])
|
1369
|
-
) {
|
1370
|
-
throw new TypeError(
|
1371
|
-
`Incorrect type of argument (${i}) for (${
|
1372
|
-
first[VALUE]
|
1373
|
-
}). Expected (${toTypeNames(
|
1374
|
-
getType(args[i][STATS])
|
1375
|
-
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
1376
|
-
exp
|
1377
|
-
)}) (check #30)`
|
1378
|
-
)
|
1379
|
-
} else if (isUnknownType(args[i][STATS])) {
|
1380
|
-
retry(args[i][STATS], stack, () => check(exp, env, scope))
|
1381
|
-
}
|
1382
|
-
// TOODO maybe we don't need this
|
1383
|
-
else if (
|
1384
|
-
env[rest[i][VALUE]] &&
|
1385
|
-
!isUnknownType(args[i][STATS]) &&
|
1386
|
-
isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
1387
|
-
getType(args[i][STATS]) !== APPLY
|
1388
|
-
) {
|
1389
|
-
// REFF ASSIGMENT
|
1390
|
-
setTypeRef(env[rest[i][VALUE]][STATS], args[i][STATS])
|
1391
|
-
} else if (
|
1392
|
-
env[rest[i][VALUE]] &&
|
1393
|
-
!isUnknownType(args[i][STATS]) &&
|
1394
|
-
isUnknownType(env[rest[i][VALUE]][STATS])
|
1395
|
-
) {
|
1396
|
-
setStatsRef(env[rest[i][VALUE]], args[i])
|
1397
|
-
}
|
1398
|
-
} else if (env[rest[i][0][VALUE]]) {
|
1399
|
-
const match = () => {
|
1400
|
-
const actual =
|
1401
|
-
rest[i][0][VALUE] === KEYWORDS.CREATE_ARRAY
|
1402
|
-
? initArrayType({ rem: rest[i], env }) ??
|
1403
|
-
env[rest[i][0][VALUE]][STATS]
|
1404
|
-
: env[rest[i][0][VALUE]][STATS]
|
1405
|
-
const expected = args[i][STATS]
|
1406
|
-
retryArgs(args[i][STATS], stack, () => match())
|
1407
|
-
if (!isUnknownType(expected) && !isUnknownReturn(actual))
|
1408
|
-
if (!compareTypeWithReturn(expected, actual))
|
1409
|
-
throw new TypeError(
|
1410
|
-
`Incorrect type of argument (${i}) for (${
|
1411
|
-
first[VALUE]
|
1412
|
-
}). Expected (${toTypeNames(
|
1413
|
-
getType(expected)
|
1414
|
-
)}) but got (${toTypeNames(
|
1415
|
-
getReturn(actual)
|
1416
|
-
)}) (${stringifyArgs(exp)}) (check #16)`
|
1417
|
-
)
|
1418
|
-
else if (notABooleanReturn(expected, actual)) {
|
1419
|
-
throw new TypeError(
|
1420
|
-
`Incorrect type of argument (${i}) for (${
|
1421
|
-
first[VALUE]
|
1422
|
-
}). Expected (${formatSubType(
|
1423
|
-
getTypes(expected)
|
1424
|
-
)}) but got (${formatSubType(
|
1425
|
-
getReturns(actual)
|
1426
|
-
)}) (${stringifyArgs(exp)}) (check #206)`
|
1394
|
+
if (!isSpecial) {
|
1395
|
+
const name = rest[i][VALUE]
|
1396
|
+
if (isUnknownType(args[i][STATS])) {
|
1397
|
+
retry(args[i][STATS], stack, () =>
|
1398
|
+
check(exp, env, scope)
|
1427
1399
|
)
|
1428
|
-
} else {
|
1429
|
-
switch (getType(expected)) {
|
1430
|
-
// almost exclusively for anonymous lambdas
|
1431
|
-
case APPLY:
|
1432
|
-
{
|
1433
|
-
const argsN = rest[i].length - 2
|
1434
|
-
if (
|
1435
|
-
env[rest[i][0][VALUE]][STATS][SIGNATURE] ===
|
1436
|
-
KEYWORDS.ANONYMOUS_FUNCTION
|
1437
|
-
) {
|
1438
|
-
if (argsN !== args[i][STATS][ARG_COUNT])
|
1439
|
-
throw new TypeError(
|
1440
|
-
`Incorrect number of arguments for (${
|
1441
|
-
args[i][STATS][SIGNATURE]
|
1442
|
-
}) the (${
|
1443
|
-
KEYWORDS.ANONYMOUS_FUNCTION
|
1444
|
-
}) argument of (${
|
1445
|
-
first[VALUE]
|
1446
|
-
}) at position (${i}). Expected (= ${
|
1447
|
-
args[i][STATS][ARG_COUNT]
|
1448
|
-
}) but got ${argsN} (${stringifyArgs(
|
1449
|
-
exp
|
1450
|
-
)}) (check #777)`
|
1451
|
-
)
|
1452
|
-
else {
|
1453
|
-
// ANONYMOUS LAMBDAS TYPE CHECKING
|
1454
|
-
const local = Object.create(env)
|
1455
|
-
const lambdaName = `${ANONYMOUS_FUNCTION_TYPE_PREFIX}${i}::${++scopeIndex}`
|
1456
|
-
check(
|
1457
|
-
[
|
1458
|
-
[APPLY, KEYWORDS.DEFINE_VARIABLE],
|
1459
|
-
[WORD, lambdaName],
|
1460
|
-
rest[i]
|
1461
|
-
],
|
1462
|
-
local,
|
1463
|
-
scope
|
1464
|
-
)
|
1465
|
-
// TODO delete this maybe
|
1466
|
-
// #C2
|
1467
|
-
// It will not be possilbe to know return type
|
1468
|
-
const match1 = () => {
|
1469
|
-
const actual = local[lambdaName]
|
1470
|
-
const expected = args[i]
|
1471
|
-
if (
|
1472
|
-
!isUnknownReturn(expected[STATS]) &&
|
1473
|
-
!isUnknownReturn(actual[STATS]) &&
|
1474
|
-
!compareReturns(
|
1475
|
-
expected[STATS],
|
1476
|
-
actual[STATS]
|
1477
|
-
)
|
1478
|
-
)
|
1479
|
-
throw new TypeError(
|
1480
|
-
`Incorrect return type for (${
|
1481
|
-
expected[STATS][SIGNATURE]
|
1482
|
-
}) the (${
|
1483
|
-
KEYWORDS.ANONYMOUS_FUNCTION
|
1484
|
-
}) argument of (${
|
1485
|
-
first[VALUE]
|
1486
|
-
}) at position (${i}). Expected (${toTypeNames(
|
1487
|
-
getReturn(expected[STATS])
|
1488
|
-
)}) but got (${toTypeNames(
|
1489
|
-
getReturn(actual[STATS])
|
1490
|
-
)}) (${stringifyArgs(
|
1491
|
-
exp
|
1492
|
-
)}) (check #779)`
|
1493
|
-
)
|
1494
|
-
else
|
1495
|
-
retry(actual[STATS], stack, () =>
|
1496
|
-
match1()
|
1497
|
-
)
|
1498
|
-
}
|
1499
|
-
match1()
|
1500
|
-
for (
|
1501
|
-
let j = 0;
|
1502
|
-
j < args[i][STATS][ARGUMENTS].length;
|
1503
|
-
++j
|
1504
|
-
) {
|
1505
|
-
const match2 = () => {
|
1506
|
-
const actual =
|
1507
|
-
local[lambdaName][STATS][ARGUMENTS][j]
|
1508
|
-
const expected =
|
1509
|
-
args[i][STATS][ARGUMENTS][j]
|
1510
|
-
if (
|
1511
|
-
!isUnknownType(actual[STATS]) &&
|
1512
|
-
!isUnknownType(expected[STATS]) &&
|
1513
|
-
!compareTypes(
|
1514
|
-
actual[STATS],
|
1515
|
-
expected[STATS]
|
1516
|
-
)
|
1517
|
-
)
|
1518
|
-
throw new TypeError(
|
1519
|
-
`Incorrect type for (${
|
1520
|
-
KEYWORDS.ANONYMOUS_FUNCTION
|
1521
|
-
}) (${
|
1522
|
-
args[i][STATS][SIGNATURE]
|
1523
|
-
}) argument at position (${j}) named as (${
|
1524
|
-
local[lambdaName][STATS][
|
1525
|
-
ARGUMENTS
|
1526
|
-
][j][STATS][SIGNATURE]
|
1527
|
-
}). Expected (${toTypeNames(
|
1528
|
-
getType(expected[STATS])
|
1529
|
-
)}) but got (${toTypeNames(
|
1530
|
-
getType(actual[STATS])
|
1531
|
-
)}) (${stringifyArgs(
|
1532
|
-
exp
|
1533
|
-
)}) (check #780)`
|
1534
|
-
)
|
1535
|
-
else
|
1536
|
-
retry(actual[STATS], stack, () =>
|
1537
|
-
match2()
|
1538
|
-
)
|
1539
|
-
}
|
1540
|
-
match2()
|
1541
|
-
}
|
1542
|
-
}
|
1543
|
-
} else {
|
1544
|
-
// TODO fix curry: lambdas enter here as undefined
|
1545
|
-
}
|
1546
|
-
}
|
1547
|
-
break
|
1548
|
-
// case ATOM:
|
1549
|
-
// case COLLECTION:
|
1550
|
-
// break
|
1551
|
-
}
|
1552
1400
|
}
|
1553
|
-
|
1554
|
-
|
1401
|
+
// TOODO maybe we don't need this
|
1402
|
+
else if (
|
1403
|
+
env[name] &&
|
1404
|
+
!isUnknownType(args[i][STATS]) &&
|
1405
|
+
isUnknownType(env[name][STATS]) &&
|
1406
|
+
getType(args[i][STATS]) !== APPLY
|
1407
|
+
) {
|
1408
|
+
// REFF ASSIGMENT
|
1409
|
+
setTypeRef(env[name][STATS], args[i][STATS])
|
1410
|
+
} else if (
|
1411
|
+
env[name] &&
|
1412
|
+
!isUnknownType(args[i][STATS]) &&
|
1413
|
+
isUnknownType(env[name][STATS])
|
1414
|
+
) {
|
1415
|
+
setStatsRef(env[rest[i][VALUE]], args[i])
|
1416
|
+
}
|
1417
|
+
}
|
1418
|
+
} else {
|
1419
|
+
const name = rest[i][0][VALUE]
|
1420
|
+
if (!env[name]) continue
|
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)
|
1427
|
+
)
|
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)
|
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 })
|
1555
1457
|
}
|
1556
|
-
match()
|
1557
1458
|
}
|
1459
|
+
// REFACTORING
|
1558
1460
|
}
|
1559
1461
|
}
|
1560
1462
|
})
|
@@ -1577,7 +1479,7 @@ export const typeCheck = (ast) => {
|
|
1577
1479
|
}
|
1578
1480
|
}
|
1579
1481
|
const copy = JSON.parse(JSON.stringify(ast))
|
1580
|
-
check(copy,
|
1482
|
+
check(copy, SPECIAL_FORM_TYPES, copy)
|
1581
1483
|
while (stack.length) stack.cut()()
|
1582
1484
|
return [ast, Types]
|
1583
1485
|
}
|