fez-lisp 1.5.126 → 1.5.129

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.126",
5
+ "version": "1.5.129",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -52,6 +52,7 @@ import {
52
52
  getSuffix,
53
53
  hasApplyLambdaBlock,
54
54
  hasBlock,
55
+ log,
55
56
  logExp,
56
57
  stringifyArgs
57
58
  } from './utils.js'
@@ -113,10 +114,16 @@ export const isUnknownNotAnyType = (stats) =>
113
114
  export const isUnknownNotAnyReturn = (stats) =>
114
115
  stats && !isAnyReturn(stats) && isUnknownReturn(stats)
115
116
  export const castType = (stats, type) => {
116
- return (stats[TYPE_PROP][0] = type[RETURNS][0])
117
+ return (
118
+ (stats[TYPE_PROP][0] = type[RETURNS][0]),
119
+ (stats[TYPE_PROP][1] = type[RETURNS][1])
120
+ )
117
121
  }
118
122
  export const castReturn = (stats, type) => {
119
- return (stats[RETURNS][0] = type[RETURNS][0])
123
+ return (
124
+ (stats[RETURNS][0] = type[RETURNS][0]),
125
+ (stats[RETURNS][1] = type[RETURNS][1])
126
+ )
120
127
  }
121
128
  export const isTypeAbstraction = (stats) => stats[TYPE_PROP] === APPLY
