fez-lisp 1.5.31 → 1.5.33

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.31",
5
+ "version": "1.5.33",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -61,7 +61,6 @@ export const typeCheck = (ast) => {
61
61
  [DEBUG.SET_THEME]: {
62
62
  [STATS]: { type: APPLY, [ARGS_COUNT]: VARIADIC, [RETURNS]: UNKNOWN }
63
63
  },
64
- [SCOPE_NAME]: performance.now().toString().replace('.', 0),
65
64
  [KEYWORDS.BLOCK]: {
66
65
  [STATS]: { type: APPLY, [ARGS_COUNT]: VARIADIC, [RETURNS]: UNKNOWN }
67
66
  },
@@ -376,8 +375,29 @@ export const typeCheck = (ast) => {
376
375
  }
377
376
  }
378
377
  const errorStack = new Map()
379
- const withScope = (name, env) =>
380
- `${env[SCOPE_NAME] ?? root[SCOPE_NAME]}_${name}`
378
+ // const isDefinitionOfAFunction = (head, tail) =>
379
+ // head[TYPE] === APPLY &&
380
+ // head[VALUE] === KEYWORDS.DEFINE_VARIABLE &&
381
+ // tail.at(-1)[0][TYPE] === APPLY &&
382
+ // tail.at(-1)[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
383
+ const getScopeNames = (scope) => {
384
+ const scopeNames = []
385
+ let current = scope
386
+
387
+ while (current) {
388
+ if (current[SCOPE_NAME]) {
389
+ scopeNames.push(current[SCOPE_NAME])
390
+ }
391
+ current = Object.getPrototypeOf(current)
392
+ }
393
+ return scopeNames.reverse()
394
+ }
395
+ const withScope = (name, scope) => {
396
+ const chain = getScopeNames(scope)
397
+ const str = `${chain.join('_')}_${name}`
398
+ // console.log({ str })
399
+ return { str, chain }
400
+ }
381
401
 
382
402
  const stack = []
