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 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.112",
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
+ }
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 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
- 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(expectedArgs[i][STATS])
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(expectedArgs[i][STATS])
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
- setType(env[name][STATS], expectedArgs[i][STATS])
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
- expectedArgs[i][STATS][TYPE_PROP][0]
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 (isRestILeaf) {
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 `[${