fez-lisp 1.5.126 → 1.5.128

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.128",
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) =>
@@ -294,15 +317,25 @@ const notABooleanType = (a, b) => {
294
317
  (!hasSubType(b) || getSubType(a).difference(getSubType(b)).size !== 0)
295
318
  )
296
319
  }
320
+ // const notABooleanReturn = (a, b) => {
321
+ // return (
322
+ // hasSubType(a) &&
323
+ // getSubType(a).has(PREDICATE) &&
324
+ // !isUnknownReturn(b) &&
325
+ // !isAnyReturn(b) &&
326
+ // (
327
+ // !isAtomReturn(b) ||
328
+ // !hasSubReturn(b) ||
329
+ // getSubType(a).difference(getSubReturn(b)).size !== 0)
330
+ // )
331
+ // }
297
332
  const notABooleanReturn = (a, b) => {
298
333
  return (
299
334
  hasSubType(a) &&
300
335
  getSubType(a).has(PREDICATE) &&
301
336
  !isUnknownReturn(b) &&
302
337
  !isAnyReturn(b) &&
303
- (!isAtomReturn(b) ||
304
- !hasSubReturn(b) ||
305
- getSubType(a).difference(getSubReturn(b)).size !== 0)
338
+ (!hasSubReturn(b) || getSubType(a).difference(getSubReturn(b)).size !== 0)
306
339
  )
307
340
  }
308
341
  const isAtomABoolean = (atom) => atom === TRUE || atom === FALSE
@@ -516,39 +549,44 @@ const resolveSetter = (first, rest, env) => {
516
549
  ) {
517
550
  const name = rest[0][VALUE]
518
551
  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
- ])
552
+ const right = isLeaf(rest.at(-1)) ? rest.at(-1) : rest.at(-1)[0]
553
+ switch (right[TYPE]) {
554
+ case ATOM:
555
+ current[STATS][TYPE_PROP][1] = new Set([NUMBER])
556
+ break
557
+ case WORD:
558
+ if (env[right[VALUE]]) {
559
+ if (hasSubType(env[right[VALUE]][STATS]))
560
+ current[STATS][TYPE_PROP][1] = new Set(
561
+ getSubType(env[right[VALUE]][STATS])
562
+ )
563
+ else
564
+ current[STATS][TYPE_PROP][1] = new Set([
565
+ getType(env[right[VALUE]][STATS])
566
+ ])
567
+ }
568
+ break
569
+ case APPLY:
570
+ if (env[right[VALUE]]) {
571
+ if (right[VALUE] === KEYWORDS.CREATE_ARRAY) {
572
+ current[STATS][TYPE_PROP][1] = (initArrayType({
573
+ rem: rest.at(-1),
574
+ env
575
+ }) ?? { [RETURNS]: [COLLECTION, new Set([])] })[RETURNS][1]
576
+ break
547
577
  }
548
- break
549
- }
550
- setTypeToCollection(current[STATS])
578
+ if (hasSubReturn(env[right[VALUE]][STATS]))
579
+ current[STATS][TYPE_PROP][1] = new Set([
580
+ ...getSubReturn(env[right[VALUE]][STATS])
581
+ ])
582
+ else if (!isUnknownReturn(env[right[VALUE]][STATS]))
583
+ current[STATS][TYPE_PROP][1] = new Set([
584
+ getReturn(env[right[VALUE]][STATS])
585
+ ])
586
+ }
587
+ break
551
588
  }
589
+ setTypeToCollection(current[STATS])
552
590
  }
553
591
  }
