fez-lisp 1.6.89 → 1.6.91

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.89",
5
+ "version": "1.6.91",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -614,27 +614,95 @@ const IfApplyBranch = ({
614
614
  return setPropToReturn(ref[STATS], prop, branch[STATS])
615
615
  }
616
616
  }
617
+ const inferIf = (branch, re, env, name) => {
618
+ switch (branch[TYPE]) {
619
+ case ATOM:
620
+ return [[ATOM, NUMBER_SUBTYPE()]]
621
+ case WORD:
622
+ if (branch[VALUE] === NIL) return [[UNKNOWN]]
623
+ if (env[branch[VALUE]]) return [env[branch[VALUE]][STATS][TYPE_PROP]]
624
+ break
625
+ case APPLY:
626
+ if (branch[VALUE] !== name && env[branch[VALUE]])
627
+ if (branch[VALUE] === KEYWORDS.CREATE_ARRAY) {
628
+ return [initArrayType({ rem: re, env })[RETURNS]]
629
+ } else if (branch[VALUE] === KEYWORDS.IF) {
630
+ const conc = isLeaf(re[2]) ? re[2] : re[2][0]
631
+ const alt = isLeaf(re[3]) ? re[3] : re[3][0]
632
+ return inferIf(conc, re[2], env, name).concat(
633
+ inferIf(alt, re[3], env, name)
634
+ )
635
+ } else return [env[branch[VALUE]][STATS][RETURNS]]
636
+ break
637
+ }
638
+ return []
639
+ }
640
+ const validateIfMatchingBranches = (
641
+ concequent,
642
+ alternative,
643
+ env,
644
+ exp,
645
+ re,
646
+ name
647
+ ) => {
648
+ const A = inferIf(concequent, re[0], env, name).filter(
649
+ (x) => x[0] !== UNKNOWN && x[0] !== ANY
650
+ )
651
+ const B = inferIf(alternative, re[1], env, name).filter(
652
+ (x) => x[0] !== UNKNOWN && x[0] !== ANY
653
+ )
654
+
655
+ if (!A.length || !B.length) return
656
+
657
+ const isSame = (A, B) => {
658
+ if (
659
+ A[0] !== B[0] ||
660
+ (isSubType(A[1]) && isSubType(B[1]) && !A[1].isMatching(B[1]))
661
+ ) {
662
+ throw new TypeError(
663
+ `(if) needs to have matching concequent and alternative branches but got (${formatSubType(
664
+ A
665
+ )}) and (${formatSubType(B)}) (${stringifyArgs(exp)}) (check #1005)`
666
+ )
667
+ }
668
+ }
669
+ A.forEach((x) => isSame(A[0], x))
670
+ B.forEach((x) => isSame(B[0], x))
671
+
672
+ const FA = A[0]
673
+ const FB = B[0]
674
+ if (
675
+ FA[0] !== FB[0] ||
676
+ (isSubType(FA[1]) && isSubType(FB[1]) && !FA[1].isMatching(FB[1]))
677
+ ) {
678
+ throw new TypeError(
679
+ `(if) needs to have matching concequent and alternative branches but got (${formatSubType(
680
+ FA
681
+ )}) and (${formatSubType(FB)}) (${stringifyArgs(exp)}) (check #1005)`
682
+ )
683
+ }
684
+ }
617
685
  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)
686
+ const conc = isLeaf(re[0]) ? re[0] : re[0][0]
687
+ const alt = isLeaf(re[1]) ? re[1] : re[1][0]
688
+ const concequent = env[conc[VALUE]]
689
+ const alternative = env[alt[VALUE]]
690
+ if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
691
+ setPropToAtom(ref[STATS], prop)
692
+ }
620
693
  // TODO check that both branches are predicates if one is
621
694
  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
695
  // TODO make this more simple - it's so many different things just because types are functions or not
628
696
  // WHY not consider making return types for everything
629
697
  if (concequent)
630
698
  if (conc[TYPE] === WORD) {
631
- return setPropToTypeRef(ref[STATS], prop, concequent[STATS])
699
+ setPropToTypeRef(ref[STATS], prop, concequent[STATS])
632
700
  } else if (
633
701
  conc[TYPE] === APPLY &&
634
702
  getType(concequent[STATS]) === APPLY &&
635
703
  // Making sure the recursive function don't look for their own return type
636
704
  concequent[STATS][SIGNATURE] !== ref[STATS][SIGNATURE]
637
- ) {
705
+ )
638
706
  IfApplyBranch({
639
707
  leaf: conc,
640
708
  branch: concequent,
@@ -646,16 +714,15 @@ const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
646
714
  exp,
647
715
  check
648
716
  })
