fez-lisp 1.5.110 → 1.5.112
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 +107 -28
- package/src/types.js +2 -1
package/package.json
CHANGED
package/src/check.js
CHANGED
@@ -41,7 +41,9 @@ import {
|
|
41
41
|
NIL,
|
42
42
|
TRUE_WORD,
|
43
43
|
FALSE_WORD,
|
44
|
-
BOOLEAN_SUBTYPE
|
44
|
+
BOOLEAN_SUBTYPE,
|
45
|
+
formatSubType,
|
46
|
+
PREDICATE
|
45
47
|
} from './types.js'
|
46
48
|
import {
|
47
49
|
Brr,
|
@@ -51,7 +53,35 @@ import {
|
|
51
53
|
logExp,
|
52
54
|
stringifyArgs
|
53
55
|
} from './utils.js'
|
56
|
+
Set.prototype.union = function (B) {
|
57
|
+
const A = this
|
58
|
+
const out = new Set()
|
59
|
+
A.forEach((element) => out.add(element))
|
60
|
+
B.forEach((element) => out.add(element))
|
61
|
+
return out
|
62
|
+
}
|
63
|
+
|
64
|
+
Set.prototype.xor = function (B) {
|
65
|
+
const A = this
|
66
|
+
const out = new Set()
|
67
|
+
B.forEach((element) => !A.has(element) && out.add(element))
|
68
|
+
A.forEach((element) => !B.has(element) && out.add(element))
|
69
|
+
return out
|
70
|
+
}
|
71
|
+
|
72
|
+
Set.prototype.intersection = function (B) {
|
73
|
+
const A = this
|
74
|
+
const out = new Set()
|
75
|
+
B.forEach((element) => A.has(element) && out.add(element))
|
76
|
+
return out
|
77
|
+
}
|
54
78
|
|
79
|
+
Set.prototype.difference = function (B) {
|
80
|
+
const A = this
|
81
|
+
const out = new Set()
|
82
|
+
A.forEach((element) => !B.has(element) && out.add(element))
|
83
|
+
return out
|
84
|
+
}
|
55
85
|
export const identity = (name) => [
|
56
86
|
[0, 'let'],
|
57
87
|
[1, name],
|
@@ -214,6 +244,10 @@ export const getType = (stats) => stats && stats[TYPE_PROP][0]
|
|
214
244
|
export const getTypes = (stats) => stats && stats[TYPE_PROP]
|
215
245
|
export const getReturn = (stats) => stats && stats[RETURNS][0]
|
216
246
|
export const getReturns = (stats) => stats && stats[RETURNS]
|
247
|
+
export const getSubType = (stats) => stats && stats[TYPE_PROP][1]
|
248
|
+
export const hasSubType = (stats) => stats && stats[TYPE_PROP][1] instanceof Set
|
249
|
+
export const getSubReturn = (stats) => stats && stats[RETURNS][1]
|
250
|
+
export const hasSubReturn = (stats) => stats && stats[RETURNS][1] instanceof Set
|
217
251
|
export const isAtomType = (stats) =>
|
218
252
|
isAnyType(stats) || stats[TYPE_PROP][0] === ATOM
|
219
253
|
export const isAtomReturn = (stats) =>
|
@@ -234,6 +268,20 @@ const IsPredicate = (leaf) =>
|
|
234
268
|
(leaf[TYPE] === APPLY &&
|
235
269
|
(PREDICATES_OUTPUT_SET.has(leaf[VALUE]) ||
|
236
270
|
getSuffix(leaf[VALUE]) === PREDICATE_SUFFIX))
|
271
|
+
|
272
|
+
const notABooleanType = (a, b) =>
|
273
|
+
hasSubType(a) &&
|
274
|
+
getSubType(a).has(PREDICATE) &&
|
275
|
+
!isUnknownType(b) &&
|
276
|
+
!isAnyType(b) &&
|
277
|
+
(!hasSubType(b) || getSubType(a).difference(getSubType(b)).size !== 0)
|
278
|
+
const notABooleanReturn = (a, b) =>
|
279
|
+
hasSubType(a) &&
|
280
|
+
getSubType(a).has(PREDICATE) &&
|
281
|
+
!isUnknownReturn(b) &&
|
282
|
+
!isAnyReturn(b) &&
|
283
|
+
(!hasSubReturn(b) || getSubType(a).difference(getSubReturn(b)).size !== 0)
|
284
|
+
const isAtomABoolean = (atom) => atom === TRUE || atom === FALSE
|
237
285
|
const checkPredicateName = (exp, rest) => {
|
238
286
|
if (getSuffix(rest[0][VALUE]) === PREDICATE_SUFFIX) {
|
239
287
|
const last = rest.at(-1)
|
@@ -789,34 +837,49 @@ export const typeCheck = (ast, error = true) => {
|
|
789
837
|
// also type of arg
|
790
838
|
const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
|
791
839
|
for (let i = 0; i < args.length; ++i) {
|
792
|
-
const
|
840
|
+
const isResLeaf = isLeaf(rest[i])
|
793
841
|
// type check
|
794
842
|
// TODO get rof pred type
|
795
843
|
// const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
|
796
844
|
const MAIN_TYPE = getType(args[i][STATS])
|
797
845
|
if (MAIN_TYPE === ANY) continue
|
798
846
|
if (first[TYPE] === APPLY && isSpecial) {
|
799
|
-
|
800
|
-
if (!isRestILeaf) {
|
847
|
+
if (!isResLeaf) {
|
801
848
|
const name = rest[i][0][VALUE]
|
802
849
|
if (!env[name]) continue
|
803
|
-
if (
|
850
|
+
if (name === KEYWORDS.IF) {
|
851
|
+
const concequent = [...rest]
|
852
|
+
const alternative = [...rest]
|
853
|
+
concequent[i] = rest[i][1]
|
854
|
+
alternative[i] = rest[i][2]
|
855
|
+
check([first, ...concequent], env, scope)
|
856
|
+
check([first, ...alternative], env, scope)
|
857
|
+
} else if (
|
804
858
|
!isUnknownReturn(env[name][STATS]) &&
|
805
|
-
!compareTypeWithReturn(
|
806
|
-
expectedArgs[i][STATS],
|
807
|
-
env[name][STATS]
|
808
|
-
)
|
859
|
+
!compareTypeWithReturn(args[i][STATS], env[name][STATS])
|
809
860
|
)
|
810
861
|
throw new TypeError(
|
811
862
|
`Incorrect type of argument (${i}) for special form (${
|
812
863
|
first[VALUE]
|
813
864
|
}). Expected (${toTypeNames(
|
814
|
-
getType(
|
865
|
+
getType(args[i][STATS])
|
815
866
|
)}) but got (${toTypeNames(
|
816
867
|
getReturn(env[name][STATS])
|
817
868
|
)}) (${stringifyArgs(exp)}) (check #1)`
|
818
869
|
)
|
819
|
-
else
|
870
|
+
else if (
|
871
|
+
notABooleanReturn(args[i][STATS], env[name][STATS])
|
872
|
+
) {
|
873
|
+
throw new TypeError(
|
874
|
+
`Incorrect type of argument (${i}) for special form (${
|
875
|
+
first[VALUE]
|
876
|
+
}). Expected (${formatSubType(
|
877
|
+
getTypes(args[i][STATS])
|
878
|
+
)}) but got (${formatSubType(
|
879
|
+
getReturns(env[name][STATS])
|
880
|
+
)}) (${stringifyArgs(exp)}) (check #201)`
|
881
|
+
)
|
882
|
+
} else {
|
820
883
|
if (env[name] && getType(env[name][STATS]) === APPLY)
|
821
884
|
switch (first[VALUE]) {
|
822
885
|
case KEYWORDS.IF:
|
@@ -827,10 +890,7 @@ export const typeCheck = (ast, error = true) => {
|
|
827
890
|
// what if it's a global function used elsewhere where the return type mwould be different
|
828
891
|
// THIS willgive lambda return types but refactor is needed still
|
829
892
|
if (!SPECIAL_FORMS_SET.has(name))
|
830
|
-
setReturn(
|
831
|
-
env[name][STATS],
|
832
|
-
expectedArgs[i][STATS]
|
833
|
-
)
|
893
|
+
setReturn(env[name][STATS], args[i][STATS])
|
834
894
|
break
|
835
895
|
}
|
836
896
|
// TODO also handle casting
|
@@ -843,45 +903,64 @@ export const typeCheck = (ast, error = true) => {
|
|
843
903
|
if (!env[name]) continue
|
844
904
|
if (
|
845
905
|
!isUnknownType(env[name][STATS]) &&
|
846
|
-
!compareTypes(
|
847
|
-
expectedArgs[i][STATS],
|
848
|
-
env[name][STATS]
|
849
|
-
)
|
906
|
+
!compareTypes(args[i][STATS], env[name][STATS])
|
850
907
|
)
|
851
908
|
throw new TypeError(
|
852
909
|
`Incorrect type of argument (${i}) for special form (${
|
853
910
|
first[VALUE]
|
854
911
|
}). Expected (${toTypeNames(
|
855
|
-
getType(
|
912
|
+
getType(args[i][STATS])
|
856
913
|
)}) but got (${toTypeNames(
|
857
914
|
getType(env[name][STATS])
|
858
915
|
)}) (${stringifyArgs(exp)}) (check #3)`
|
859
916
|
)
|
860
|
-
else
|
861
|
-
|
917
|
+
else if (
|
918
|
+
notABooleanType(args[i][STATS], env[name][STATS])
|
919
|
+
)
|
920
|
+
throw new TypeError(
|
921
|
+
`Incorrect type of argument (${i}) for special form (${
|
922
|
+
first[VALUE]
|
923
|
+
}). Expected (${formatSubType(
|
924
|
+
getTypes(args[i][STATS])
|
925
|
+
)}) but got (${formatSubType(
|
926
|
+
getTypes(env[name][STATS])
|
927
|
+
)}) (${stringifyArgs(exp)}) (check #202)`
|
928
|
+
)
|
929
|
+
else setType(env[name][STATS], args[i][STATS])
|
862
930
|
}
|
863
931
|
break
|
864
932
|
case ATOM: {
|
865
|
-
if (
|
866
|
-
rest[i][TYPE] !==
|
867
|
-
expectedArgs[i][STATS][TYPE_PROP][0]
|
868
|
-
)
|
933
|
+
if (rest[i][TYPE] !== args[i][STATS][TYPE_PROP][0])
|
869
934
|
throw new TypeError(
|
870
935
|
`Incorrect type of argument (${i}) for special form (${
|
871
936
|
first[VALUE]
|
872
937
|
}). Expected (${toTypeNames(
|
873
|
-
|
938
|
+
args[i][STATS][TYPE_PROP][0]
|
874
939
|
)}) but got (${toTypeNames(
|
875
940
|
rest[i][TYPE]
|
876
941
|
)}) (${stringifyArgs(exp)}) (check #2)`
|
877
942
|
)
|
943
|
+
else if (
|
944
|
+
hasSubType(args[i][STATS]) &&
|
945
|
+
getSubType(args[i][STATS]).has(PREDICATE) &&
|
946
|
+
!isAtomABoolean(rest[i][VALUE])
|
947
|
+
)
|
948
|
+
throw new TypeError(
|
949
|
+
`Incorrect type of argument (${i}) for special form (${
|
950
|
+
first[VALUE]
|
951
|
+
}). Expected (${formatSubType(
|
952
|
+
getTypes(args[i][STATS])
|
953
|
+
)}) but got (${rest[i][VALUE]}) (${stringifyArgs(
|
954
|
+
exp
|
955
|
+
)}) (check #203)`
|
956
|
+
)
|
878
957
|
break
|
879
958
|
}
|
880
959
|
}
|
881
960
|
}
|
882
961
|
}
|
883
962
|
// type checking
|
884
|
-
else if (
|
963
|
+
else if (isResLeaf) {
|
885
964
|
const T =
|
886
965
|
rest[i][TYPE] === WORD
|
887
966
|
? env[rest[i][VALUE]]
|
package/src/types.js
CHANGED
@@ -29,6 +29,7 @@ export const NIL = 'nil'
|
|
29
29
|
export const TRUE_WORD = 'true'
|
30
30
|
export const FALSE_WORD = 'false'
|
31
31
|
export const BOOLEAN_SUBTYPE = () => new Set([PREDICATE])
|
32
|
+
|
32
33
|
export const toTypeNames = (type) => {
|
33
34
|
switch (type) {
|
34
35
|
case APPLY:
|
@@ -1180,7 +1181,7 @@ export const SPECIAL_FORM_TYPES = {
|
|
1180
1181
|
}
|
1181
1182
|
}
|
1182
1183
|
|
1183
|
-
const formatSubType = (T) => {
|
1184
|
+
export const formatSubType = (T) => {
|
1184
1185
|
switch (T[0]) {
|
1185
1186
|
case COLLECTION:
|
1186
1187
|
return `[${
|