fez-lisp 1.6.87 → 1.6.90

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.6.87",
5
+ "version": "1.6.90",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -365,13 +365,12 @@ const getGenericProp = (ref, rem, prop) => {
365
365
  const getGenericReturn = (ref, rem) => getGenericProp(ref, rem, RETURNS)
366
366
  const getGenericType = (ref, rem) => getGenericProp(ref, rem, TYPE_PROP)
367
367
  const resolveGenericNest = (ref, prop, nestGeneric, multiplier) => {
368
- const T = isSubType(ref[STATS][prop][1])
369
- ? ref[STATS][prop][1].types
370
- : [ref[STATS][prop][0]]
368
+ const hasSubType = isSubType(ref[STATS][prop][1])
369
+ const T = hasSubType ? ref[STATS][prop][1].types : [ref[STATS][prop][0]]
371
370
  if (multiplier === -1) {
372
371
  if (nestGeneric === 0) {
373
372
  if (T.at(-1) === NUMBER || T.at(-1) === BOOLEAN) {
374
- if (isSubType(ref[STATS][prop][1])) {
373
+ if (hasSubType) {
375
374
  if (ref[STATS][prop][1].types.length === 1) ref[STATS][prop][0] = ATOM
376
375
  else {
377
376
  ref[STATS][prop][1] = new SubType(
@@ -384,8 +383,9 @@ const resolveGenericNest = (ref, prop, nestGeneric, multiplier) => {
384
383
  }
385
384
  } else {
386
385
  if (T.length - nestGeneric - 1) {
387
- for (let i = 0; i < nestGeneric + 1; ++i)
388
- ref[STATS][prop][1].types.shift()
386
+ if (hasSubType)
387
+ for (let i = 0; i < nestGeneric + 1; ++i)
388
+ ref[STATS][prop][1].types.shift()
389
389
  ref[STATS][prop].length = 2
390
390
  } else {
391
391
  if (T.at(-1) === NUMBER || T.at(-1) === BOOLEAN) {
@@ -614,27 +614,108 @@ const IfApplyBranch = ({
614
614
  return setPropToReturn(ref[STATS], prop, branch[STATS])
615
615
  }
616
616
  }
617
+
618
+ const validateIfMatchingBranches = (
619
+ concequent,
620
+ alternative,
621
+ env,
622
+ exp,
623
+ re,
624
+ name
625
+ ) => {
626
+ let A = null
627
+ let B = null
628
+ switch (concequent[TYPE]) {
629
+ case ATOM:
630
+ A = [ATOM, NUMBER_SUBTYPE()]
631
+ break
632
+ case WORD:
633
+ if (concequent[VALUE] === NIL) return
634
+ if (env[concequent[VALUE]]) A = env[concequent[VALUE]][STATS][TYPE_PROP]
635
+ break
636
+ case APPLY:
637
+ if (concequent[VALUE] !== name && env[concequent[VALUE]])
638
+ if (concequent[VALUE] === KEYWORDS.CREATE_ARRAY) {
639
+ A = initArrayType({ rem: re[0], env })[RETURNS]
640
+ } else if (concequent[VALUE] === KEYWORDS.IF && re[0][2]) {
641
+ const conc = isLeaf(re[0][2]) ? re[0][2] : re[0][2][0]
642
+ validateIfMatchingBranches(
643
+ conc,
644
+ alternative,
645
+ env,
646
+ exp,
647
+ isLeaf(re[0]) ? re[0].slice(2) : re[0].slice(2),
648
+ name
649
+ )
650
+ } else A = env[concequent[VALUE]][STATS][RETURNS]
651
+ break
652
+ }
653
+ switch (alternative[TYPE]) {
654
+ case ATOM:
655
+ B = [ATOM, NUMBER_SUBTYPE()]
656
+ break
657
+ case WORD:
658
+ if (alternative[VALUE] === NIL) return
659
+ if (env[alternative[VALUE]]) B = env[alternative[VALUE]][STATS][TYPE_PROP]
660
+ break
661
+ case APPLY:
662
+ if (alternative[VALUE] !== name && env[alternative[VALUE]])
663
+ if (alternative[VALUE] === KEYWORDS.CREATE_ARRAY) {
664
+ B = initArrayType({ rem: re[1], env })[RETURNS]
665
+ } else if (alternative[VALUE] === KEYWORDS.IF && re[1][2]) {
666
+ const alt = isLeaf(re[1][2]) ? re[1][2] : re[1][2][0]
667
+ validateIfMatchingBranches(
668
+ concequent,
669
+ alt,
670
+ env,
671
+ exp,
672
+ isLeaf(re[1]) ? re[1].slice(2) : re[1].slice(2),
673
+ name
674
+ )
675
+ } else B = env[alternative[VALUE]][STATS][RETURNS]
676
+ break
677
+ }
678
+ if (
679
+ A === null ||
680
+ B === null ||
681
+ A[0] === UNKNOWN ||
682
+ B[0] === UNKNOWN ||
683
+ A[0] === ANY ||
684
+ B[0] === ANY
685
+ )
686
+ return
687
+ if (
688
+ A[0] !== B[0] ||
689
+ (isSubType(A[1]) && isSubType(B[1]) && !A[1].isMatching(B[1]))
690
+ ) {
691
+ throw new TypeError(
692
+ `(if) needs to have matching concequent and alternative branches but got (${formatSubType(
693
+ A
694
+ )}) and (${formatSubType(B)}) (${stringifyArgs(exp)}) (check #1005)`
695
+ )
696
+ }
697
+ }
617
698
  const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
618
- if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM)
619
- return setPropToAtom(ref[STATS], prop)
699
+ const conc = isLeaf(re[0]) ? re[0] : re[0][0]
700
+ const alt = isLeaf(re[1]) ? re[1] : re[1][0]
701
+ const concequent = env[conc[VALUE]]
702
+ const alternative = env[alt[VALUE]]
703
+ if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
704
+ setPropToAtom(ref[STATS], prop)
705
+ }
620
706
  // TODO check that both branches are predicates if one is
621
707
  else {
622
- const conc = isLeaf(re[0]) ? re[0] : re[0][0]
623
- const alt = isLeaf(re[1]) ? re[1] : re[1][0]
624
- const concequent = env[conc[VALUE]]
625
- const alternative = env[alt[VALUE]]
626
-
627
708
  // TODO make this more simple - it's so many different things just because types are functions or not
628
709
  // WHY not consider making return types for everything
629
710
  if (concequent)
630
711
  if (conc[TYPE] === WORD) {
631
- return setPropToTypeRef(ref[STATS], prop, concequent[STATS])
712
+ setPropToTypeRef(ref[STATS], prop, concequent[STATS])
632
713
  } else if (
633
714
  conc[TYPE] === APPLY &&
634
715
  getType(concequent[STATS]) === APPLY &&
635
716
  // Making sure the recursive function don't look for their own return type
636
717
  concequent[STATS][SIGNATURE] !== ref[STATS][SIGNATURE]
637
- ) {
718
+ )
638
719
  IfApplyBranch({
639
720
  leaf: conc,
640
721
  branch: concequent,
@@ -646,16 +727,15 @@ const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
646
727
  exp,
647
728
  check
648
729
  })
649
- }
650
- if (alternative) {
730
+ if (alternative)
651
731
  if (alt[TYPE] === WORD) {
652
- return setPropToTypeRef(ref[STATS], prop, alternative[STATS])
732
+ setPropToTypeRef(ref[STATS], prop, alternative[STATS])
653
733
  } else if (
654
734
  alt[TYPE] === APPLY &&
655
735
  getType(alternative[STATS]) === APPLY &&
656
736
  // Making sure the recursive function don't look for their own return type
657
737
  alternative[STATS][SIGNATURE] !== ref[STATS][SIGNATURE]
658
- ) {
738
+ )
659
739
  IfApplyBranch({
660
740
  leaf: alt,
661
741
  branch: alternative,
@@ -667,9 +747,8 @@ const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
667
747
  exp,
668
748
  check
669
749
  })
670
- }
671
- }
672
750
  }
751
+ validateIfMatchingBranches(conc, alt, env, exp, re, ref[STATS][SIGNATURE])
673
752
  }
674
753
  const resolveCondition = ({ rem, name, env, exp, prop, stack, check }) => {
675
754
  const ret = rem[0]
@@ -958,8 +1037,13 @@ const initArrayTypeRec = ({ rem, env }) =>
958
1037
  x[TYPE] === ATOM ? NUMBER_SUBTYPE() : new SubType([UNKNOWN])
959
1038
  ]
960
1039
  else if (env[x[0][VALUE]])
961
- if (x.length > 1 && env[x[0][VALUE]][STATS][RETURNS][0] === COLLECTION)
1040
+ if (x.length > 1 && x[0][VALUE] === KEYWORDS.CREATE_ARRAY)
962
1041
  return initArrayTypeRec({ rem: x, env })
1042
+ else if (
1043
+ x.length > 1 &&
1044
+ env[x[0][VALUE]][STATS][RETURNS][0] === COLLECTION
1045
+ )
1046
+ return [getReturns(env[x[0][VALUE]][STATS])]
963
1047
  else if (GET_ARRAY_INFERENCE_SET.has(x[0][VALUE])) {
964
1048
  const res = resolveGetterRec(x, env)
965
1049
  if (!res) return [UNKNOWN]
@@ -1884,6 +1968,7 @@ export const typeCheck = (
1884
1968
  }
1885
1969
  }
1886
1970
  }
1971
+
1887
1972
  // also type of arg
1888
1973
  const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
1889
1974
  for (let i = 0; i < args.length; ++i) {
@@ -2078,11 +2163,8 @@ export const typeCheck = (
2078
2163
  isUnknownReturn(env[name][STATS]) &&
2079
2164
  !env[name][STATS][IS_ARGUMENT]
2080
2165
  )
2081
- return retry(
2082
- env[name][STATS],
2083
- [first, env],
2084
- stack,
2085
- () => check(exp, env, scope)
2166
+ retry(env[name][STATS], [first, env], stack, () =>
2167
+ check(exp, env, scope)
2086
2168
  )
2087
2169
  else if (
2088
2170
  env[name] &&
@@ -2109,13 +2191,14 @@ export const typeCheck = (
2109
2191
  // GENERICS CODE START
2110
2192
  if (
2111
2193
  first[VALUE][0] !== PLACEHOLDER &&
2112
- env[first[VALUE]][STATS].source &&
2194
+ env[first[VALUE]][STATS][ARGUMENTS] &&
2113
2195
  env[first[VALUE]][STATS][ARGUMENTS].length &&
2196
+ env[first[VALUE]][STATS].source &&
2114
2197
  env[first[VALUE]][STATS][ARGUMENTS].some(
2115
2198
  (x) => isGenericType(x[STATS]) || isGenericReturn(x[STATS])
2116
2199
  )
2117
2200
  ) {
2118
- const rec = (ref) => {
2201
+ const genericRecursiveDecent = (ref) => {
2119
2202
  if (isGenericReturn(ref[STATS])) {
2120
2203
  const [index, multiplier] = ref[STATS][RETURNS][2]
2121
2204
  const desiredTypeIndex = env[first[VALUE]][STATS][
@@ -2180,7 +2263,6 @@ export const typeCheck = (
2180
2263
  const desiredType = isLeaf(rest[desiredTypeIndex])
2181
2264
  ? rest[desiredTypeIndex]
2182
2265
  : rest[desiredTypeIndex][0]
2183
-
2184
2266
  switch (desiredType[TYPE]) {
2185
2267
  case ATOM:
2186
2268
  expected[STATS][TYPE_PROP] = [
@@ -2231,7 +2313,8 @@ export const typeCheck = (
2231
2313
  expected[STATS][TYPE_PROP].length = 2
2232
2314
  }
2233
2315
  }
2234
- if (expected[STATS][ARGUMENTS].length) rec(expected)
2316
+ if (expected[STATS][ARGUMENTS].length)
2317
+ genericRecursiveDecent(expected)
2235
2318
  }
2236
2319
  }
2237
2320
  const copy = Object.create(env)
@@ -2242,7 +2325,7 @@ export const typeCheck = (
2242
2325
  }
2243
2326
  copy[newName][STATS][SIGNATURE] = newName
2244
2327
 
2245
- rec(copy[newName])
2328
+ genericRecursiveDecent(copy[newName])
2246
2329
 
2247
2330
  const cexp = structuredClone(exp)
2248
2331
  copy[newName][STATS].source = structuredClone(
@@ -2250,7 +2333,6 @@ export const typeCheck = (
2250
2333
  )
2251
2334
  cexp[0][VALUE] = newName
2252
2335
  copy[newName][STATS].source[1][VALUE] = newName
2253
-
2254
2336
  doOnce(copy[newName][STATS], cexp, stack, () => {
2255
2337
  check(
2256
2338
  wrapInArray([copy[newName][STATS].source, cexp]),
@@ -2263,6 +2345,7 @@ export const typeCheck = (
2263
2345
  }
2264
2346
  }
2265
2347
  }
2348
+
2266
2349
  stagger(stack, 'append', [first, env], judge)
2267
2350
  stagger(stack, 'prepend', [first, env], judge)
2268
2351
  for (let i = 0; i < rest.length; ++i) {
package/src/compiler.js CHANGED
@@ -276,18 +276,17 @@ const comp = (tree, Drill) => {
276
276
  )}}return -1})();`
277
277
  }
278
278
 
279
- case STATIC_TYPES.ABSTRACTION:
280
- case STATIC_TYPES.COLLECTION:
281
- case STATIC_TYPES.UNKNOWN:
282
- case STATIC_TYPES.ATOM:
283
- case STATIC_TYPES.BOOLEAN:
284
- case STATIC_TYPES.ANY:
285
- case STATIC_TYPES.NUMBER:
286
- case STATIC_TYPES.NUMBERS:
287
- case STATIC_TYPES.ABSTRACTIONS:
288
- case STATIC_TYPES.BOOLEANS:
289
- case STATIC_TYPES.COLLECTIONS:
290
- case STATIC_TYPES.AS_NUMBER:
279
+ // case STATIC_TYPES.ABSTRACTION:
280
+ // case STATIC_TYPES.COLLECTION:
281
+ // case STATIC_TYPES.UNKNOWN:
282
+ // case STATIC_TYPES.ATOM:
283
+ // case STATIC_TYPES.BOOLEAN:
284
+ // case STATIC_TYPES.ANY:
285
+ // case STATIC_TYPES.NUMBER:
286
+ // case STATIC_TYPES.NUMBERS:
287
+ // case STATIC_TYPES.ABSTRACTIONS:
288
+ // case STATIC_TYPES.BOOLEANS:
289
+ // case STATIC_TYPES.COLLECTIONS:
291
290
  case DEBUG.LOG:
292
291
  case DEBUG.STRING:
293
292
  case DEBUG.UNQUOTED_STRING:
package/src/enhance.js CHANGED
@@ -36,11 +36,6 @@ const opt = (ast) => {
36
36
  case APPLY:
37
37
  {
38
38
  switch (first[VALUE]) {
39
- case STATIC_TYPES.AS_NUMBER:
40
- exp.length = 0
41
- for (let i = 0; i < rest.length; ++i) exp.push(...rest[i])
42
- evaluate(exp)
43
- break
44
39
  case KEYWORDS.DEFINE_VARIABLE:
45
40
  {
46
41
  const last = exp.at(-1)
@@ -257,7 +252,6 @@ export const removeCast = (ast) => {
257
252
  case STATIC_TYPES.ABSTRACTIONS:
258
253
  case STATIC_TYPES.BOOLEANS:
259
254
  case STATIC_TYPES.COLLECTIONS:
260
- case STATIC_TYPES.AS_NUMBER:
261
255
  exp.length = 0
262
256
  for (let i = 0; i < rest.length; ++i) exp.push(...rest[i])
263
257
  evaluate(exp)
package/src/keywords.js CHANGED
@@ -20,7 +20,6 @@ export const STATIC_TYPES = {
20
20
  BOOLEANS: 'Booleans',
21
21
  ABSTRACTIONS: 'Abstractions',
22
22
  COLLECTIONS: 'Collections',
23
- AS_NUMBER: 'numberp',
24
23
  ANY: 'Any',
25
24
  DEFINE_TYPE: 'the'
26
25
  }
package/src/macros.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  VALUE,
17
17
  WORD
18
18
  } from './keywords.js'
19
- import { hasBlock, stringifyArgs } from './utils.js'
19
+ import { hasBlock, logExp, stringifyArgs } from './utils.js'
20
20
  import { NIL } from './types.js'
21
21
  export const SUGGAR = {
22
22
  // Syntactic suggars
@@ -382,6 +382,15 @@ export const deSuggarAst = (ast, scope) => {
382
382
  exp[0][TYPE] = ATOM
383
383
  exp[0][VALUE] = FALSE
384
384
  } else if (rest.length > 2) {
385
+ // TODO: maybe one day implement
386
+ // Constant folding
387
+ // it works sort of like this
388
+ // while (
389
+ // rest.at(-2) &&
390
+ // rest.at(-1)[TYPE] === ATOM &&
391
+ // rest.at(-2)[TYPE] === ATOM
392
+ // )
393
+ // rest[rest.length - 2][VALUE] += rest.pop()[VALUE]
385
394
  exp.length = 0
386
395
  let temp = exp
387
396
  for (let i = 0; i < rest.length; i += 1) {
@@ -522,7 +531,11 @@ export const deSuggarAst = (ast, scope) => {
522
531
  KEYWORDS.IF
523
532
  } ${stringifyArgs(rest)})`
524
533
  )
525
- if (rest.length === 2) exp.push([WORD, NIL])
534
+ if (rest.length === 2) {
535
+ // for this to work also make nil to be a false boolean
536
+ // exp[2] = [[APPLY, 'logic:true'], exp[2]]
537
+ exp.push([WORD, NIL])
538
+ }
526
539
  }
527
540
  deSuggarAst(exp[1], scope)
528
541
  break
package/src/parser.js CHANGED
@@ -150,7 +150,6 @@ export const AST = {
150
150
  case STATIC_TYPES.ABSTRACTIONS:
151
151
  case STATIC_TYPES.BOOLEANS:
152
152
  case STATIC_TYPES.COLLECTIONS:
153
- case STATIC_TYPES.AS_NUMBER:
154
153
  out += dfs(tail[0])
155
154
  break
156
155
  default:
@@ -193,7 +192,6 @@ export const AST = {
193
192
  case STATIC_TYPES.ABSTRACTIONS:
194
193
  case STATIC_TYPES.BOOLEANS:
195
194
  case STATIC_TYPES.COLLECTIONS:
196
- case STATIC_TYPES.AS_NUMBER:
197
195
  out += dfs(tail[0])
198
196
  break
199
197
  default:
@@ -241,7 +239,6 @@ pub fn ${mod}() -> Expression { ${str} }`
241
239
  case STATIC_TYPES.ABSTRACTIONS:
242
240
  case STATIC_TYPES.BOOLEANS:
243
241
  case STATIC_TYPES.COLLECTIONS:
244
- case STATIC_TYPES.AS_NUMBER:
245
242
  out += dfs(tail[0])
246
243
  break
247
244
  default:
package/src/types.js CHANGED
@@ -234,27 +234,6 @@ export const SPECIAL_FORM_TYPES = {
234
234
  [RETURNS]: [ATOM]
235
235
  }
236
236
  },
237
- [STATIC_TYPES.AS_NUMBER]: {
238
- [STATS]: {
239
- [TYPE_PROP]: [APPLY],
240
- [SIGNATURE]: STATIC_TYPES.AS_NUMBER,
241
- retried: Infinity,
242
- [ARG_COUNT]: 1,
243
- [ARGUMENTS]: [
244
- {
245
- [STATS]: {
246
- retried: Infinity,
247
- [SIGNATURE]: PLACEHOLDER,
248
- [TYPE_PROP]: [ATOM, SPECIAL_BOOLEAN],
249
- [RETURNS]: [ATOM, SPECIAL_BOOLEAN],
250
- [ARGUMENTS]: [],
251
- [ARG_COUNT]: 0
252
- }
253
- }
254
- ],
255
- [RETURNS]: [ATOM, SPECIAL_NUMBER]
256
- }
257
- },
258
237
  [STATIC_TYPES.BOOLEAN]: {
259
238
  [STATS]: {
260
239
  [TYPE_PROP]: [APPLY],
package/src/utils.js CHANGED
@@ -273,7 +273,7 @@ const toIgnore = (ast) => {
273
273
  break
274
274
  }
275
275
  }
276
- dfs(ast[0])
276
+ dfs(ast)
277
277
  return out
278
278
  // ast.filter(([x]) => isDefinition(x)).map(([_, x]) => x[VALUE])
279
279
  }
@@ -282,12 +282,12 @@ export const treeShake = (ast, libs) => {
282
282
  const visited = new Set()
283
283
  const ignored = new Set(toIgnore(ast))
284
284
  deepShake(ast, deps, visited, ignored)
285
- return extractDeps(visited, deps)
285
+ return [extractDeps(visited, deps), visited]
286
286
  }
287
287
  export const shakedList = (ast, libs) => {
288
288
  const deps = toDeps(libs)
289
289
  const visited = new Set()
290
- const ignored = new Set(toIgnore(ast))
290
+ const ignored = new Set(toIgnore(ast[0]))
291
291
  deepShake(ast, deps, visited, ignored)
292
292
  const out = []
293
293
  for (const [key] of deps) if (visited.has(key)) out.push(key)
@@ -311,7 +311,10 @@ export const wrapInApplyLambda = (ast) => [
311
311
  ]
312
312
  export const interpret = (ast, keywords) =>
313
313
  ast.reduce((_, x) => evaluate(x, keywords), 0)
314
- export const shake = (parsed, std) => treeShake(parsed, std).concat(parsed)
314
+ export const shake = (parsed, std) => {
315
+ const [shaked] = treeShake(parsed, std)
316
+ return shaked.concat(parsed)
317
+ }
315
318
  export const tree = (source, std) =>
316
319
  std
317
320
  ? shake(LISP.parse(deSuggarSource(removeNoCode(source))), std)