649
- }
650
- if (alternative) {
717
+ if (alternative)
651
718
  if (alt[TYPE] === WORD) {
652
- return setPropToTypeRef(ref[STATS], prop, alternative[STATS])
719
+ setPropToTypeRef(ref[STATS], prop, alternative[STATS])
653
720
  } else if (
654
721
  alt[TYPE] === APPLY &&
655
722
  getType(alternative[STATS]) === APPLY &&
656
723
  // Making sure the recursive function don't look for their own return type
657
724
  alternative[STATS][SIGNATURE] !== ref[STATS][SIGNATURE]
658
- ) {
725
+ )
659
726
  IfApplyBranch({
660
727
  leaf: alt,
661
728
  branch: alternative,
@@ -667,9 +734,8 @@ const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
667
734
  exp,
668
735
  check
669
736
  })
670
- }
671
- }
672
737
  }
738
+ validateIfMatchingBranches(conc, alt, env, exp, re, ref[STATS][SIGNATURE])
673
739
  }
674
740
  const resolveCondition = ({ rem, name, env, exp, prop, stack, check }) => {
675
741
  const ret = rem[0]
@@ -958,8 +1024,13 @@ const initArrayTypeRec = ({ rem, env }) =>
958
1024
  x[TYPE] === ATOM ? NUMBER_SUBTYPE() : new SubType([UNKNOWN])
959
1025
  ]
960
1026
  else if (env[x[0][VALUE]])
961
- if (x.length > 1 && env[x[0][VALUE]][STATS][RETURNS][0] === COLLECTION)
1027
+ if (x.length > 1 && x[0][VALUE] === KEYWORDS.CREATE_ARRAY)
962
1028
  return initArrayTypeRec({ rem: x, env })
1029
+ else if (
1030
+ x.length > 1 &&
1031
+ env[x[0][VALUE]][STATS][RETURNS][0] === COLLECTION
1032
+ )
1033
+ return [getReturns(env[x[0][VALUE]][STATS])]
963
1034
  else if (GET_ARRAY_INFERENCE_SET.has(x[0][VALUE])) {
964
1035
  const res = resolveGetterRec(x, env)
965
1036
  if (!res) return [UNKNOWN]
@@ -2114,7 +2185,7 @@ export const typeCheck = (
2114
2185
  (x) => isGenericType(x[STATS]) || isGenericReturn(x[STATS])
2115
2186
  )
2116
2187
  ) {
2117
- const rec = (ref) => {
2188
+ const genericRecursiveDecent = (ref) => {
2118
2189
  if (isGenericReturn(ref[STATS])) {
2119
2190
  const [index, multiplier] = ref[STATS][RETURNS][2]
2120
2191
  const desiredTypeIndex = env[first[VALUE]][STATS][
@@ -2229,7 +2300,8 @@ export const typeCheck = (
2229
2300
  expected[STATS][TYPE_PROP].length = 2
2230
2301
  }
2231
2302
  }
2232
- if (expected[STATS][ARGUMENTS].length) rec(expected)
2303
+ if (expected[STATS][ARGUMENTS].length)
2304
+ genericRecursiveDecent(expected)
2233
2305
  }
2234
2306
  }
2235
2307
  const copy = Object.create(env)
@@ -2240,7 +2312,7 @@ export const typeCheck = (
2240
2312
  }
2241
2313
  copy[newName][STATS][SIGNATURE] = newName
2242
2314
 
2243
- rec(copy[newName])
2315
+ genericRecursiveDecent(copy[newName])
2244
2316
 
2245
2317
  const cexp = structuredClone(exp)
2246
2318
  copy[newName][STATS].source = structuredClone(
@@ -2260,6 +2332,7 @@ export const typeCheck = (
2260
2332
  }
2261
2333
  }
2262
2334
  }
2335
+
2263
2336
  stagger(stack, 'append', [first, env], judge)
2264
2337
  stagger(stack, 'prepend', [first, env], judge)
2265
2338
  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)