383
403
  const check = (exp, env, scope) => {
@@ -386,14 +406,15 @@ export const typeCheck = (ast) => {
386
406
  switch (first[TYPE]) {
387
407
  case WORD:
388
408
  {
389
- const key = withScope(first[VALUE], scope)
390
- if (env[first[VALUE]] === undefined) {
391
- errorStack.set(
392
- key,
393
- `Trying to access undefined variable ${first[VALUE]} (check #11)`
394
- )
395
- }
396
- // else if (errorStack.has(key)) errorStack.delete(key)
409
+ stack.push(() => {
410
+ const key = withScope(first[VALUE], scope)
411
+ if (env[first[VALUE]] === undefined) {
412
+ errorStack.set(
413
+ key.str,
414
+ `Trying to access undefined variable ${first[VALUE]} (check #11)`
415
+ )
416
+ }
417
+ })
397
418
  }
398
419
  break
399
420
  case ATOM:
@@ -402,50 +423,48 @@ export const typeCheck = (ast) => {
402
423
  switch (first[VALUE]) {
403
424
  case KEYWORDS.DEFINE_VARIABLE:
404
425
  {
405
- if (
406
- rest.length &&
407
- rest.at(-1).length &&
408
- rest.at(-1)[0][TYPE] === APPLY &&
409
- rest.at(-1)[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
410
- ) {
411
- const name = rest[0][VALUE]
412
- const n = rest.at(-1).length
413
- env[name] = {
414
- [STATS]: {
415
- type: APPLY,
416
- [ARGS_COUNT]: n - 2,
417
- [ARGS]: []
418
- }
419
- }
420
- if (name[name.length - 1] === PREDICATE_SUFFIX)
421
- env[name][STATS][SUBTYPE] = PREDICATE
422
-
423
- scope = exp
424
- if (env[SCOPE_NAME]) {
425
- const key = withScope(name, scope)
426
- if (errorStack.has(key)) errorStack.delete(key)
427
- }
428
- check(rest.at(-1), env, scope)
426
+ if (rest.length !== 2) {
427
+ throw new TypeError(
428
+ `Incorrect number of arguments for (${
429
+ first[VALUE]
430
+ }). Expected (= 2) but got ${rest.length} (${stringifyArgs(
431
+ exp
432
+ )}) (check #10)`
433
+ )
429
434
  } else {
430
435
  const name = rest[0][VALUE]
431
- if (!(name in env)) {
432
- if (rest[1][TYPE] === WORD) env[name] = env[rest[1][VALUE]]
433
- else
434
- env[name] = {
435
- [STATS]: {
436
- type: isLeaf(rest.at(-1))
437
- ? rest.at(-1)[TYPE]
438
- : env[rest.at(-1)[0]?.[VALUE]]?.[STATS]?.[
439
- RETURNS
440
- ] ?? UNKNOWN
441
- }
436
+ if (
437
+ rest.at(-1)[0][TYPE] === APPLY &&
438
+ rest.at(-1)[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
439
+ ) {
440
+ const n = rest.at(-1).length
441
+ env[name] = {
442
+ [STATS]: {
443
+ type: APPLY,
444
+ [ARGS_COUNT]: n - 2,
445
+ [ARGS]: []
442
446
  }
447
+ }
448
+ if (name[name.length - 1] === PREDICATE_SUFFIX)
449
+ env[name][STATS][SUBTYPE] = PREDICATE
450
+ check(rest.at(-1), env, exp)
451
+ } else {
452
+ if (!(name in env)) {
453
+ if (rest[1][TYPE] === WORD)
454
+ env[name] = env[rest[1][VALUE]]
455
+ else
456
+ env[name] = {
457
+ [STATS]: {
458
+ type: isLeaf(rest.at(-1))
459
+ ? rest.at(-1)[TYPE]
460
+ : env[rest.at(-1)[0]?.[VALUE]]?.[STATS]?.[
461
+ RETURNS
462
+ ] ?? UNKNOWN
463
+ }
464
+ }
465
+ }
466
+ check(rest.at(-1), env, scope)
443
467
  }
444
- if (env[SCOPE_NAME]) {
445
- const key = withScope(name, scope)
446
- if (errorStack.has(key)) errorStack.delete(key)
447
- }
448
- check(rest.at(-1), env, scope)
449
468
  }
450
469
  }
451
470
  break
@@ -462,19 +481,20 @@ export const typeCheck = (ast) => {
462
481
  }
463
482
  const params = exp.slice(1, -1)
464
483
  const copy = Object.create(env)
465
- if (isLeaf(scope[1])) {
484
+ if (Array.isArray(scope[1]) && scope[1][TYPE] === WORD) {
466
485
  copy[SCOPE_NAME] = scope[1][VALUE]
467
- } else
486
+ } else {
468
487
  copy[SCOPE_NAME] = performance
469
488
  .now()
470
489
  .toString()
471
490
  .replace('.', 0)
491
+ }
472
492
  for (const param of params) {
473
493
  copy[param[VALUE]] = { [STATS]: { type: UNKNOWN } }
474
494
  if (env[copy[SCOPE_NAME]])
475
495
  env[copy[SCOPE_NAME]][STATS][ARGS].push(copy[param[VALUE]])
476
496
  }
477
- check(rest.at(-1), copy, scope)
497
+ check(rest.at(-1), copy, copy)
478
498
  }
479
499
  break
480
500
  default:
@@ -482,7 +502,7 @@ export const typeCheck = (ast) => {
482
502
  const key = withScope(first[VALUE], scope)
483
503
  if (env[first[VALUE]] === undefined)
484
504
  errorStack.set(
485
- key,
505
+ key.str,
486
506
  `Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
487
507
  )
488
508
  else if (
@@ -491,7 +511,7 @@ export const typeCheck = (ast) => {
491
511
  env[first[VALUE]][STATS][ARGS_COUNT] !== rest.length
492
512
  ) {
493
513
  errorStack.set(
494
- key,
514
+ key.str,
495
515
  `Incorrect number of arguments for (${
496
516
  first[VALUE]
497
517
  }). Expected (= ${
@@ -506,10 +526,10 @@ export const typeCheck = (ast) => {
506
526
  if (first[TYPE] === APPLY && !isSpecial) {
507
527
  if (env[first[VALUE]][STATS].type === ATOM) {
508
528
  errorStack.set(
509
- key,
529
+ key.str,
510
530
  `(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
511
531
  exp
512
- )})`
532
+ )}) (check #12)`
513
533
  )
514
534
  } else if (!env[first[VALUE]][STATS][ARGS_COUNT]) {
515
535
  env[first[VALUE]][STATS][RETURNS] = UNKNOWN
@@ -535,7 +555,7 @@ export const typeCheck = (ast) => {
535
555
  env[rest[i][VALUE]][STATS][ARGS_COUNT]
536
556
  ) {
537
557
  errorStack.set(
538
- key,
558
+ key.str,
539
559
  `Incorrect number of arguments for (${
540
560
  first[VALUE]
541
561
  }). Expected (= ${
@@ -554,7 +574,7 @@ export const typeCheck = (ast) => {
554
574
  ) {
555
575
  if (args[i][STATS][ARGS_COUNT] !== rest[i].length - 2)
556
576
  errorStack.set(
557
- key,
577
+ key.str,
558
578
  `Incorrect number of arguments for (${
559
579
  first[VALUE]
560
580
  }). Expected (= ${
@@ -584,7 +604,7 @@ export const typeCheck = (ast) => {
584
604
  ) {
585
605
  // console.log(env[CAR][STATS], expectedArgs[i][TYPE])
586
606
  errorStack.set(
587
- key,
607
+ key.str,
588
608
  `Incorrect type of arguments for special form (${
589
609
  first[VALUE]
590
610
  }). Expected (${toTypeNames(
@@ -618,7 +638,7 @@ export const typeCheck = (ast) => {
618
638
  env[TT][STATS][RETURNS]
619
639
  )
620
640
  errorStack.set(
621
- key,
641
+ key.str,
622
642
  `Incorrect type of arguments for special form (${
623
643
  first[VALUE]
624
644
  }). Expected (${toTypeNames(
@@ -633,7 +653,7 @@ export const typeCheck = (ast) => {
633
653
  expectedArgs[i][TYPE] !== T
634
654
  ) {
635
655
  errorStack.set(
636
- key,
656
+ key.str,
637
657
  `Incorrect type of arguments for special form (${
638
658
  first[VALUE]
639
659
  }). Expected (${toTypeNames(
@@ -650,7 +670,7 @@ export const typeCheck = (ast) => {
650
670
  case APPLY:
651
671
  case ATOM:
652
672
  errorStack.set(
653
- key,
673
+ key.str,
654
674
  `Incorrect type of arguments for (${
655
675
  first[VALUE]
656
676
  }). Expected (${toTypeNames(
@@ -686,7 +706,7 @@ export const typeCheck = (ast) => {
686
706
  args[i][STATS].type)
687
707
  ) {
688
708
  errorStack.set(
689
- key,
709
+ key.str,
690
710
  `Incorrect type of arguments ${i} for (${
691
711
  first[VALUE]
692
712
  }). Expected (${toTypeNames(
@@ -704,8 +724,6 @@ export const typeCheck = (ast) => {
704
724
  args[i][STATS].type === UNKNOWN
705
725
  ) {
706
726
  retry.retried = true
707
- if (!scope[SCOPE_NAME])
708
- scope[SCOPE_NAME] = scope[1][VALUE]
709
727
  stack.unshift(() => check(exp, env, scope))
710
728
  }
711
729
  // console.log(
@@ -725,7 +743,7 @@ export const typeCheck = (ast) => {
725
743
  args[i][STATS].type
726
744
  ) {
727
745
  errorStack.set(
728
- key,
746
+ key.str,
729
747
  `Incorrect type of arguments ${i} for (${
730
748
  first[VALUE]
731
749
  }). Expected (${toTypeNames(
@@ -760,6 +778,7 @@ export const typeCheck = (ast) => {
760
778
  }
761
779
  }
762
780
  const copy = JSON.parse(JSON.stringify(ast))
781
+ copy[SCOPE_NAME] = 'root'
763
782
  check(copy, root, copy)
764
783
  while (stack.length) stack.pop()()
765
784
  if (errorStack.size)
package/src/macros.js CHANGED
@@ -619,7 +619,6 @@ export const deSuggarAst = (ast, scope) => {
619
619
  ]
620
620
  deSuggarAst(exp[exp.length - 1])
621
621
  } else if (prefix === OPTIMIZATIONS.CACHE) {
622
- // TODO: Make this
623
622
  const args = last.slice(1, -1)
624
623
  const newName = `*${performance
625
624
  .now()
@@ -810,7 +809,7 @@ export const deSuggarAst = (ast, scope) => {
810
809
  export const replaceStrings = (source) => {
811
810
  // const quotes = source.match(/"(.*?)"/g)
812
811
  const quotes = source.match(/"(?:.*?(\n|\r))*?.*?"/g)
813
- // TODO handle escaping
812
+ // TODO: handle escaping
814
813
  if (quotes)
815
814
  for (const q of quotes)
816
815
  source = source.replaceAll(
package/src/utils.js CHANGED
@@ -195,8 +195,34 @@ const extractDeps = (visited, deps) =>
195
195
  .map((x) => deps.get(x))
196
196
  .sort((a, b) => a.index - b.index)
197
197
  .map((x) => x.value)
198
- const toIgnore = (ast) =>
199
- ast.filter(([x]) => isDefinition(x)).map(([_, x]) => x[VALUE])
198
+ const toIgnore = (ast) => {
199
+ const out = []
200
+ const dfs = (exp) => {
201
+ const [head, ...tail] = isLeaf(exp) ? [exp] : exp
202
+ if (head == undefined) return []
203
+ switch (head[TYPE]) {
204
+ case WORD:
205
+ break
206
+ case ATOM:
207
+ break
208
+ case APPLY:
209
+ {
210
+ switch (head[VALUE]) {
211
+ case KEYWORDS.DEFINE_VARIABLE:
212
+ out.push(tail[0][VALUE])
213
+ break
214
+ default:
215
+ for (const r of tail) dfs(r)
216
+ break
217
+ }
218
+ }
219
+ break
220
+ }
221
+ }
222
+ dfs(ast[0])
223
+ return out
224
+ // ast.filter(([x]) => isDefinition(x)).map(([_, x]) => x[VALUE])
225
+ }
200
226
  export const treeShake = (ast, libs) => {
201
227
  const deps = toDeps(libs)
202
228
  const visited = new Set()