554
592
  const resolveGetter = ({ rem, prop, name, env }) => {
@@ -572,7 +610,10 @@ const resolveGetter = ({ rem, prop, name, env }) => {
572
610
  {
573
611
  if (hasSubType(env[array[VALUE]][STATS])) {
574
612
  const rightSub = getSubType(env[array[VALUE]][STATS])
575
- const isAtom = rightSub.has(NUMBER) || rightSub.has(PREDICATE)
613
+ const isAtom =
614
+ rightSub.has(ATOM) ||
615
+ rightSub.has(NUMBER) ||
616
+ rightSub.has(PREDICATE)
576
617
  const isCollection = rightSub.has(COLLECTION)
577
618
  if (isAtom && !isCollection) {
578
619
  setPropToAtom(env[name][STATS], prop)
@@ -586,12 +627,45 @@ const resolveGetter = ({ rem, prop, name, env }) => {
586
627
  }
587
628
  return true
588
629
  }
630
+ const initArrayType = ({ rem, env }) => {
631
+ const ret = rem
632
+ .slice(1)
633
+ .map((x) =>
634
+ isLeaf(x)
635
+ ? x[TYPE] === WORD
636
+ ? env[x[VALUE]]
637
+ ? getTypes(env[x[VALUE]][STATS])
638
+ : [UNKNOWN]
639
+ : [x[TYPE]]
640
+ : env[x[0][VALUE]]
641
+ ? getReturns(env[x[0][VALUE]][STATS])
642
+ : [UNKNOWN]
643
+ )
644
+ const known = ret.find((x) => x[0] !== ANY && x[0] !== UNKNOWN)
645
+ if (
646
+ known &&
647
+ ret.length &&
648
+ !ret.some((x) => known[0] !== x[0] || known.length !== x.length)
649
+ ) {
650
+ const [main, sub] = ret[0]
651
+ return {
652
+ [TYPE_PROP]: [APPLY],
653
+ [RETURNS]: [COLLECTION, new Set(sub ? [...sub] : [main])]
654
+ }
655
+ }
656
+ }
589
657
  const resolveRetunType = ({ returns, rem, stack, prop, exp, name, env }) => {
590
658
  if (returns[TYPE] === ATOM) {
591
659
  // ATOM ASSIGMENT
592
660
  setPropToAtom(env[name][STATS], prop)
593
661
  } else {
594
662
  switch (returns[VALUE]) {
663
+ case KEYWORDS.CREATE_ARRAY:
664
+ {
665
+ const r = initArrayType({ rem, env })
666
+ if (r) setPropToSubReturn(env[name][STATS], prop, r)
667
+ }
668
+ break
595
669
  case KEYWORDS.IF:
596
670
  resolveCondition({ rem, name, env, exp, prop })
597
671
  break
@@ -881,6 +955,7 @@ export const typeCheck = (ast) => {
881
955
  case STATIC_TYPES.ATOM:
882
956
  case STATIC_TYPES.PREDICATE:
883
957
  case STATIC_TYPES.ANY:
958
+ case STATIC_TYPES.NUMBER:
884
959
  {
885
960
  const ret = isLeaf(rest[0]) ? rest[0] : rest[0][0]
886
961
  const ref = env[ret[VALUE]]
@@ -1071,7 +1146,21 @@ export const typeCheck = (ast) => {
1071
1146
  getTypes(env[name][STATS])
1072
1147
  )}) (${stringifyArgs(exp)}) (check #202)`
1073
1148
  )
1074
- else setType(env[name][STATS], args[i][STATS])
1149
+ else {
1150
+ // TODO the special form will set type first but it
1151
+ // might be known already
1152
+ // example
1153
+ // (let xs [])
1154
+ // (let x (array:set-and-get! xs 0 100))
1155
+ // (length x)
1156
+ //
1157
+ // if (isUnknownType(env[name][STATS])) {
1158
+ // retry(env[name][STATS], stack, () =>
1159
+ // check(exp, env, scope)
1160
+ // )
1161
+ // } else
1162
+ setType(env[name][STATS], args[i][STATS])
1163
+ }
1075
1164
  }
1076
1165
  break
1077
1166
  case ATOM: {
@@ -1298,7 +1387,11 @@ export const typeCheck = (ast) => {
1298
1387
  }
1299
1388
  } else if (env[rest[i][0][VALUE]]) {
1300
1389
  const match = () => {
1301
- const actual = env[rest[i][0][VALUE]][STATS]
1390
+ const actual =
1391
+ rest[i][0][VALUE] === KEYWORDS.CREATE_ARRAY
1392
+ ? initArrayType({ rem: rest[i], env }) ??
1393
+ env[rest[i][0][VALUE]][STATS]
1394
+ : env[rest[i][0][VALUE]][STATS]
1302
1395
  const expected = args[i][STATS]
1303
1396
  retryArgs(args[i][STATS], stack, () => match())
1304
1397
  if (!isUnknownType(expected) && !isUnknownReturn(actual))
@@ -1314,13 +1407,13 @@ export const typeCheck = (ast) => {
1314
1407
  )
1315
1408
  else if (notABooleanReturn(expected, actual)) {
1316
1409
  throw new TypeError(
1317
- `Incorrect type of argument (${i}) for special form (${
1410
+ `Incorrect type of argument (${i}) for (${
1318
1411
  first[VALUE]
1319
1412
  }). Expected (${formatSubType(
1320
1413
  getTypes(expected)
1321
1414
  )}) but got (${formatSubType(
1322
1415
  getReturns(actual)
1323
- )}) (${stringifyArgs(exp)}) (check #204)`
1416
+ )}) (${stringifyArgs(exp)}) (check #206)`
1324
1417
  )
1325
1418
  } else {
1326
1419
  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
  )