fez-lisp 1.5.130 → 1.5.132
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 +272 -262
- package/src/types.js +12 -12
- package/src/utils.js +21 -0
package/package.json
CHANGED
package/src/check.js
CHANGED
@@ -116,13 +116,13 @@ export const isUnknownNotAnyReturn = (stats) =>
|
|
116
116
|
export const castType = (stats, type) => {
|
117
117
|
return (
|
118
118
|
(stats[TYPE_PROP][0] = type[RETURNS][0]),
|
119
|
-
(stats[TYPE_PROP][1] = type[RETURNS][1])
|
119
|
+
type[RETURNS][1] && (stats[TYPE_PROP][1] = type[RETURNS][1])
|
120
120
|
)
|
121
121
|
}
|
122
122
|
export const castReturn = (stats, type) => {
|
123
123
|
return (
|
124
124
|
(stats[RETURNS][0] = type[RETURNS][0]),
|
125
|
-
(stats[RETURNS][1] = type[RETURNS][1])
|
125
|
+
stats[RETURNS][1] && (stats[RETURNS][1] = type[RETURNS][1])
|
126
126
|
)
|
127
127
|
}
|
128
128
|
export const isTypeAbstraction = (stats) => stats[TYPE_PROP] === APPLY
|
@@ -285,7 +285,7 @@ export const isAtomType = (stats) =>
|
|
285
285
|
isAnyType(stats) || stats[TYPE_PROP][0] === ATOM
|
286
286
|
export const isAtomReturn = (stats) =>
|
287
287
|
isAnyType(stats) || stats[RETURNS][0] === ATOM
|
288
|
-
export const
|
288
|
+
export const equalsTypes = (a, b) => {
|
289
289
|
const isAnyAny = isAnyType(a) || isAnyType(b)
|
290
290
|
if (isAnyAny) return true
|
291
291
|
const isSameType = a[TYPE_PROP][0] === b[TYPE_PROP][0]
|
@@ -293,9 +293,9 @@ export const compareTypes = (a, b) => {
|
|
293
293
|
return true
|
294
294
|
}
|
295
295
|
|
296
|
-
export const
|
296
|
+
export const equalsReturns = (a, b) =>
|
297
297
|
isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
|
298
|
-
export const
|
298
|
+
export const equalsTypeWithReturn = (a, b) =>
|
299
299
|
isAnyType(a) || isAnyReturn(b) || a[TYPE_PROP][0] === b[RETURNS][0]
|
300
300
|
const IsPredicate = (leaf) =>
|
301
301
|
(leaf[TYPE] === ATOM && (leaf[VALUE] === TRUE || leaf[VALUE] === FALSE)) ||
|
@@ -319,7 +319,7 @@ const notABooleanType = (a, b) => {
|
|
319
319
|
(hasSubType(b) && getSubType(a).difference(getSubType(b)).size !== 0))
|
320
320
|
)
|
321
321
|
}
|
322
|
-
const
|
322
|
+
const notABooleanTypeWithReturn = (a, b) => {
|
323
323
|
return (
|
324
324
|
hasSubType(a) &&
|
325
325
|
getSubType(a).has(PREDICATE) &&
|
@@ -328,6 +328,15 @@ const notABooleanReturn = (a, b) => {
|
|
328
328
|
(!hasSubReturn(b) || getSubType(a).difference(getSubReturn(b)).size !== 0)
|
329
329
|
)
|
330
330
|
}
|
331
|
+
const notABooleanReturn = (a, b) => {
|
332
|
+
return (
|
333
|
+
hasSubReturn(a) &&
|
334
|
+
getSubReturn(a).has(PREDICATE) &&
|
335
|
+
!isUnknownReturn(b) &&
|
336
|
+
!isAnyReturn(b) &&
|
337
|
+
(!hasSubReturn(b) || getSubReturn(a).difference(getSubReturn(b)).size !== 0)
|
338
|
+
)
|
339
|
+
}
|
331
340
|
const isAtomABoolean = (atom) => atom === TRUE || atom === FALSE
|
332
341
|
const checkPredicateName = (exp, rest) => {
|
333
342
|
if (getSuffix(rest[0][VALUE]) === PREDICATE_SUFFIX) {
|
@@ -406,19 +415,20 @@ const withScope = (name, scope) => {
|
|
406
415
|
const chain = getScopeNames(scope)
|
407
416
|
return `${chain.length === 1 ? '; ' : ''}${chain.join(' ')} ${name}`
|
408
417
|
}
|
409
|
-
const retry = (stats, stack, cb) => {
|
418
|
+
const retry = (stats, ctx, stack, cb) => {
|
410
419
|
if (
|
411
420
|
(isUnknownNotAnyType(stats) || isUnknownNotAnyReturn(stats)) &&
|
412
421
|
stats.retried < MAX_RETRY_DEFINITION
|
413
422
|
) {
|
414
423
|
stats.retried += 1
|
415
|
-
stack
|
424
|
+
stagger(stack, 'prepend', ctx, cb)
|
416
425
|
}
|
417
426
|
}
|
418
|
-
|
427
|
+
|
428
|
+
const retryArgs = (stats, ctx, stack, cb) => {
|
419
429
|
if (stats.counter < MAX_ARGUMENT_RETRY) {
|
420
430
|
stats.counter++
|
421
|
-
stack
|
431
|
+
stagger(stack, 'prepend', ctx, cb)
|
422
432
|
}
|
423
433
|
}
|
424
434
|
const IfApplyBranch = ({ leaf, branch, re, prop, ref, env }) => {
|
@@ -521,7 +531,7 @@ const resolveCondition = ({ rem, name, env, exp, prop }) => {
|
|
521
531
|
default:
|
522
532
|
if (env[ret[VALUE]]) setPropRef(ref[STATS], prop, env[ret[VALUE]][STATS])
|
523
533
|
else
|
524
|
-
stack
|
534
|
+
stagger(stack, 'append', exp, () => {
|
525
535
|
if (env[ret[VALUE]])
|
526
536
|
setPropRef(ref[STATS], prop, env[ret[VALUE]][STATS])
|
527
537
|
})
|
@@ -665,7 +675,7 @@ const resolveRetunType = ({ returns, rem, stack, prop, exp, name, env }) => {
|
|
665
675
|
GETTERS_SET.has(returns[VALUE]) &&
|
666
676
|
!resolveGetter({ rem, prop, name, env })
|
667
677
|
)
|
668
|
-
return retry(env[name][STATS], stack, () => {
|
678
|
+
return retry(env[name][STATS], [returns, env], stack, () => {
|
669
679
|
resolveRetunType({
|
670
680
|
returns,
|
671
681
|
rem,
|
@@ -686,7 +696,7 @@ const resolveRetunType = ({ returns, rem, stack, prop, exp, name, env }) => {
|
|
686
696
|
// rest.at(-1)[0][TYPE] === APPLY
|
687
697
|
// Here is upon application to store the result in the variable
|
688
698
|
if (isUnknownType(env[name][STATS]))
|
689
|
-
stack
|
699
|
+
stagger(stack, 'prepend', exp, () => {
|
690
700
|
setTypeToReturnRef(
|
691
701
|
env[name][STATS],
|
692
702
|
env[returns[VALUE]][STATS]
|
@@ -716,11 +726,188 @@ const checkReturnType = ({ exp, stack, name, env }) => {
|
|
716
726
|
stack
|
717
727
|
})
|
718
728
|
}
|
729
|
+
const stagger = (stack, method, data, fn) => {
|
730
|
+
// console.log(data[0], data[1])
|
731
|
+
stack[method]({ data, fn })
|
732
|
+
}
|
719
733
|
export const typeCheck = (ast) => {
|
720
|
-
let scopeIndex = 0
|
721
|
-
const root = structuredClone(SPECIAL_FORM_TYPES)
|
722
734
|
const Types = new Map()
|
723
735
|
const stack = new Brr()
|
736
|
+
let scopeIndex = 0
|
737
|
+
// TODO also handle casting
|
738
|
+
const match = ({ rest, args, i, env, scope, exp }) => {
|
739
|
+
const first = exp[0]
|
740
|
+
const actual =
|
741
|
+
rest[i][0][VALUE] === KEYWORDS.CREATE_ARRAY
|
742
|
+
? initArrayType({ rem: rest[i], env }) ?? env[rest[i][0][VALUE]][STATS]
|
743
|
+
: env[rest[i][0][VALUE]][STATS]
|
744
|
+
const expected = args[i][STATS]
|
745
|
+
retryArgs(args[i][STATS], exp, stack, () =>
|
746
|
+
match({ rest, args, i, env, scope, exp })
|
747
|
+
)
|
748
|
+
if (!isUnknownType(expected) && !isUnknownReturn(actual))
|
749
|
+
if (!equalsTypeWithReturn(expected, actual))
|
750
|
+
throw new TypeError(
|
751
|
+
`Incorrect type of argument (${i}) for (${
|
752
|
+
first[VALUE]
|
753
|
+
}). Expected (${toTypeNames(
|
754
|
+
getType(expected)
|
755
|
+
)}) but got (${toTypeNames(getReturn(actual))}) (${stringifyArgs(
|
756
|
+
exp
|
757
|
+
)}) (check #16)`
|
758
|
+
)
|
759
|
+
else if (notABooleanTypeWithReturn(expected, actual)) {
|
760
|
+
throw new TypeError(
|
761
|
+
`Incorrect type of argument (${i}) for (${
|
762
|
+
first[VALUE]
|
763
|
+
}). Expected (${formatSubType(
|
764
|
+
getTypes(expected)
|
765
|
+
)}) but got (${formatSubType(getReturns(actual))}) (${stringifyArgs(
|
766
|
+
exp
|
767
|
+
)}) (check #206)`
|
768
|
+
)
|
769
|
+
} else {
|
770
|
+
switch (getType(expected)) {
|
771
|
+
// almost exclusively for anonymous lambdas
|
772
|
+
case APPLY:
|
773
|
+
{
|
774
|
+
const argsN = rest[i].length - 2
|
775
|
+
if (
|
776
|
+
env[rest[i][0][VALUE]][STATS][SIGNATURE] ===
|
777
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
778
|
+
) {
|
779
|
+
if (argsN !== args[i][STATS][ARG_COUNT])
|
780
|
+
throw new TypeError(
|
781
|
+
`Incorrect number of arguments for (${
|
782
|
+
args[i][STATS][SIGNATURE]
|
783
|
+
}) the (${KEYWORDS.ANONYMOUS_FUNCTION}) argument of (${
|
784
|
+
first[VALUE]
|
785
|
+
}) at position (${i}). Expected (= ${
|
786
|
+
args[i][STATS][ARG_COUNT]
|
787
|
+
}) but got ${argsN} (${stringifyArgs(exp)}) (check #777)`
|
788
|
+
)
|
789
|
+
else {
|
790
|
+
// ANONYMOUS LAMBDAS TYPE CHECKING
|
791
|
+
const local = Object.create(env)
|
792
|
+
const lambdaName = `${ANONYMOUS_FUNCTION_TYPE_PREFIX}${i}::${++scopeIndex}`
|
793
|
+
check(
|
794
|
+
[
|
795
|
+
[APPLY, KEYWORDS.DEFINE_VARIABLE],
|
796
|
+
[WORD, lambdaName],
|
797
|
+
rest[i]
|
798
|
+
],
|
799
|
+
local,
|
800
|
+
scope
|
801
|
+
)
|
802
|
+
// TODO delete this maybe
|
803
|
+
// #C2
|
804
|
+
// It will not be possilbe to know return type
|
805
|
+
const match1 = () => {
|
806
|
+
const actual = local[lambdaName]
|
807
|
+
const expected = args[i]
|
808
|
+
if (
|
809
|
+
!isUnknownReturn(expected[STATS]) &&
|
810
|
+
!isUnknownReturn(actual[STATS]) &&
|
811
|
+
!equalsReturns(expected[STATS], actual[STATS])
|
812
|
+
)
|
813
|
+
throw new TypeError(
|
814
|
+
`Incorrect return type for (${
|
815
|
+
expected[STATS][SIGNATURE]
|
816
|
+
}) the (${KEYWORDS.ANONYMOUS_FUNCTION}) argument of (${
|
817
|
+
first[VALUE]
|
818
|
+
}) at position (${i}). Expected (${toTypeNames(
|
819
|
+
getReturn(expected[STATS])
|
820
|
+
)}) but got (${toTypeNames(
|
821
|
+
getReturn(actual[STATS])
|
822
|
+
)}) (${stringifyArgs(exp)}) (check #779)`
|
823
|
+
)
|
824
|
+
else if (notABooleanReturn(expected[STATS], actual[STATS]))
|
825
|
+
throw new TypeError(
|
826
|
+
`Incorrect return type for (${
|
827
|
+
expected[STATS][SIGNATURE]
|
828
|
+
}) the (${KEYWORDS.ANONYMOUS_FUNCTION}) argument of (${
|
829
|
+
first[VALUE]
|
830
|
+
}) at position (${i}). Expected (${toTypeNames(
|
831
|
+
getReturn(expected[STATS])
|
832
|
+
)}) but got (${toTypeNames(
|
833
|
+
getReturn(actual[STATS])
|
834
|
+
)}) (${stringifyArgs(exp)}) (check #783)`
|
835
|
+
)
|
836
|
+
else
|
837
|
+
retry(
|
838
|
+
actual[STATS],
|
839
|
+
[[WORD, lambdaName], local],
|
840
|
+
stack,
|
841
|
+
match1
|
842
|
+
)
|
843
|
+
}
|
844
|
+
match1()
|
845
|
+
for (let j = 0; j < args[i][STATS][ARGUMENTS].length; ++j) {
|
846
|
+
const match2 = () => {
|
847
|
+
const actual = local[lambdaName][STATS][ARGUMENTS][j]
|
848
|
+
const expected = args[i][STATS][ARGUMENTS][j]
|
849
|
+
if (
|
850
|
+
!isUnknownType(actual[STATS]) &&
|
851
|
+
!isUnknownType(expected[STATS]) &&
|
852
|
+
!equalsTypes(actual[STATS], expected[STATS])
|
853
|
+
)
|
854
|
+
throw new TypeError(
|
855
|
+
`Incorrect type for (${
|
856
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
857
|
+
}) (${
|
858
|
+
args[i][STATS][SIGNATURE]
|
859
|
+
}) argument at position (${j}) named as (${
|
860
|
+
local[lambdaName][STATS][ARGUMENTS][j][STATS][
|
861
|
+
SIGNATURE
|
862
|
+
]
|
863
|
+
}). Expected (${toTypeNames(
|
864
|
+
getType(expected[STATS])
|
865
|
+
)}) but got (${toTypeNames(
|
866
|
+
getType(actual[STATS])
|
867
|
+
)}) (${stringifyArgs(exp)}) (check #780)`
|
868
|
+
)
|
869
|
+
else if (
|
870
|
+
notABooleanReturn(expected[STATS], actual[STATS])
|
871
|
+
)
|
872
|
+
throw new TypeError(
|
873
|
+
`Incorrect return type for (${
|
874
|
+
expected[STATS][SIGNATURE]
|
875
|
+
}) the (${
|
876
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
877
|
+
}) argument of (${
|
878
|
+
first[VALUE]
|
879
|
+
}) at position (${i}). Expected (${toTypeNames(
|
880
|
+
getReturn(expected[STATS])
|
881
|
+
)}) but got (${toTypeNames(
|
882
|
+
getReturn(actual[STATS])
|
883
|
+
)}) (${stringifyArgs(exp)}) (check #784)`
|
884
|
+
)
|
885
|
+
else
|
886
|
+
retry(
|
887
|
+
actual[STATS],
|
888
|
+
[[WORD, lambdaName], local],
|
889
|
+
stack,
|
890
|
+
match2
|
891
|
+
)
|
892
|
+
}
|
893
|
+
match2()
|
894
|
+
}
|
895
|
+
}
|
896
|
+
} else {
|
897
|
+
// TODO fix curry: lambdas enter here as undefined
|
898
|
+
}
|
899
|
+
}
|
900
|
+
break
|
901
|
+
// case ATOM:
|
902
|
+
// case COLLECTION:
|
903
|
+
// break
|
904
|
+
}
|
905
|
+
}
|
906
|
+
else if (isUnknownType(expected))
|
907
|
+
retry(args[i][STATS], [first, env], stack, () =>
|
908
|
+
match({ rest, args, i, env, scope, exp })
|
909
|
+
)
|
910
|
+
}
|
724
911
|
const check = (exp, env, scope) => {
|
725
912
|
const [first, ...rest] = isLeaf(exp) ? [exp] : exp
|
726
913
|
if (first === undefined)
|
@@ -732,7 +919,7 @@ export const typeCheck = (ast) => {
|
|
732
919
|
switch (first[TYPE]) {
|
733
920
|
case WORD:
|
734
921
|
if (!isSpecial)
|
735
|
-
stack
|
922
|
+
stagger(stack, 'append', [first, env], () => {
|
736
923
|
// Figure out how to determine if varible is define after it's used
|
737
924
|
if (env[first[VALUE]] === undefined) {
|
738
925
|
throw new TypeError(
|
@@ -787,7 +974,7 @@ export const typeCheck = (ast) => {
|
|
787
974
|
}) ||
|
788
975
|
isUnknownReturn(env[name][STATS])
|
789
976
|
) {
|
790
|
-
retry(env[name][STATS], stack, () => {
|
977
|
+
retry(env[name][STATS], [first, env], stack, () => {
|
791
978
|
checkReturnType({
|
792
979
|
stack,
|
793
980
|
exp,
|
@@ -906,13 +1093,16 @@ export const typeCheck = (ast) => {
|
|
906
1093
|
// TODO figure out what we do here
|
907
1094
|
// this here is a variable WORD
|
908
1095
|
// so return type of that function is that varible type
|
909
|
-
|
1096
|
+
stagger(
|
1097
|
+
stack,
|
1098
|
+
'append',
|
1099
|
+
[returns, copy],
|
910
1100
|
() =>
|
911
1101
|
copy[returns[VALUE]] &&
|
912
1102
|
setReturnToType(ref[STATS], copy[returns[VALUE]][STATS])
|
913
1103
|
)
|
914
1104
|
else {
|
915
|
-
stack
|
1105
|
+
stagger(stack, 'append', [returns, copy], () => {
|
916
1106
|
const ret = returns[0]
|
917
1107
|
switch (ret[VALUE]) {
|
918
1108
|
case KEYWORDS.IF:
|
@@ -929,7 +1119,7 @@ export const typeCheck = (ast) => {
|
|
929
1119
|
if (copy[ret[VALUE]])
|
930
1120
|
setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
|
931
1121
|
else
|
932
|
-
stack
|
1122
|
+
stagger(stack, 'append', [ret, copy], () => {
|
933
1123
|
if (copy[ret[VALUE]])
|
934
1124
|
setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
|
935
1125
|
})
|
@@ -950,7 +1140,7 @@ export const typeCheck = (ast) => {
|
|
950
1140
|
const ret = isLeaf(rest[0]) ? rest[0] : rest[0][0]
|
951
1141
|
const ref = env[ret[VALUE]]
|
952
1142
|
if (!ref) break
|
953
|
-
const caster =
|
1143
|
+
const caster = SPECIAL_FORM_TYPES[first[VALUE]]
|
954
1144
|
if (ret[TYPE] === APPLY && isUnknownReturn(ref[STATS]))
|
955
1145
|
castReturn(ref[STATS], caster[STATS])
|
956
1146
|
else if (isUnknownType(ref[STATS]))
|
@@ -963,9 +1153,8 @@ export const typeCheck = (ast) => {
|
|
963
1153
|
// So they MUST happen before Judgement
|
964
1154
|
resolveSetter(first, rest, env)
|
965
1155
|
// end of Var ---------------
|
966
|
-
|
967
1156
|
// Judgement
|
968
|
-
stack
|
1157
|
+
stagger(stack, 'append', [first, env], () => {
|
969
1158
|
if (!isSpecial && env[first[VALUE]] === undefined)
|
970
1159
|
throw new TypeError(
|
971
1160
|
`Trying to call undefined (${KEYWORDS.ANONYMOUS_FUNCTION}) ${first[VALUE]} (check #9)`
|
@@ -1082,7 +1271,7 @@ export const typeCheck = (ast) => {
|
|
1082
1271
|
}
|
1083
1272
|
if (
|
1084
1273
|
isKnown &&
|
1085
|
-
!
|
1274
|
+
!equalsTypes(args[i][STATS], env[name][STATS])
|
1086
1275
|
)
|
1087
1276
|
throw new TypeError(
|
1088
1277
|
`Incorrect type of argument (${i}) for (${
|
@@ -1114,12 +1303,16 @@ export const typeCheck = (ast) => {
|
|
1114
1303
|
// (let xs [])
|
1115
1304
|
// (let x (array:set-and-get! xs 0 100))
|
1116
1305
|
// (length x)
|
1117
|
-
|
1118
|
-
// if (
|
1119
|
-
//
|
1306
|
+
|
1307
|
+
// if (
|
1308
|
+
// isUnknownType(env[name][STATS]) &&
|
1309
|
+
// !env[name][STATS].tried
|
1310
|
+
// ) {
|
1311
|
+
// once(env[name][STATS], stack, () =>
|
1120
1312
|
// check(exp, env, scope)
|
1121
1313
|
// )
|
1122
|
-
// }
|
1314
|
+
// }
|
1315
|
+
|
1123
1316
|
if (isSpecial)
|
1124
1317
|
setType(env[name][STATS], args[i][STATS])
|
1125
1318
|
}
|
@@ -1207,7 +1400,7 @@ export const typeCheck = (ast) => {
|
|
1207
1400
|
if (
|
1208
1401
|
!isUnknownReturn(expected[STATS]) &&
|
1209
1402
|
!isUnknownReturn(actual[STATS]) &&
|
1210
|
-
!
|
1403
|
+
!equalsReturns(expected[STATS], actual[STATS])
|
1211
1404
|
) {
|
1212
1405
|
throw new TypeError(
|
1213
1406
|
`Incorrect return type for (${
|
@@ -1222,7 +1415,8 @@ export const typeCheck = (ast) => {
|
|
1222
1415
|
getReturn(actual[STATS])
|
1223
1416
|
)}) (${stringifyArgs(exp)}) (check #782)`
|
1224
1417
|
)
|
1225
|
-
} else
|
1418
|
+
} else
|
1419
|
+
retry(actual[STATS], [first, env], stack, match1)
|
1226
1420
|
}
|
1227
1421
|
match1()
|
1228
1422
|
for (
|
@@ -1236,7 +1430,7 @@ export const typeCheck = (ast) => {
|
|
1236
1430
|
if (
|
1237
1431
|
!isUnknownType(actual[STATS]) &&
|
1238
1432
|
!isUnknownType(expected[STATS]) &&
|
1239
|
-
!
|
1433
|
+
!equalsTypes(actual[STATS], expected[STATS])
|
1240
1434
|
)
|
1241
1435
|
throw new TypeError(
|
1242
1436
|
`Incorrect type for (${
|
@@ -1251,7 +1445,13 @@ export const typeCheck = (ast) => {
|
|
1251
1445
|
getType(actual[STATS])
|
1252
1446
|
)}) (${stringifyArgs(exp)}) (check #781)`
|
1253
1447
|
)
|
1254
|
-
else
|
1448
|
+
else
|
1449
|
+
retry(
|
1450
|
+
actual[STATS],
|
1451
|
+
[first, env],
|
1452
|
+
stack,
|
1453
|
+
match2
|
1454
|
+
)
|
1255
1455
|
}
|
1256
1456
|
match2()
|
1257
1457
|
}
|
@@ -1260,7 +1460,7 @@ export const typeCheck = (ast) => {
|
|
1260
1460
|
if (!isSpecial) {
|
1261
1461
|
const name = rest[i][VALUE]
|
1262
1462
|
if (isUnknownType(args[i][STATS])) {
|
1263
|
-
retry(args[i][STATS], stack, () =>
|
1463
|
+
retry(args[i][STATS], [first, env], stack, () =>
|
1264
1464
|
check(exp, env, scope)
|
1265
1465
|
)
|
1266
1466
|
}
|
@@ -1284,235 +1484,45 @@ export const typeCheck = (ast) => {
|
|
1284
1484
|
} else {
|
1285
1485
|
const name = rest[i][0][VALUE]
|
1286
1486
|
if (!env[name]) continue
|
1287
|
-
if (
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
check(
|
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])
|
1487
|
+
if (
|
1488
|
+
isUnknownReturn(env[name][STATS]) &&
|
1489
|
+
!env[name][STATS][IS_ARGUMENT]
|
1490
|
+
)
|
1491
|
+
return retry(
|
1492
|
+
env[name][STATS],
|
1493
|
+
[first, env],
|
1494
|
+
stack,
|
1495
|
+
() => check(exp, env, scope)
|
1324
1496
|
)
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
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()
|
1497
|
+
|
1498
|
+
if (isSpecial && name === KEYWORDS.IF) {
|
1499
|
+
const concequent = [...rest]
|
1500
|
+
const alternative = [...rest]
|
1501
|
+
concequent[i] = rest[i][1]
|
1502
|
+
alternative[i] = rest[i][2]
|
1503
|
+
check([first, ...concequent], env, scope)
|
1504
|
+
check([first, ...alternative], env, scope)
|
1515
1505
|
}
|
1506
|
+
|
1507
|
+
if (
|
1508
|
+
env[name] &&
|
1509
|
+
getType(env[name][STATS]) === APPLY &&
|
1510
|
+
!SPECIAL_FORMS_SET.has(name)
|
1511
|
+
)
|
1512
|
+
switch (first[VALUE]) {
|
1513
|
+
case KEYWORDS.IF:
|
1514
|
+
break
|
1515
|
+
default:
|
1516
|
+
// TODO fix this assigment
|
1517
|
+
// It turns out it's not possible to determine return type of function here
|
1518
|
+
// what if it's a global function used elsewhere where the return type mwould be different
|
1519
|
+
// THIS willgive lambda return types but refactor is needed still
|
1520
|
+
// if (!SPECIAL_FORMS_SET.has(name))
|
1521
|
+
setReturnRef(env[name][STATS], args[i][STATS])
|
1522
|
+
break
|
1523
|
+
}
|
1524
|
+
|
1525
|
+
match({ rest, args, i, env, scope, exp })
|
1516
1526
|
}
|
1517
1527
|
}
|
1518
1528
|
// REFACTORING
|
@@ -1538,8 +1548,8 @@ export const typeCheck = (ast) => {
|
|
1538
1548
|
}
|
1539
1549
|
}
|
1540
1550
|
const copy = JSON.parse(JSON.stringify(ast))
|
1541
|
-
check(copy,
|
1542
|
-
while (stack.length) stack.cut()()
|
1551
|
+
check(copy, SPECIAL_FORM_TYPES, copy)
|
1552
|
+
while (stack.length) stack.cut().fn()
|
1543
1553
|
return [ast, Types]
|
1544
1554
|
}
|
1545
1555
|
export const type = (ast) => typeCheck(ast)[0]
|
package/src/types.js
CHANGED
@@ -419,7 +419,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
419
419
|
}
|
420
420
|
}
|
421
421
|
],
|
422
|
-
[RETURNS]: [ATOM]
|
422
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
423
423
|
}
|
424
424
|
},
|
425
425
|
[KEYWORDS.MULTIPLICATION]: {
|
@@ -452,7 +452,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
452
452
|
}
|
453
453
|
}
|
454
454
|
],
|
455
|
-
[RETURNS]: [ATOM]
|
455
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
456
456
|
}
|
457
457
|
},
|
458
458
|
[KEYWORDS.SUBTRACTION]: {
|
@@ -485,7 +485,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
485
485
|
}
|
486
486
|
}
|
487
487
|
],
|
488
|
-
[RETURNS]: [ATOM]
|
488
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
489
489
|
}
|
490
490
|
},
|
491
491
|
[KEYWORDS.DIVISION]: {
|
@@ -518,7 +518,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
518
518
|
}
|
519
519
|
}
|
520
520
|
],
|
521
|
-
[RETURNS]: [ATOM]
|
521
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
522
522
|
}
|
523
523
|
},
|
524
524
|
[KEYWORDS.REMAINDER_OF_DIVISION]: {
|
@@ -550,7 +550,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
550
550
|
}
|
551
551
|
}
|
552
552
|
],
|
553
|
-
[RETURNS]: [ATOM]
|
553
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
554
554
|
}
|
555
555
|
},
|
556
556
|
[KEYWORDS.BITWISE_AND]: {
|
@@ -583,7 +583,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
583
583
|
}
|
584
584
|
}
|
585
585
|
],
|
586
|
-
[RETURNS]: [ATOM]
|
586
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
587
587
|
}
|
588
588
|
},
|
589
589
|
[KEYWORDS.BITWISE_NOT]: {
|
@@ -605,7 +605,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
605
605
|
}
|
606
606
|
}
|
607
607
|
],
|
608
|
-
[RETURNS]: [ATOM]
|
608
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
609
609
|
}
|
610
610
|
},
|
611
611
|
[KEYWORDS.BITWISE_OR]: {
|
@@ -638,7 +638,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
638
638
|
}
|
639
639
|
}
|
640
640
|
],
|
641
|
-
[RETURNS]: [ATOM]
|
641
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
642
642
|
}
|
643
643
|
},
|
644
644
|
[KEYWORDS.BITWISE_XOR]: {
|
@@ -671,7 +671,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
671
671
|
}
|
672
672
|
}
|
673
673
|
],
|
674
|
-
[RETURNS]: [ATOM]
|
674
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
675
675
|
}
|
676
676
|
},
|
677
677
|
[KEYWORDS.BITWISE_LEFT_SHIFT]: {
|
@@ -704,7 +704,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
704
704
|
}
|
705
705
|
}
|
706
706
|
],
|
707
|
-
[RETURNS]: [ATOM]
|
707
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
708
708
|
}
|
709
709
|
},
|
710
710
|
[KEYWORDS.BITWISE_RIGHT_SHIFT]: {
|
@@ -737,7 +737,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
737
737
|
}
|
738
738
|
}
|
739
739
|
],
|
740
|
-
[RETURNS]: [ATOM]
|
740
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
741
741
|
}
|
742
742
|
},
|
743
743
|
[KEYWORDS.GET_ARRAY]: {
|
@@ -859,7 +859,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
859
859
|
}
|
860
860
|
}
|
861
861
|
],
|
862
|
-
[RETURNS]: [ATOM]
|
862
|
+
[RETURNS]: [ATOM, NUMBER_SUBTYPE()]
|
863
863
|
}
|
864
864
|
},
|
865
865
|
[KEYWORDS.IF]: {
|
package/src/utils.js
CHANGED
@@ -462,6 +462,27 @@ export class Brr {
|
|
462
462
|
for (let i = half; i < initial.length; ++i) this._addToRight(initial[i])
|
463
463
|
return this
|
464
464
|
}
|
465
|
+
static from(iterable) {
|
466
|
+
const out = new Brr()
|
467
|
+
const half = (iterable.length / 2) | 0.5
|
468
|
+
for (let i = half - 1; i >= 0; --i) out._addToLeft(iterable[i])
|
469
|
+
for (let i = half; i < iterable.length; ++i) out._addToRight(iterable[i])
|
470
|
+
return out
|
471
|
+
}
|
472
|
+
/**
|
473
|
+
* Returns the elements of an array that meet the condition specified in a callback function.
|
474
|
+
* @param predicate — A function that accepts up to three arguments.
|
475
|
+
* The filter method calls the predicate function one time for each element in the array.
|
476
|
+
*/
|
477
|
+
filter(callback = _Identity) {
|
478
|
+
const out = []
|
479
|
+
for (let i = 0, len = this.length; i < len; ++i) {
|
480
|
+
const current = this.get(i)
|
481
|
+
const predicat = callback(current, i, this)
|
482
|
+
if (predicat) out.push(current)
|
483
|
+
}
|
484
|
+
return Brr.from(out)
|
485
|
+
}
|
465
486
|
// reverse() {
|
466
487
|
// const left = this._left
|
467
488
|
// const right = this._right
|