fez-lisp 1.2.33 → 1.2.35

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.2.33",
5
+ "version": "1.2.35",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/compiler.js CHANGED
@@ -109,7 +109,8 @@ const Helpers = {
109
109
  __tco: `__tco=fn=>(...args)=>{let result=fn(...args);while(typeof result==='function')result=result();return result}`,
110
110
  atom_predicate: `atom_predicate=(number)=>+(typeof number==='number')`,
111
111
  lambda_predicate: `lambda_predicate=(fm)=>+(typeof fn==='function')`,
112
- set_effect: `set_effect=(array,index,value)=>{if(index<0){const target=array.length+index;while(array.length!==target)array.pop()}else array[index] = value;return array}`
112
+ set_effect: `set_effect=(array,index,value)=>{if(index<0){const target=array.length+index;while(array.length!==target)array.pop()}else array[index] = value;return array}`,
113
+ __error: `__error=(error)=>{throw new Error(error.map((x)=>String.fromCharCode(x)).join(''))}`
113
114
  }
114
115
  const semiColumnEdgeCases = new Set([
115
116
  ';)',
@@ -141,6 +142,8 @@ const compile = (tree, Drill) => {
141
142
  const token = first[VALUE]
142
143
  if (first[TYPE] === APPLY) {
143
144
  switch (token) {
145
+ case KEYWORDS.ASSERT:
146
+ return '0'
144
147
  case KEYWORDS.BLOCK: {
145
148
  if (Arguments.length > 1) {
146
149
  return `(${Arguments.map((x) =>
@@ -292,12 +295,10 @@ const compile = (tree, Drill) => {
292
295
  out += '0);'
293
296
  return out
294
297
  }
295
- // case KEYWORDS.PIPE: {
296
- // let inp = Arguments[0]
297
- // for (let i = 1; i < Arguments.length; ++i)
298
- // inp = [Arguments[i].shift(), inp, ...Arguments[i]]
299
- // return compile(inp, Drill)
300
- // }
298
+ case KEYWORDS.THROW: {
299
+ Drill.Helpers.add('__error')
300
+ return `__error(${compile(Arguments[0], Drill)})`
301
+ }
301
302
  default: {
302
303
  const camelCased = lispToJavaScriptVariableName(token)
303
304
  if (camelCased in Helpers) Drill.Helpers.add(camelCased)
@@ -3,14 +3,12 @@ import {
3
3
  VALUE,
4
4
  WORD,
5
5
  KEYWORDS,
6
- APPLY,
7
- ATOM,
8
6
  FALSE,
9
7
  TRUE,
10
- TYPES
8
+ TYPES,
9
+ APPLY
11
10
  } from './keywords.js'
12
11
  import { evaluate } from './evaluator.js'
13
- import { isLeaf } from './parser.js'
14
12
  import { isForbiddenVariableName, stringifyArgs } from './utils.js'
15
13
  const keywords = {
16
14
  [KEYWORDS.REMAINDER_OF_DIVISION]: (args, env) => {
@@ -172,7 +170,9 @@ const keywords = {
172
170
  const condition = evaluate(args[0], env)
173
171
  if (condition !== FALSE && condition !== TRUE)
174
172
  throw new TypeError(
175
- `Condition of (${KEYWORDS.IF}) must be ${TRUE} or ${FALSE} but got ${condition}`
173
+ `Condition of (${KEYWORDS.IF}) must be ${TRUE} or ${FALSE} but got (${
174
+ KEYWORDS.IF
175
+ } ${stringifyArgs(args)})`
176
176
  )
177
177
  return condition
178
178
  ? evaluate(args[1], env)
@@ -201,7 +201,11 @@ const keywords = {
201
201
  const condition = evaluate(args[i], env)
202
202
  if (condition !== FALSE && condition !== TRUE)
203
203
  throw new TypeError(
204
- `Condition of (${KEYWORDS.CONDITION}) must be ${TRUE} or ${FALSE} but got ${condition}`
204
+ `Condition of (${
205
+ KEYWORDS.CONDITION
206
+ }) must be ${TRUE} or ${FALSE} but got (${
207
+ KEYWORDS.CONDITION
208
+ } ${stringifyArgs(args)})`
205
209
  )
206
210
  if (condition) return evaluate(args[i + 1], env)
207
211
  }
@@ -437,7 +441,11 @@ const keywords = {
437
441
  circuit = evaluate(args[i], env)
438
442
  if (circuit !== FALSE && circuit !== TRUE)
439
443
  throw new TypeError(
440
- `Condition of (${KEYWORDS.AND}) must be ${TRUE} or ${FALSE} but got ${circuit}`
444
+ `Condition of (${
445
+ KEYWORDS.AND
446
+ }) must be ${TRUE} or ${FALSE} but got (${
447
+ KEYWORDS.AND
448
+ } ${stringifyArgs(args)})`
441
449
  )
442
450
  if (circuit) continue
443
451
  else return 0
@@ -445,7 +453,9 @@ const keywords = {
445
453
  const end = evaluate(args.at(-1), env)
446
454
  if (end !== FALSE && end !== TRUE)
447
455
  throw new TypeError(
448
- `Condition of (${KEYWORDS.AND}) must be ${TRUE} or ${FALSE} but got ${end}`
456
+ `Condition of (${KEYWORDS.AND}) must be ${TRUE} or ${FALSE} but got (${
457
+ KEYWORDS.AND
458
+ } ${stringifyArgs(args)})`
449
459
  )
450
460
  return end
451
461
  },
@@ -461,7 +471,9 @@ const keywords = {
461
471
  circuit = evaluate(args[i], env)
462
472
  if (circuit !== FALSE && circuit !== TRUE)
463
473
  throw new TypeError(
464
- `Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got ${circuit}`
474
+ `Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got (${
475
+ KEYWORDS.OR
476
+ } ${stringifyArgs(args)})`
465
477
  )
466
478
  if (circuit) return 1
467
479
  else continue
@@ -469,7 +481,9 @@ const keywords = {
469
481
  const end = evaluate(args.at(-1), env)
470
482
  if (end !== FALSE && end !== TRUE)
471
483
  throw new TypeError(
472
- `Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got ${end}`
484
+ `Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got (${
485
+ KEYWORDS.OR
486
+ } ${stringifyArgs(args)})`
473
487
  )
474
488
  return end
475
489
  },
@@ -795,8 +809,67 @@ const keywords = {
795
809
  )
796
810
  console.clear()
797
811
  return 0
812
+ },
813
+
814
+ // Not sure about these
815
+ [KEYWORDS.THROW]: (args, env) => {
816
+ if (args.length !== 1)
817
+ throw new RangeError(
818
+ `Invalid number of arguments to (${KEYWORDS.THROW}) (= 1 required) (${
819
+ KEYWORDS.THROW
820
+ } ${stringifyArgs(args)})`
821
+ )
822
+ const expression = evaluate(args[0], env)
823
+ if (!Array.isArray(expression))
824
+ throw new TypeError(
825
+ `Argument of (${KEYWORDS.THROW}) must be an (${
826
+ KEYWORDS.ARRAY_TYPE
827
+ }) but got (${expression}) (${KEYWORDS.THROW} ${stringifyArgs(args)})`
828
+ )
829
+ throw new Error(expression.map((x) => String.fromCharCode(x)).join(''))
830
+ },
831
+
832
+ [KEYWORDS.ASSERT]: (args, env) => {
833
+ if (args.length < 2)
834
+ throw new RangeError(
835
+ `Invalid number of arguments for (${
836
+ KEYWORDS.ASSERT
837
+ }), expected (> 2 required) but got ${args.length} (${
838
+ KEYWORDS.ASSERT
839
+ } ${stringifyArgs(args)})`
840
+ )
841
+ if (args.length % 2 !== 0)
842
+ throw new RangeError(
843
+ `Invalid number of arguments for (${
844
+ KEYWORDS.ASSERT
845
+ }), expected even number of arguments but got ${args.length} (${
846
+ KEYWORDS.ASSERT
847
+ } ${stringifyArgs(args)})`
848
+ )
849
+ for (let i = 0; i < args.length; i += 2) {
850
+ const condition = evaluate(args[i], env)
851
+ if (condition !== FALSE && condition !== TRUE)
852
+ throw new TypeError(
853
+ `Condition of (${
854
+ KEYWORDS.ASSERT
855
+ }) must be ${TRUE} or ${FALSE} but got (${
856
+ KEYWORDS.ASSERT
857
+ } ${stringifyArgs(args)})`
858
+ )
859
+ if (condition) {
860
+ const error = args[i + 1]
861
+ if (error[0][TYPE] === APPLY && error[0][VALUE] === KEYWORDS.THROW)
862
+ return evaluate(error, env)
863
+ else
864
+ throw new TypeError(
865
+ `Concequence of (${KEYWORDS.ASSERT}) must be (${
866
+ KEYWORDS.THROW
867
+ }) but got (${KEYWORDS.ASSERT} ${stringifyArgs(args)})`
868
+ )
869
+ }
870
+ }
871
+ return 0
798
872
  }
799
873
  }
800
- keywords[KEYWORDS.NOT_COMPILED_BLOCK] = keywords[KEYWORDS.BLOCK]
801
874
 
802
875
  export { keywords }
package/src/keywords.js CHANGED
@@ -44,12 +44,14 @@ export const KEYWORDS = {
44
44
 
45
45
  SET_ARRAY: 'set!',
46
46
 
47
- NOT_COMPILED_BLOCK: 'void',
48
47
  LOG: 'log!',
49
48
  LOG_STRING: 'log-string!',
50
49
  LOG_CHAR: 'log-char!',
51
50
  CLEAR_CONSOLE: 'clear!',
52
51
 
52
+ THROW: 'throw',
53
+ ASSERT: 'assert',
54
+
53
55
  // Syntactic suggars
54
56
  PIPE: '|>',
55
57
  NOT_EQUAL_1: '!=',
package/src/utils.js CHANGED
@@ -70,7 +70,7 @@ export const stringifyArrayTypes = (type) =>
70
70
  : 'number'
71
71
  export const stringifyType = (type) => {
72
72
  if (!isLeaf(type)) {
73
- const [car, ...cdr] = type
73
+ const [car] = type
74
74
  if (car == undefined) return '(array)'
75
75
  else if (car[TYPE] === APPLY && car[VALUE] === KEYWORDS.ARRAY_TYPE)
76
76
  return `(array ${type