fez-lisp 1.4.3 → 1.4.5

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.4.3",
5
+ "version": "1.4.5",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/evaluator.js CHANGED
@@ -2,6 +2,7 @@ import { keywords } from './interpreter.js'
2
2
  import {
3
3
  APPLY,
4
4
  ATOM,
5
+ DEBUG,
5
6
  KEYWORDS,
6
7
  SPECIAL_FORMS_SET,
7
8
  TYPE,
@@ -9,7 +10,7 @@ import {
9
10
  WORD
10
11
  } from './keywords.js'
11
12
  import { isLeaf } from './parser.js'
12
- import { callStack, stringifyArgs } from './utils.js'
13
+ import { stringifyArgs } from './utils.js'
13
14
  export const evaluate = (exp, env = keywords) => {
14
15
  const [first, ...rest] = isLeaf(exp) ? [exp] : exp
15
16
  if (first == undefined) return []
@@ -33,7 +34,8 @@ export const evaluate = (exp, env = keywords) => {
33
34
  )
34
35
  const isSpecial = SPECIAL_FORMS_SET.has(value)
35
36
  const result = apply(rest, env, value)
36
- if (!isSpecial) callStack.pop()
37
+ if (!isSpecial && Array.isArray(env[DEBUG.CALLSTACK]))
38
+ env[DEBUG.CALLSTACK].pop()
37
39
  return result
38
40
  }
39
41
  case ATOM:
@@ -6,10 +6,11 @@ import {
6
6
  FALSE,
7
7
  TRUE,
8
8
  TYPES,
9
- RUNTIME_TYPES
9
+ RUNTIME_TYPES,
10
+ DEBUG
10
11
  } from './keywords.js'
11
12
  import { evaluate } from './evaluator.js'
12
- import { callStack, isForbiddenVariableName, stringifyArgs } from './utils.js'
13
+ import { isForbiddenVariableName, stringifyArgs } from './utils.js'
13
14
  import { LISP } from './parser.js'
14
15
  export const keywords = {
15
16
  [KEYWORDS.ADDITION]: (args, env) => {
@@ -758,7 +759,11 @@ export const keywords = {
758
759
  name ? ` ${name}` : ''
759
760
  }) are provided (expects ${params.length} but got ${
760
761
  props.length
761
- })\n\n(${KEYWORDS.ANONYMOUS_FUNCTION} ${stringifyArgs(params)})`
762
+ })\n\n${
763
+ name
764
+ ? `(${name} ${stringifyArgs(params)})`
765
+ : `(${KEYWORDS.ANONYMOUS_FUNCTION} ${stringifyArgs(params)})`
766
+ }`
762
767
  )
763
768
  const localEnv = Object.create(env)
764
769
  // localEnv[KEYWORDS.BLOCK] = block[KEYWORDS.BLOCK]
@@ -769,7 +774,8 @@ export const keywords = {
769
774
  writable: true
770
775
  })
771
776
  }
772
- if (name) callStack.push(name)
777
+ if (name && Array.isArray(env[DEBUG.CALLSTACK]))
778
+ env[DEBUG.CALLSTACK].push(name)
773
779
  return evaluate(body, localEnv)
774
780
  }
775
781
  },
package/src/keywords.js CHANGED
@@ -40,7 +40,7 @@ export const KEYWORDS = {
40
40
  DEFINE_VARIABLE: 'let',
41
41
 
42
42
  SET_ARRAY: 'set!',
43
- ERROR: 'throw'
43
+ ERROR: 'throw',
44
44
  }
45
45
 
46
46
  export const TYPES = {
@@ -54,7 +54,9 @@ export const RUNTIME_TYPES = {
54
54
  }
55
55
  export const DEBUG = {
56
56
  LOG: 'log',
57
- ASSERT: 'assert'
57
+ ASSERT: 'assert',
58
+ CALLSTACK: '(CALLSTACK)' // so that you can't use it in the code
59
+
58
60
  }
59
61
 
60
62
  export const SPECIAL_FORMS_SET = new Set(Object.values(KEYWORDS))
package/src/utils.js CHANGED
@@ -317,133 +317,162 @@ const identity = (name) => [
317
317
  [1, 'x']
318
318
  ]
319
319
  ]
