fez-lisp 1.5.110 → 1.5.111

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 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.110",
5
+ "version": "1.5.111",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
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
+ }
54
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
+ }
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,42 @@ 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 isRestILeaf = isLeaf(rest[i])
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
- const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
800
- if (!isRestILeaf) {
847
+ if (!isResLeaf) {
801
848
  const name = rest[i][0][VALUE]
802
849
  if (!env[name]) continue
803
850
  if (
804
851
  !isUnknownReturn(env[name][STATS]) &&
805
- !compareTypeWithReturn(
806
- expectedArgs[i][STATS],
807
- env[name][STATS]
808
- )
852
+ !compareTypeWithReturn(args[i][STATS], env[name][STATS])
809
853
  )
810
854
  throw new TypeError(
811
855
  `Incorrect type of argument (${i}) for special form (${
812
856
  first[VALUE]
813
857
  }). Expected (${toTypeNames(
814
- getType(expectedArgs[i][STATS])
858
+ getType(args[i][STATS])
815
859
  )}) but got (${toTypeNames(
816
860
  getReturn(env[name][STATS])
817
861
  )}) (${stringifyArgs(exp)}) (check #1)`
818
862
  )
819
- else {
863
+ else if (
864
+ notABooleanReturn(args[i][STATS], env[name][STATS])
865
+ ) {
866
+ throw new TypeError(
867
+ `Incorrect type of argument (${i}) for special form (${
868
+ first[VALUE]
869
+ }). Expected (${formatSubType(
870
+ getTypes(args[i][STATS])
871
+ )}) but got (${formatSubType(
872
+ getReturns(env[name][STATS])
873
+ )}) (${stringifyArgs(exp)}) (check #201)`
874
+ )
875
+ } else {
820
876
  if (env[name] && getType(env[name][STATS]) === APPLY)
821
877
  switch (first[VALUE]) {
822
878
  case KEYWORDS.IF:
@@ -827,10 +883,7 @@ export const typeCheck = (ast, error = true) => {
827
883
  // what if it's a global function used elsewhere where the return type mwould be different
828
884
  // THIS willgive lambda return types but refactor is needed still
829
885
  if (!SPECIAL_FORMS_SET.has(name))
830
- setReturn(
831
- env[name][STATS],
832
- expectedArgs[i][STATS]
833
- )
886
+ setReturn(env[name][STATS], args[i][STATS])
834
887
  break
835
888
  }
836
889
  // TODO also handle casting
@@ -843,45 +896,64 @@ export const typeCheck = (ast, error = true) => {
843
896
  if (!env[name]) continue
844
897
  if (
845
898
  !isUnknownType(env[name][STATS]) &&
846
- !compareTypes(
847
- expectedArgs[i][STATS],
848
- env[name][STATS]
849
- )
899
+ !compareTypes(args[i][STATS], env[name][STATS])
850
900
  )
851
901
  throw new TypeError(
852
902
  `Incorrect type of argument (${i}) for special form (${
853
903
  first[VALUE]
854
904
  }). Expected (${toTypeNames(
855
- getType(expectedArgs[i][STATS])
905
+ getType(args[i][STATS])
856
906
  )}) but got (${toTypeNames(
857
907
  getType(env[name][STATS])
858
908
  )}) (${stringifyArgs(exp)}) (check #3)`
859
909
  )
860
- else
861
- setType(env[name][STATS], expectedArgs[i][STATS])
910
+ else if (
911
+ notABooleanType(args[i][STATS], env[name][STATS])
912
+ )
913
+ throw new TypeError(
914
+ `Incorrect type of argument (${i}) for special form (${
915
+ first[VALUE]
916
+ }). Expected (${formatSubType(
917
+ getTypes(args[i][STATS])
918
+ )}) but got (${formatSubType(
919
+ getTypes(env[name][STATS])
920
+ )}) (${stringifyArgs(exp)}) (check #202)`
921
+ )
922
+ else setType(env[name][STATS], args[i][STATS])
862
923
  }
863
924
  break
864
925
  case ATOM: {
865
- if (
866
- rest[i][TYPE] !==
867
- expectedArgs[i][STATS][TYPE_PROP][0]
868
- )
926
+ if (rest[i][TYPE] !== args[i][STATS][TYPE_PROP][0])
869
927
  throw new TypeError(
870
928
  `Incorrect type of argument (${i}) for special form (${
871
929
  first[VALUE]
872
930
  }). Expected (${toTypeNames(
873
- expectedArgs[i][STATS][TYPE_PROP][0]
931
+ args[i][STATS][TYPE_PROP][0]
874
932
  )}) but got (${toTypeNames(
875
933
  rest[i][TYPE]
876
934
  )}) (${stringifyArgs(exp)}) (check #2)`
877
935
  )
936
+ else if (
937
+ hasSubType(args[i][STATS]) &&
938
+ getSubType(args[i][STATS]).has(PREDICATE) &&
939
+ !isAtomABoolean(rest[i][VALUE])
940
+ )
941
+ throw new TypeError(
942
+ `Incorrect type of argument (${i}) for special form (${
943
+ first[VALUE]
944
+ }). Expected (${formatSubType(
945
+ getTypes(args[i][STATS])
946
+ )}) but got (${rest[i][VALUE]}) (${stringifyArgs(
947
+ exp
948
+ )}) (check #203)`
949
+ )
878
950
  break
879
951
  }
880
952
  }
881
953
  }
882
954
  }
883
955
  // type checking
884
- else if (isRestILeaf) {
956
+ else if (isResLeaf) {
885
957
  const T =
886
958
  rest[i][TYPE] === WORD
887
959
  ? 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 `[${