122
129
  export const setPropToAtom = (stats, prop) => {
@@ -129,7 +136,7 @@ export const setPropToPredicate = (stats, prop) => {
129
136
  return (stats[prop][1] = BOOLEAN_SUBTYPE())
130
137
  }
131
138
  export const setReturnToPredicate = (stats) => {
132
- return (stats[RETURNS][1] = BOOLEAN_SUBTYPE())
139
+ return (stats[RETURNS][0] = BOOLEAN_SUBTYPE())
133
140
  }
134
141
  export const setTypeToPredicate = (stats) => {
135
142
  return (stats[RETURNS][1] = BOOLEAN_SUBTYPE())
@@ -195,6 +202,9 @@ export const setTypeRef = (stats, value) =>
195
202
  (isUnknownType(stats) || isAnyType(stats)) &&
196
203
  (stats[TYPE_PROP] = value[TYPE_PROP])
197
204
  export const setReturnRef = (stats, value) => {
205
+ if (SPECIAL_FORMS_SET.has(value[SIGNATURE])) {
206
+ return setReturn(stats, value)
207
+ }
198
208
  return isUnknownReturn(stats) && (stats[RETURNS] = value[RETURNS])
199
209
  }
200
210
  export const setReturnToTypeRef = (stats, value) => {
@@ -237,7 +247,7 @@ export const setPropToSubType = (stats, prop, value) =>
237
247
  hasSubType(value) && (stats[prop][1] = value[TYPE_PROP][1])
238
248
  export const setPropToSubReturn = (stats, prop, value) =>
239
249
  // makes no senseto protect this for now
240
- hasSubType(value) && (stats[prop][1] = value[RETURNS][1])
250
+ hasSubReturn(value) && (stats[prop][1] = value[RETURNS][1])
241
251
  export const setTypeToReturn = (stats, value) =>
242
252
  (isUnknownType(stats) || isAnyType(stats)) &&
243
253
  !isUnknownReturn(value) &&
@@ -264,12 +274,25 @@ export const getSubType = (stats) => stats && stats[TYPE_PROP][1]
264
274
  export const hasSubType = (stats) => stats && stats[TYPE_PROP][1] instanceof Set
265
275
  export const getSubReturn = (stats) => stats && stats[RETURNS][1]
266
276
  export const hasSubReturn = (stats) => stats && stats[RETURNS][1] instanceof Set
277
+ export const isUknownSubReturn = (stats) =>
278
+ !hasSubReturn(stats) ||
279
+ (stats[RETURNS][1].size === 1 && stats[RETURNS][1].has(UNKNOWN))
280
+ export const isUknownSubType = (stats) =>
281
+ hasSubType(stats) &&
282
+ stats[TYPE_PROP][1].size === 1 &&
283
+ stats[TYPE_PROP][1].has(UNKNOWN)
267
284
  export const isAtomType = (stats) =>
268
285
  isAnyType(stats) || stats[TYPE_PROP][0] === ATOM
269
286
  export const isAtomReturn = (stats) =>
270
287
  isAnyType(stats) || stats[RETURNS][0] === ATOM
271
- export const compareTypes = (a, b) =>
272
- isAnyType(a) || isAnyType(b) || a[TYPE_PROP][0] === b[TYPE_PROP][0]
288
+ export const compareTypes = (a, b) => {
289
+ const isAnyAny = isAnyType(a) || isAnyType(b)
290
+ if (isAnyAny) return true
291
+ const isSameType = a[TYPE_PROP][0] === b[TYPE_PROP][0]
292
+ if (!isSameType) return false
293
+ return true
294
+ }
295
+
273
296
  export const compareReturns = (a, b) =>
274
297
  isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
275
298
  export const compareTypeWithReturn = (a, b) =>
@@ -285,6 +308,7 @@ const IsPredicate = (leaf) =>
285
308
  (PREDICATES_OUTPUT_SET.has(leaf[VALUE]) ||
286
309
  getSuffix(leaf[VALUE]) === PREDICATE_SUFFIX))
287
310
 
311
+ // THese should also check if sub type is Uknown array and pass as ok
288
312
  const notABooleanType = (a, b) => {
289
313
  return (
290
314
  hasSubType(a) &&
@@ -294,15 +318,25 @@ const notABooleanType = (a, b) => {
294
318
  (!hasSubType(b) || getSubType(a).difference(getSubType(b)).size !== 0)
295
319
  )
296
320
  }
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
+ // }
297
333
  const notABooleanReturn = (a, b) => {
298
334
  return (
299
335
  hasSubType(a) &&
300
336
  getSubType(a).has(PREDICATE) &&
301
337
  !isUnknownReturn(b) &&
302
338
  !isAnyReturn(b) &&
303
- (!isAtomReturn(b) ||
304
- !hasSubReturn(b) ||
305
- getSubType(a).difference(getSubReturn(b)).size !== 0)
339
+ (!hasSubReturn(b) || getSubType(a).difference(getSubReturn(b)).size !== 0)
306
340
  )
307
341
  }
308
342
  const isAtomABoolean = (atom) => atom === TRUE || atom === FALSE
@@ -516,39 +550,44 @@ const resolveSetter = (first, rest, env) => {
516
550
  ) {
517
551
  const name = rest[0][VALUE]
518
552
  const current = env[name]
519
- if (!hasSubType(current[STATS])) {
520
- const right = isLeaf(rest.at(-1)) ? rest.at(-1) : rest.at(-1)[0]
521
- switch (right[TYPE]) {
522
- case ATOM:
523
- current[STATS][TYPE_PROP][1] = new Set([NUMBER])
524
- break
525
- case WORD:
526
- if (env[right[VALUE]]) {
527
- if (hasSubType(env[right[VALUE]][STATS]))
528
- current[STATS][TYPE_PROP][1] = new Set(
529
- getSubType(env[right[VALUE]][STATS])
530
- )
531
- else
532
- current[STATS][TYPE_PROP][1] = new Set([
533
- getType(env[right[VALUE]][STATS])
534
- ])
535
- }
536
- break
537
- case APPLY:
538
- if (env[right[VALUE]]) {
539
- if (hasSubReturn(env[right[VALUE]][STATS]))
540
- current[STATS][TYPE_PROP][1] = new Set([
541
- ...getSubReturn(env[right[VALUE]][STATS])
542
- ])
543
- else
544
- current[STATS][TYPE_PROP][1] = new Set([
545
- env[right[VALUE]][STATS][RETURNS][0]
546
- ])
553
+ const right = isLeaf(rest.at(-1)) ? rest.at(-1) : rest.at(-1)[0]
554
+ switch (right[TYPE]) {
555
+ case ATOM:
556
+ current[STATS][TYPE_PROP][1] = new Set([NUMBER])
557
+ break
558
+ case WORD:
559
+ if (env[right[VALUE]]) {
560
+ if (hasSubType(env[right[VALUE]][STATS]))
561
+ current[STATS][TYPE_PROP][1] = new Set(
562
+ getSubType(env[right[VALUE]][STATS])
563
+ )
564
+ else
565
+ current[STATS][TYPE_PROP][1] = new Set([
566
+ getType(env[right[VALUE]][STATS])
567
+ ])
568
+ }
569
+ break
570
+ case APPLY:
571
+ if (env[right[VALUE]]) {
572
+ if (right[VALUE] === KEYWORDS.CREATE_ARRAY) {
573
+ current[STATS][TYPE_PROP][1] = (initArrayType({
574
+ rem: rest.at(-1),
575
+ env
576
+ }) ?? { [RETURNS]: [COLLECTION, new Set([])] })[RETURNS][1]
577
+ break
547
578
  }
548
- break
549
- }
550
- setTypeToCollection(current[STATS])
579
+ if (hasSubReturn(env[right[VALUE]][STATS]))
580
+ current[STATS][TYPE_PROP][1] = new Set([
581
+ ...getSubReturn(env[right[VALUE]][STATS])
582
+ ])
583
+ else if (!isUnknownReturn(env[right[VALUE]][STATS]))
584
+ current[STATS][TYPE_PROP][1] = new Set([
585
+ getReturn(env[right[VALUE]][STATS])
586
+ ])
587
+ }
588
+ break
551
589
  }
590
+ setTypeToCollection(current[STATS])
552
591
  }
553
592
  }
554
593
  const resolveGetter = ({ rem, prop, name, env }) => {
@@ -572,7 +611,10 @@ const resolveGetter = ({ rem, prop, name, env }) => {
572
611
  {
573
612
  if (hasSubType(env[array[VALUE]][STATS])) {
574
613
  const rightSub = getSubType(env[array[VALUE]][STATS])
575
- const isAtom = rightSub.has(NUMBER) || rightSub.has(PREDICATE)
614
+ const isAtom =
615
+ rightSub.has(ATOM) ||
616
+ rightSub.has(NUMBER) ||
617
+ rightSub.has(PREDICATE)
576
618
  const isCollection = rightSub.has(COLLECTION)
577
619
  if (isAtom && !isCollection) {
578
620
  setPropToAtom(env[name][STATS], prop)
@@ -586,12 +628,45 @@ const resolveGetter = ({ rem, prop, name, env }) => {
586
628
  }
587
629
  return true
588
630
  }
631
+ const initArrayType = ({ rem, env }) => {
632
+ const ret = rem
633
+ .slice(1)
634
+ .map((x) =>
635
+ isLeaf(x)
636
+ ? x[TYPE] === WORD
637
+ ? env[x[VALUE]]
638
+ ? getTypes(env[x[VALUE]][STATS])
639
+ : [UNKNOWN]
640
+ : [x[TYPE]]
641
+ : env[x[0][VALUE]]
642
+ ? getReturns(env[x[0][VALUE]][STATS])
643
+ : [UNKNOWN]
644
+ )
645
+ const known = ret.find((x) => x[0] !== ANY && x[0] !== UNKNOWN)
646
+ if (
647
+ known &&
648
+ ret.length &&
649
+ !ret.some((x) => known[0] !== x[0] || known.length !== x.length)
650
+ ) {
651
+ const [main, sub] = ret[0]
652
+ return {
653
+ [TYPE_PROP]: [APPLY],
654
+ [RETURNS]: [COLLECTION, new Set(sub ? [...sub] : [main])]
655
+ }
656
+ }
657
+ }
589
658
  const resolveRetunType = ({ returns, rem, stack, prop, exp, name, env }) => {
590
659
  if (returns[TYPE] === ATOM) {
591
660
  // ATOM ASSIGMENT
592
661
  setPropToAtom(env[name][STATS], prop)
593
662
  } else {
594
663
  switch (returns[VALUE]) {
664
+ case KEYWORDS.CREATE_ARRAY:
665
+ {
666
+ const r = initArrayType({ rem, env })
667
+ if (r) setPropToSubReturn(env[name][STATS], prop, r)
668
+ }
669
+ break
595
670
  case KEYWORDS.IF:
596
671
  resolveCondition({ rem, name, env, exp, prop })
597
672
  break
@@ -881,6 +956,7 @@ export const typeCheck = (ast) => {
881
956
  case STATIC_TYPES.ATOM:
882
957
  case STATIC_TYPES.PREDICATE:
883
958
  case STATIC_TYPES.ANY:
959
+ case STATIC_TYPES.NUMBER:
884
960
  {
885
961
  const ret = isLeaf(rest[0]) ? rest[0] : rest[0][0]
886
962
  const ref = env[ret[VALUE]]
@@ -979,10 +1055,12 @@ export const typeCheck = (ast) => {
979
1055
  // const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
980
1056
  const MAIN_TYPE = getType(args[i][STATS])
981
1057
  if (MAIN_TYPE === ANY) continue
1058
+ // TODO - try to merge special and non special
982
1059
  if (first[TYPE] === APPLY && isSpecial) {
983
1060
  if (!isResLeaf) {
984
1061
  const name = rest[i][0][VALUE]
985
1062
  if (!env[name]) continue
1063
+ // there is a problem here with cond pr when passed as an argument
986
1064
  if (name === KEYWORDS.IF) {
987
1065
  const concequent = [...rest]
988
1066
  const alternative = [...rest]
@@ -998,6 +1076,7 @@ export const typeCheck = (ast) => {
998
1076
  check(exp, env, scope)
999
1077
  )
1000
1078
  } else if (
1079
+ !isUnknownType(args[i][STATS]) &&
1001
1080
  !isUnknownReturn(env[name][STATS]) &&
1002
1081
  !compareTypeWithReturn(args[i][STATS], env[name][STATS])
1003
1082
  )
@@ -1011,6 +1090,7 @@ export const typeCheck = (ast) => {
1011
1090
  )}) (${stringifyArgs(exp)}) (check #1)`
1012
1091
  )
1013
1092
  else if (
1093
+ !isUnknownReturn(args[i][STATS]) &&
1014
1094
  !isUnknownReturn(env[name][STATS]) &&
1015
1095
  notABooleanReturn(args[i][STATS], env[name][STATS])
1016
1096
  )
@@ -1046,6 +1126,7 @@ export const typeCheck = (ast) => {
1046
1126
  const name = rest[i][VALUE]
1047
1127
  if (!env[name]) continue
1048
1128
  if (
1129
+ !isUnknownType(args[i][STATS]) &&
1049
1130
  !isUnknownType(env[name][STATS]) &&
1050
1131
  !compareTypes(args[i][STATS], env[name][STATS])
1051
1132
  )
@@ -1059,6 +1140,7 @@ export const typeCheck = (ast) => {
1059
1140
  )}) (${stringifyArgs(exp)}) (check #3)`
1060
1141
  )
1061
1142
  else if (
1143
+ !isUnknownType(args[i][STATS]) &&
1062
1144
  !isUnknownType(env[name][STATS]) &&
1063
1145
  notABooleanType(args[i][STATS], env[name][STATS])
1064
1146
  )
@@ -1071,11 +1153,28 @@ export const typeCheck = (ast) => {
1071
1153
  getTypes(env[name][STATS])
1072
1154
  )}) (${stringifyArgs(exp)}) (check #202)`
1073
1155
  )
1074
- else setType(env[name][STATS], args[i][STATS])
1156
+ else {
1157
+ // TODO the special form will set type first but it
1158
+ // might be known already
1159
+ // example
1160
+ // (let xs [])
1161
+ // (let x (array:set-and-get! xs 0 100))
1162
+ // (length x)
1163
+ //
1164
+ // if (isUnknownType(env[name][STATS])) {
1165
+ // retry(env[name][STATS], stack, () =>
1166
+ // check(exp, env, scope)
1167
+ // )
1168
+ // } else
1169
+ setType(env[name][STATS], args[i][STATS])
1170
+ }
1075
1171
  }
1076
1172
  break
1077
1173
  case ATOM: {
1078
- if (rest[i][TYPE] !== args[i][STATS][TYPE_PROP][0])
1174
+ if (
1175
+ !isUnknownType(args[i][STATS]) &&
1176
+ rest[i][TYPE] !== args[i][STATS][TYPE_PROP][0]
1177
+ )
1079
1178
  throw new TypeError(
1080
1179
  `Incorrect type of argument (${i}) for special form (${
1081
1180
  first[VALUE]
@@ -1298,7 +1397,11 @@ export const typeCheck = (ast) => {
1298
1397
  }
1299
1398
  } else if (env[rest[i][0][VALUE]]) {
1300
1399
  const match = () => {
1301
- const actual = env[rest[i][0][VALUE]][STATS]
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]
1302
1405
  const expected = args[i][STATS]
1303
1406
  retryArgs(args[i][STATS], stack, () => match())
1304
1407
  if (!isUnknownType(expected) && !isUnknownReturn(actual))
@@ -1314,13 +1417,13 @@ export const typeCheck = (ast) => {
1314
1417
  )
1315
1418
  else if (notABooleanReturn(expected, actual)) {
1316
1419
  throw new TypeError(
1317
- `Incorrect type of argument (${i}) for special form (${
1420
+ `Incorrect type of argument (${i}) for (${
1318
1421
  first[VALUE]
1319
1422
  }). Expected (${formatSubType(
1320
1423
  getTypes(expected)
1321
1424
  )}) but got (${formatSubType(
1322
1425
  getReturns(actual)
1323
- )}) (${stringifyArgs(exp)}) (check #204)`
1426
+ )}) (${stringifyArgs(exp)}) (check #206)`
1324
1427
  )
1325
1428
  } else {
1326
1429
  switch (getType(expected)) {
package/src/compiler.js CHANGED
@@ -275,6 +275,7 @@ const comp = (tree, Drill) => {
275
275
  case STATIC_TYPES.ATOM:
276
276
  case STATIC_TYPES.PREDICATE:
277
277
  case STATIC_TYPES.ANY:
278
+ case STATIC_TYPES.NUMBER:
278
279
  case DEBUG.ASSERT:
279
280
  case DEBUG.LOG:
280
281
  case DEBUG.STRING:
@@ -837,6 +837,7 @@ export const keywords = {
837
837
  [STATIC_TYPES.ATOM]: (args, env) => evaluate(args[0], env),
838
838
  [STATIC_TYPES.COLLECTION]: (args, env) => evaluate(args[0], env),
839
839
  [STATIC_TYPES.PREDICATE]: (args, env) => evaluate(args[0], env),
840
+ [STATIC_TYPES.NUMBER]: (args, env) => evaluate(args[0], env),
840
841
  [STATIC_TYPES.UNKNOWN]: (args, env) => evaluate(args[0], env),
841
842
  [STATIC_TYPES.ANY]: (args, env) => evaluate(args[0], env)
842
843
  }
package/src/keywords.js CHANGED
@@ -9,6 +9,7 @@ export const PLACEHOLDER = '.'
9
9
  export const MUTATION_SUFFIX = '!'
10
10
  export const PREDICATE_SUFFIX = '?'
11
11
  export const STATIC_TYPES = {
12
+ NUMBER: 'Number',
12
13
  ABSTRACTION: 'Abstraction',
13
14
  UNKNOWN: 'Unknown',
14
15
  ATOM: 'Atom',
package/src/types.js CHANGED
@@ -30,7 +30,6 @@ export const NIL = 'nil'
30
30
  export const TRUE_WORD = 'true'
31
31
  export const FALSE_WORD = 'false'
32
32
  export const BOOLEAN_SUBTYPE = () => new Set([PREDICATE])
33
- export const ANY_SUBTYPE = () => new Set([ANY])
34
33
  export const COLLECTION_SUBTYPE = () => new Set([COLLECTION])
35
34
  export const NUMBER_SUBTYPE = () => new Set([NUMBER])
36
35
 
@@ -134,6 +133,27 @@ export const SPECIAL_FORM_TYPES = {
134
133
  [RETURNS]: [ATOM, BOOLEAN_SUBTYPE()]
135
134
  }
136
135
  },
136
+ [STATIC_TYPES.NUMBER]: {
137
+ [STATS]: {
138
+ [TYPE_PROP]: [APPLY],
139
+ [SIGNATURE]: STATIC_TYPES.NUMBER,
140
+ retried: Infinity,
141
+ [ARG_COUNT]: 1,
142
+ [ARGUMENTS]: [
143
+ {
144
+ [STATS]: {
145
+ retried: Infinity,
146
+ [SIGNATURE]: PLACEHOLDER,
147
+ [TYPE_PROP]: [UNKNOWN],
148
+ [RETURNS]: [UNKNOWN],
149
+ [ARGUMENTS]: [],
150
+ [ARG_COUNT]: 0
151
+ }
152
+ }
153
+ ],
154
+ [RETURNS]: [ATOM, NUMBER_SUBTYPE()]
155
+ }
156
+ },
137
157
  [STATIC_TYPES.COLLECTION]: {
138
158
  [STATS]: {
139
159
  [TYPE_PROP]: [APPLY],
@@ -765,8 +785,8 @@ export const SPECIAL_FORM_TYPES = {
765
785
  [STATS]: {
766
786
  retried: 0,
767
787
  [SIGNATURE]: PLACEHOLDER,
768
- [TYPE_PROP]: [COLLECTION, ANY_SUBTYPE()],
769
- [RETURNS]: [COLLECTION, ANY_SUBTYPE()],
788
+ [TYPE_PROP]: [COLLECTION],
789
+ [RETURNS]: [COLLECTION],
770
790
 
771
791
  [ARGUMENTS]: [],
772
792
  [ARG_COUNT]: 0
@@ -795,7 +815,7 @@ export const SPECIAL_FORM_TYPES = {
795
815
  }
796
816
  }
797
817
  ],
798
- [RETURNS]: [COLLECTION, ANY_SUBTYPE()]
818
+ [RETURNS]: [COLLECTION]
799
819
  }
800
820
  },
801
821
  [KEYWORDS.POP_ARRAY]: {
package/src/utils.js CHANGED
@@ -24,6 +24,10 @@ export const logExp = function (exp, ...args) {
24
24
  console.log(wrapInBracesString(exp), ...args)
25
25
  return exp
26
26
  }
27
+ export const log = (x) => {
28
+ console.log(x)
29
+ return x
30
+ }
27
31
  export const formatCallstack = (callstack) =>
28
32
  callstack
29
33
  .reverse()
@@ -332,6 +336,7 @@ export const addTypeIdentities = (ast) => {
332
336
  identity(STATIC_TYPES.ATOM),
333
337
  identity(STATIC_TYPES.COLLECTION),
334
338
  identity(STATIC_TYPES.PREDICATE),
339
+ identity(STATIC_TYPES.NUMBER),
335
340
  identity(STATIC_TYPES.ANY),
336
341
  identity(STATIC_TYPES.UNKNOWN)
337
342
  )