320
- export const callStack = [KEYWORDS.BLOCK]
320
+ // export const result = (ast) => {
321
+ // try {
322
+ // return { output: evaluate(ast, keywords), error: null }
323
+ // } catch (error) {
324
+ // const isMaxCallStack =
325
+ // error.message.includes('Maximum call stack size exceeded') ||
326
+ // error.message.includes('too much recursion')
327
+ // return {
328
+ // output: null,
329
+ // error: {
330
+ // stack: [...callStack],
331
+ // message: isMaxCallStack
332
+ // ? error
333
+ // : `${error}\n${callStack
334
+ // .reverse()
335
+ // .map((x, i) => `${Array(i + 2).join(' ')}(${x} ...)`)
336
+ // .join('\n')}`
337
+ // }
338
+ // }
339
+ // }
340
+ // }
321
341
  export const debug = (ast) => {
322
- callStack.length = 0
323
- callStack.push(KEYWORDS.BLOCK)
324
- try {
325
- const debugEnv = {
326
- ...keywords,
327
- [DEBUG.LOG]: (args, env) => {
328
- if (args.length !== 1 && args.length !== 2)
329
- throw new RangeError(
330
- `Invalid number of arguments to (${DEBUG.LOG}) (or (= 1) (= 2)) (${
331
- DEBUG.LOG
332
- } ${stringifyArgs(args)})`
342
+ const debugEnv = {
343
+ ...keywords,
344
+ [DEBUG.CALLSTACK]: [KEYWORDS.BLOCK],
345
+ [DEBUG.LOG]: (args, env) => {
346
+ if (args.length !== 1 && args.length !== 2)
347
+ throw new RangeError(
348
+ `Invalid number of arguments to (${DEBUG.LOG}) (or (= 1) (= 2)) (${
349
+ DEBUG.LOG
350
+ } ${stringifyArgs(args)})`
351
+ )
352
+ const expression = evaluate(args[0], env)
353
+ if (args.length === 2) {
354
+ const option = evaluate(args[1], env)
355
+ if (!Array.isArray(option)) {
356
+ throw new TypeError(
357
+ `Second argument of (${DEBUG.LOG}) must be an (${
358
+ RUNTIME_TYPES.ARRAY
359
+ }) but got (${expression}) (${DEBUG.LOG} ${stringifyArgs(args)})`
333
360
  )
334
- const expression = evaluate(args[0], env)
335
- if (args.length === 2) {
336
- const option = evaluate(args[1], env)
337
- if (!Array.isArray(option)) {
338
- throw new TypeError(
339
- `Second argument of (${DEBUG.LOG}) must be an (${
340
- RUNTIME_TYPES.ARRAY
341
- }) but got (${expression}) (${DEBUG.LOG} ${stringifyArgs(args)})`
342
- )
343
- }
344
- const type = option.map((x) => String.fromCharCode(x)).join('')
345
- switch (type) {
346
- case 'string':
347
- case 'str':
348
- {
349
- if (!Array.isArray(expression))
350
- throw new TypeError(
351
- `Argument of (${DEBUG.LOG}) must be an (${
352
- RUNTIME_TYPES.ARRAY
353
- }) in the case ${type} but got (${expression}) (${
354
- DEBUG.LOG
355
- } ${stringifyArgs(args)})`
356
- )
357
- console.log(
358
- expression.map((x) => String.fromCharCode(x)).join('')
361
+ }
362
+ const type = option.map((x) => String.fromCharCode(x)).join('')
363
+ switch (type) {
364
+ case 'string':
365
+ case 'str':
366
+ {
367
+ if (!Array.isArray(expression))
368
+ throw new TypeError(
369
+ `Argument of (${DEBUG.LOG}) must be an (${
370
+ RUNTIME_TYPES.ARRAY
371
+ }) in the case ${type} but got (${expression}) (${
372
+ DEBUG.LOG
373
+ } ${stringifyArgs(args)})`
359
374
  )
360
- }
361
- break
362
- case 'char':
363
- case 'ch':
364
- {
365
- if (typeof expression !== 'number')
366
- throw new TypeError(
367
- `Argument argument of (${DEBUG.LOG}) must be a (${
368
- RUNTIME_TYPES.NUMBER
369
- }) in the case ${type} but got (${expression}) (${
370
- DEBUG.LOG
371
- } ${stringifyArgs(args)})`
372
- )
373
- console.log(String.fromCharCode(expression))
374
- }
375
-
376
- break
377
- case '*':
378
- console.log(expression)
379
- break
380
- default:
381
- throw new TypeError(
382
- `Invalid number of option to (${
383
- DEBUG.LOG
384
- }) got ${option} ${stringifyArgs(args)})`
375
+ console.log(
376
+ expression.map((x) => String.fromCharCode(x)).join('')
385
377
  )
386
- }
387
- } else console.log(expression)
388
- return expression
389
- },
390
- [DEBUG.ASSERT]: (args, env) => {
391
- if (args.length < 2)
392
- throw new RangeError(
393
- `Invalid number of arguments for (${
394
- DEBUG.ASSERT
395
- }), expected (> 2 required) but got ${args.length} (${
396
- DEBUG.ASSERT
397
- } ${stringifyArgs(args)})`
398
- )
399
- if (args.length % 2 !== 0)
400
- throw new RangeError(
401
- `Invalid number of arguments for (${
378
+ }
379
+ break
380
+ case 'char':
381
+ case 'ch':
382
+ {
383
+ if (typeof expression !== 'number')
384
+ throw new TypeError(
385
+ `Argument argument of (${DEBUG.LOG}) must be a (${
386
+ RUNTIME_TYPES.NUMBER
387
+ }) in the case ${type} but got (${expression}) (${
388
+ DEBUG.LOG
389
+ } ${stringifyArgs(args)})`
390
+ )
391
+ console.log(String.fromCharCode(expression))
392
+ }
393
+
394
+ break
395
+ case '*':
396
+ console.log(expression)
397
+ break
398
+ default:
399
+ throw new TypeError(
400
+ `Invalid number of option to (${
401
+ DEBUG.LOG
402
+ }) got ${option} ${stringifyArgs(args)})`
403
+ )
404
+ }
405
+ } else console.log(expression)
406
+ return expression
407
+ },
408
+ [DEBUG.ASSERT]: (args, env) => {
409
+ if (args.length < 2)
410
+ throw new RangeError(
411
+ `Invalid number of arguments for (${
412
+ DEBUG.ASSERT
413
+ }), expected (> 2 required) but got ${args.length} (${
414
+ DEBUG.ASSERT
415
+ } ${stringifyArgs(args)})`
416
+ )
417
+ if (args.length % 2 !== 0)
418
+ throw new RangeError(
419
+ `Invalid number of arguments for (${
420
+ DEBUG.ASSERT
421
+ }), expected even number of arguments but got ${args.length} (${
422
+ DEBUG.ASSERT
423
+ } ${stringifyArgs(args)})`
424
+ )
425
+ for (let i = 0; i < args.length; i += 2) {
426
+ const condition = evaluate(args[i], env)
427
+ if (condition !== FALSE && condition !== TRUE)
428
+ throw new TypeError(
429
+ `Condition of (${
402
430
  DEBUG.ASSERT
403
- }), expected even number of arguments but got ${args.length} (${
431
+ }) must be ${TRUE} or ${FALSE} but got (${
404
432
  DEBUG.ASSERT
405
433
  } ${stringifyArgs(args)})`
406
434
  )
407
- for (let i = 0; i < args.length; i += 2) {
408
- const condition = evaluate(args[i], env)
409
- if (condition !== FALSE && condition !== TRUE)
435
+ if (condition) {
436
+ const error = args[i + 1]
437
+ if (error[0][TYPE] === APPLY && error[0][VALUE] === KEYWORDS.ERROR)
438
+ return evaluate(error, env)
439
+ else
410
440
  throw new TypeError(
411
- `Condition of (${
412
- DEBUG.ASSERT
413
- }) must be ${TRUE} or ${FALSE} but got (${
414
- DEBUG.ASSERT
415
- } ${stringifyArgs(args)})`
441
+ `Concequence of (${DEBUG.ASSERT}) must be (${
442
+ KEYWORDS.ERROR
443
+ }) but got (${DEBUG.ASSERT} ${stringifyArgs(args)})`
416
444
  )
417
- if (condition) {
418
- const error = args[i + 1]
419
- if (error[0][TYPE] === APPLY && error[0][VALUE] === KEYWORDS.ERROR)
420
- return evaluate(error, env)
421
- else
422
- throw new TypeError(
423
- `Concequence of (${DEBUG.ASSERT}) must be (${
424
- KEYWORDS.ERROR
425
- }) but got (${DEBUG.ASSERT} ${stringifyArgs(args)})`
426
- )
427
- }
428
445
  }
429
- return 0
430
446
  }
447
+ return 0
448
+ }
449
+ }
450
+ try {
451
+ const evaluated = evaluate(ast, debugEnv)
452
+ const block = ast[1][1]
453
+ const temp = block.shift()
454
+ block.unshift(temp, identity(DEBUG.LOG), identity(DEBUG.ASSERT))
455
+ return {
456
+ evaluated,
457
+ compiled: compile(ast),
458
+ error: null
431
459
  }
432
- evaluate(ast, debugEnv)
433
460
  } catch (error) {
434
461
  const isMaxCallStack =
435
462
  error.message.includes('Maximum call stack size exceeded') ||
436
463
  error.message.includes('too much recursion')
437
- if (!isMaxCallStack) {
438
- error.message += `\n${callStack
439
- .reverse()
440
- .map((x, i) => `${Array(i + 2).join('.')}(${x})`)
441
- .join('\n')}`
442
- throw error
443
- } else logError(error.message)
464
+ return {
465
+ compiled: null,
466
+ evaluated: null,
467
+ error: {
468
+ message: isMaxCallStack
469
+ ? error.message
470
+ : `${error.message}\n${debugEnv[DEBUG.CALLSTACK]
471
+ .reverse()
472
+ .map((x, i) => `${Array(i + 2).join(' ')}(${x} ...)`)
473
+ .join('\n')}`,
474
+ stack: debugEnv[DEBUG.CALLSTACK]
475
+ }
476
+ }
444
477
  }
445
- const block = ast[1][1]
446
- const temp = block.shift()
447
- block.unshift(temp, identity(DEBUG.LOG), identity(DEBUG.ASSERT))
448
- return compile(ast)
449
478
  }