fez-lisp 1.3.27 → 1.4.0

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.
@@ -10,13 +10,14 @@ import {
10
10
  } from './keywords.js'
11
11
  import { evaluate } from './evaluator.js'
12
12
  import { isForbiddenVariableName, stringifyArgs } from './utils.js'
13
+ import { LISP } from './parser.js'
13
14
  export const keywords = {
14
15
  [KEYWORDS.ADDITION]: (args, env) => {
15
16
  if (args.length !== 2)
16
17
  throw new RangeError(
17
18
  `Invalid number of arguments for (${
18
19
  KEYWORDS.ADDITION
19
- }), expected (= 2) but got ${args.length}. (${
20
+ }), expected (= 2) but got ${args.length}\n\nat:\n(${
20
21
  KEYWORDS.ADDITION
21
22
  } ${stringifyArgs(args)})`
22
23
  )
@@ -25,35 +26,39 @@ export const keywords = {
25
26
  throw new TypeError(
26
27
  `First arguments of (${KEYWORDS.ADDITION}) is not a (${
27
28
  RUNTIME_TYPES.NUMBER
28
- }) (${KEYWORDS.ADDITION} ${stringifyArgs(args)})`
29
+ })\n\nat:\n(${KEYWORDS.ADDITION} ${stringifyArgs(args)})`
29
30
  )
30
31
  const b = evaluate(args[1], env)
31
32
  if (typeof b !== 'number')
32
33
  throw new TypeError(
33
34
  `Second arguments of (${KEYWORDS.ADDITION}) is not a (${
34
35
  RUNTIME_TYPES.NUMBER
35
- }) (${KEYWORDS.ADDITION} ${stringifyArgs(args)})`
36
+ })\n\nat:\n(${KEYWORDS.ADDITION} ${stringifyArgs(args)})`
36
37
  )
37
38
  return a + b
38
39
  },
39
40
  [KEYWORDS.MULTIPLICATION]: (args, env) => {
40
41
  if (args.length !== 2)
41
42
  throw new RangeError(
42
- `Invalid number of arguments for (${KEYWORDS.MULTIPLICATION}), expected (= 2) but got ${args.length}.`
43
+ `Invalid number of arguments for (${
44
+ KEYWORDS.MULTIPLICATION
45
+ }), expected (= 2) but got ${args.length}\n\nat:\n(${
46
+ KEYWORDS.MULTIPLICATION
47
+ } ${stringifyArgs(args)})`
43
48
  )
44
49
  const a = evaluate(args[0], env)
45
50
  if (typeof a !== 'number')
46
51
  throw new TypeError(
47
52
  `First arguments of (${KEYWORDS.MULTIPLICATION}) is not a (${
48
53
  RUNTIME_TYPES.NUMBER
49
- }) (${KEYWORDS.MULTIPLICATION} ${stringifyArgs(args)})`
54
+ })\n\nat:\n(${KEYWORDS.MULTIPLICATION} ${stringifyArgs(args)})`
50
55
  )
51
56
  const b = evaluate(args[1], env)
52
57
  if (typeof b !== 'number')
53
58
  throw new TypeError(
54
59
  `Second arguments of (${KEYWORDS.MULTIPLICATION}) is not a (${
55
60
  RUNTIME_TYPES.NUMBER
56
- }) (${KEYWORDS.MULTIPLICATION} ${stringifyArgs(args)})`
61
+ })\n\nat:\n(${KEYWORDS.MULTIPLICATION} ${stringifyArgs(args)})`
57
62
  )
58
63
  return a * b
59
64
  },
@@ -62,7 +67,7 @@ export const keywords = {
62
67
  throw new RangeError(
63
68
  `Invalid number of arguments for (${
64
69
  KEYWORDS.SUBTRACTION
65
- }), expected (or (= 1)) (= 2) but got ${args.length}. (${
70
+ }), expected (or (= 1) (= 2)) but got ${args.length}\n\nat:\n(${
66
71
  KEYWORDS.SUBTRACTION
67
72
  } ${stringifyArgs(args)})`
68
73
  )
@@ -71,7 +76,7 @@ export const keywords = {
71
76
  throw new TypeError(
72
77
  `First argument of (${KEYWORDS.SUBTRACTION}) is not a (${
73
78
  RUNTIME_TYPES.NUMBER
74
- }) (${KEYWORDS.SUBTRACTION} ${stringifyArgs(args)})`
79
+ })\n\nat:\n(${KEYWORDS.SUBTRACTION} ${stringifyArgs(args)})`
75
80
  )
76
81
  if (args.length === 1) return -a
77
82
  const b = evaluate(args[1], env)
@@ -79,34 +84,38 @@ export const keywords = {
79
84
  throw new TypeError(
80
85
  `Second argument of (${KEYWORDS.SUBTRACTION}) is not a (${
81
86
  RUNTIME_TYPES.NUMBER
82
- }) (${KEYWORDS.SUBTRACTION} ${stringifyArgs(args)})`
87
+ })\n\nat:\n(${KEYWORDS.SUBTRACTION} ${stringifyArgs(args)})`
83
88
  )
84
89
  return a - b
85
90
  },
86
91
  [KEYWORDS.DIVISION]: (args, env) => {
87
92
  if (args.length !== 2)
88
93
  throw new RangeError(
89
- `Invalid number of arguments for (${KEYWORDS.DIVISION}), expected (= 2) but got ${args.length}.`
94
+ `Invalid number of arguments for (${
95
+ KEYWORDS.DIVISION
96
+ }), expected (= 2) but got ${args.length}\n\nat:\n(${
97
+ KEYWORDS.DIVISION
98
+ } ${stringifyArgs(args)})`
90
99
  )
91
100
  const a = evaluate(args[0], env)
92
101
  if (typeof a !== 'number')
93
102
  throw new TypeError(
94
103
  `First argument of (${KEYWORDS.DIVISION}) is not (${
95
104
  RUNTIME_TYPES.NUMBER
96
- }) (${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
105
+ })\n\nat:\n(${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
97
106
  )
98
107
  const b = evaluate(args[1], env)
99
108
  if (typeof b !== 'number')
100
109
  throw new TypeError(
101
110
  `Second argument of (${KEYWORDS.DIVISION}) is not (${
102
111
  RUNTIME_TYPES.NUMBER
103
- }) (${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
112
+ })\n\nat:\n(${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
104
113
  )
105
114
  if (b === 0)
106
115
  throw new TypeError(
107
116
  `Second Argument of (${
108
117
  KEYWORDS.DIVISION
109
- }) can't be a (0) (division by 0 is not allowed) (${
118
+ }) can't be a (0) (division by 0 is not allowed)\n\nat:\n(${
110
119
  KEYWORDS.DIVISION
111
120
  } ${stringifyArgs(args)})`
112
121
  )
@@ -117,7 +126,7 @@ export const keywords = {
117
126
  throw new RangeError(
118
127
  `Invalid number of arguments for (${
119
128
  KEYWORDS.REMAINDER_OF_DIVISION
120
- }), expected (= 2) but got ${args.length}. (${
129
+ }), expected (= 2) but got ${args.length}\n\nat:\n(${
121
130
  KEYWORDS.REMAINDER_OF_DIVISION
122
131
  } ${stringifyArgs(args)})`
123
132
  )
@@ -126,20 +135,20 @@ export const keywords = {
126
135
  throw new TypeError(
127
136
  `First argument of (${KEYWORDS.REMAINDER_OF_DIVISION}) is not (${
128
137
  RUNTIME_TYPES.NUMBER
129
- }) (${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)})`
138
+ })\n\nat:\n(${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)})`
130
139
  )
131
140
  const b = evaluate(args[1], env)
132
141
  if (typeof b !== 'number')
133
142
  throw new TypeError(
134
143
  `Second argument of (${KEYWORDS.REMAINDER_OF_DIVISION}) is not (${
135
144
  RUNTIME_TYPES.NUMBER
136
- }) (${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)})`
145
+ })\n\nat:\n(${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)})`
137
146
  )
138
147
  if (b === 0)
139
148
  throw new TypeError(
140
149
  `Second argument of (${
141
150
  KEYWORDS.REMAINDER_OF_DIVISION
142
- }) can't be a (0) (division by 0 is not allowed) (${
151
+ }) can't be a (0) (division by 0 is not allowed)\n\nat:\n(${
143
152
  KEYWORDS.REMAINDER_OF_DIVISION
144
153
  } ${stringifyArgs(args)})`
145
154
  )
@@ -151,21 +160,23 @@ export const keywords = {
151
160
  throw new RangeError(
152
161
  `Invalid number of arguments to (${
153
162
  KEYWORDS.BITWISE_AND
154
- }) (= 2 required). (${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
163
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.BITWISE_AND} ${stringifyArgs(
164
+ args
165
+ )})`
155
166
  )
156
167
  const a = evaluate(args[0], env)
157
168
  if (typeof a !== 'number')
158
169
  throw new TypeError(
159
170
  `First arguments of (${KEYWORDS.BITWISE_AND}) is not a (${
160
171
  RUNTIME_TYPES.NUMBER
161
- }) (${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
172
+ })\n\nat:\n(${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
162
173
  )
163
174
  const b = evaluate(args[1], env)
164
175
  if (typeof b !== 'number')
165
176
  throw new TypeError(
166
177
  `Second arguments of (${KEYWORDS.BITWISE_AND}) is not a (${
167
178
  RUNTIME_TYPES.NUMBER
168
- }) (${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
179
+ })\n\nat:\n(${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
169
180
  )
170
181
  return a & b
171
182
  },
@@ -174,14 +185,16 @@ export const keywords = {
174
185
  throw new RangeError(
175
186
  `Invalid number of arguments to (${
176
187
  KEYWORDS.BITWISE_NOT
177
- }) (= 1 required). (${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)})`
188
+ }) (= 1 required)\n\nat:\n(${KEYWORDS.BITWISE_NOT} ${stringifyArgs(
189
+ args
190
+ )})`
178
191
  )
179
192
  const operand = evaluate(args[0], env)
180
193
  if (typeof operand !== 'number')
181
194
  throw new TypeError(
182
195
  `Argument of (${KEYWORDS.BITWISE_NOT}) is not a (${
183
196
  RUNTIME_TYPES.NUMBER
184
- }) (${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)})`
197
+ })\n\nat:\n(${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)})`
185
198
  )
186
199
  return ~operand
187
200
  },
@@ -190,7 +203,9 @@ export const keywords = {
190
203
  throw new RangeError(
191
204
  `Invalid number of arguments to (${
192
205
  KEYWORDS.BITWISE_OR
193
- }) (= 2 required). (${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)})`
206
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.BITWISE_OR} ${stringifyArgs(
207
+ args
208
+ )})`
194
209
  )
195
210
  const a = evaluate(args[0], env)
196
211
  const b = evaluate(args[1], env)
@@ -198,7 +213,7 @@ export const keywords = {
198
213
  throw new TypeError(
199
214
  `Not all arguments of (${KEYWORDS.BITWISE_OR}) are (${
200
215
  RUNTIME_TYPES.NUMBER
201
- }) (${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)})`
216
+ })\n\nat:\n(${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)})`
202
217
  )
203
218
  return a | b
204
219
  },
@@ -207,7 +222,9 @@ export const keywords = {
207
222
  throw new RangeError(
208
223
  `Invalid number of arguments to (${
209
224
  KEYWORDS.BITWISE_XOR
210
- }) (= 2 required). (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
225
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.BITWISE_XOR} ${stringifyArgs(
226
+ args
227
+ )})`
211
228
  )
212
229
  const a = evaluate(args[0], env)
213
230
  const b = evaluate(args[1], env)
@@ -215,7 +232,7 @@ export const keywords = {
215
232
  throw new TypeError(
216
233
  `Not all arguments of (${KEYWORDS.BITWISE_XOR}) are (${
217
234
  RUNTIME_TYPES.NUMBER
218
- }) (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
235
+ })\n\nat:\n(${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
219
236
  )
220
237
  return a ^ b
221
238
  },
@@ -224,9 +241,9 @@ export const keywords = {
224
241
  throw new RangeError(
225
242
  `Invalid number of arguments to (${
226
243
  KEYWORDS.BITWISE_LEFT_SHIFT
227
- }) (= 2 required). (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(
228
- args
229
- )})`
244
+ }) (= 2 required)\n\nat:\n(${
245
+ KEYWORDS.BITWISE_LEFT_SHIFT
246
+ } ${stringifyArgs(args)})`
230
247
  )
231
248
  const a = evaluate(args[0], env)
232
249
  const b = evaluate(args[1], env)
@@ -234,7 +251,7 @@ export const keywords = {
234
251
  throw new TypeError(
235
252
  `Not all arguments of (${KEYWORDS.BITWISE_LEFT_SHIFT}) are (${
236
253
  RUNTIME_TYPES.NUMBER
237
- }) (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(args)})`
254
+ })\n\nat:\n(${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(args)})`
238
255
  )
239
256
  return a << b
240
257
  },
@@ -243,9 +260,9 @@ export const keywords = {
243
260
  throw new RangeError(
244
261
  `Invalid number of arguments to (${
245
262
  KEYWORDS.BITWISE_RIGHT_SHIFT
246
- }) (= 2 required). (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(
247
- args
248
- )})`
263
+ }) (= 2 required)\n\nat:\n(${
264
+ KEYWORDS.BITWISE_RIGHT_SHIFT
265
+ } ${stringifyArgs(args)})`
249
266
  )
250
267
  const a = evaluate(args[0], env)
251
268
  const b = evaluate(args[1], env)
@@ -253,7 +270,7 @@ export const keywords = {
253
270
  throw new TypeError(
254
271
  `Not all arguments of (${KEYWORDS.BITWISE_RIGHT_SHIFT}) are (${
255
272
  RUNTIME_TYPES.NUMBER
256
- }) (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(args)})`
273
+ })\n\nat:\n(${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(args)})`
257
274
  )
258
275
  return a >> b
259
276
  },
@@ -262,7 +279,7 @@ export const keywords = {
262
279
  throw new RangeError(
263
280
  `Invalid number of arguments to (${
264
281
  KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT
265
- }) (= 2 required). (${
282
+ }) (= 2 required)\n\nat:\n(${
266
283
  KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT
267
284
  } ${stringifyArgs(args)})`
268
285
  )
@@ -272,7 +289,9 @@ export const keywords = {
272
289
  throw new TypeError(
273
290
  `Not all arguments of (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT}) are (${
274
291
  RUNTIME_TYPES.NUMBER
275
- }) (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT} ${stringifyArgs(args)})`
292
+ })\n\nat:\n(${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT} ${stringifyArgs(
293
+ args
294
+ )})`
276
295
  )
277
296
  return a >>> b
278
297
  },
@@ -284,40 +303,48 @@ export const keywords = {
284
303
  throw new RangeError(
285
304
  `Invalid number of arguments for (${
286
305
  KEYWORDS.GET_ARRAY
287
- }) (= 2 required) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
306
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(
307
+ args
308
+ )})`
288
309
  )
289
310
  const array = evaluate(args[0], env)
290
311
  if (!Array.isArray(array))
291
312
  throw new TypeError(
292
313
  `First argument of (${KEYWORDS.GET_ARRAY}) must be an (${
293
314
  RUNTIME_TYPES.ARRAY
294
- })) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
315
+ })\n\nat:\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
295
316
  )
296
317
  if (array.length === 0)
297
318
  throw new RangeError(
298
319
  `First argument of (${KEYWORDS.GET_ARRAY}) is an empty (${
299
320
  RUNTIME_TYPES.ARRAY
300
- })) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)}))`
321
+ })\n\nat:\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
301
322
  )
302
323
  const index = evaluate(args[1], env)
303
- if (!Number.isInteger(index))
324
+ if (!Number.isInteger(index) || index < 0)
304
325
  throw new TypeError(
305
- `Second argument of (${KEYWORDS.GET_ARRAY}) must be an (32 bit ${
326
+ `Second argument of (${
327
+ KEYWORDS.GET_ARRAY
328
+ }) must be a positive (32 bit ${
306
329
  RUNTIME_TYPES.NUMBER
307
- }) (${index}) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
330
+ }) (= i ${index})\n\nat:\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(
331
+ args
332
+ )})`
308
333
  )
309
- if (index > array.length - 1 || index * -1 > array.length)
334
+ if (index > array.length - 1)
310
335
  throw new RangeError(
311
336
  `Second argument of (${KEYWORDS.GET_ARRAY}) is outside of (${
312
337
  RUNTIME_TYPES.ARRAY
313
- }) bounds (${index}) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
338
+ }) bounds (= i ${index}) expected (and (>= i 0) (< i ${
339
+ array.length
340
+ }))\n\nat:\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
314
341
  )
315
342
  const value = array.at(index)
316
343
  if (value == undefined)
317
344
  throw new RangeError(
318
345
  `Trying to get a null value in (${RUNTIME_TYPES.ARRAY}) at (${
319
346
  KEYWORDS.GET_ARRAY
320
- }) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
347
+ })\n\nat:\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
321
348
  )
322
349
  return value
323
350
  },
@@ -326,14 +353,18 @@ export const keywords = {
326
353
  throw new RangeError(
327
354
  `Invalid number of arguments for (${
328
355
  KEYWORDS.SET_ARRAY
329
- }) (or 1 3) required (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
356
+ }) (or 1 3) required\n\nat:\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(
357
+ args
358
+ )})`
330
359
  )
331
360
  const array = evaluate(args[0], env)
332
361
  if (!Array.isArray(array))
333
362
  throw new TypeError(
334
363
  `First argument of (${KEYWORDS.SET_ARRAY}) must be an (${
335
364
  RUNTIME_TYPES.ARRAY
336
- }) but got (${array}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
365
+ }) but got (${array})\n\nat:\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(
366
+ args
367
+ )})`
337
368
  )
338
369
  if (args.length === 1) {
339
370
  array.pop()
@@ -343,22 +374,24 @@ export const keywords = {
343
374
  throw new TypeError(
344
375
  `Second argument of (${KEYWORDS.SET_ARRAY}) must be a positive (${
345
376
  RUNTIME_TYPES.NUMBER
346
- } integer) (${index}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
377
+ } integer) (= i ${index})\n\nat:\n(${
378
+ KEYWORDS.SET_ARRAY
379
+ } ${stringifyArgs(args)})`
347
380
  )
348
381
  if (index > array.length)
349
382
  throw new RangeError(
350
383
  `Second argument of (${KEYWORDS.SET_ARRAY}) is outside of the (${
351
384
  RUNTIME_TYPES.ARRAY
352
- }) bounds (index ${index} bounds ${array.length}) (${
353
- KEYWORDS.SET_ARRAY
354
- } ${stringifyArgs(args)})`
385
+ }) bounds (${index}) expected (and (>= i 0) (< i ${
386
+ array.length
387
+ }))\n\nat:\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
355
388
  )
356
389
  const value = evaluate(args[2], env)
357
390
  if (value == undefined)
358
391
  throw new RangeError(
359
392
  `Trying to set a null value in (${RUNTIME_TYPES.ARRAY}) at (${
360
393
  KEYWORDS.SET_ARRAY
361
- }). (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
394
+ })\n\nat:\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
362
395
  )
363
396
  array[index] = value
364
397
  }
@@ -369,14 +402,16 @@ export const keywords = {
369
402
  throw new RangeError(
370
403
  `Invalid number of arguments for (${
371
404
  KEYWORDS.ARRAY_LENGTH
372
- }) (= 1 required) (${KEYWORDS.ARRAY_LENGTH} ${stringifyArgs(args)})`
405
+ }) (= 1 required)\n\nat:\n(${KEYWORDS.ARRAY_LENGTH} ${stringifyArgs(
406
+ args
407
+ )})`
373
408
  )
374
409
  const array = evaluate(args[0], env)
375
410
  if (!Array.isArray(array))
376
411
  throw new TypeError(
377
412
  `First argument of (${KEYWORDS.ARRAY_LENGTH}) must be an ${
378
413
  RUNTIME_TYPES.ARRAY
379
- } (${KEYWORDS.ARRAY_LENGTH} ${stringifyArgs(args)})`
414
+ }\n\nat:\n(${KEYWORDS.ARRAY_LENGTH} ${stringifyArgs(args)})`
380
415
  )
381
416
  return array.length
382
417
  },
@@ -385,16 +420,18 @@ export const keywords = {
385
420
  throw new RangeError(
386
421
  `Invalid number of arguments for (${
387
422
  KEYWORDS.IF
388
- }), expected (or (= 3) (= 2)) but got ${args.length} (${
423
+ }), expected (or (= 3) (= 2)) but got ${args.length}\n\nat:\n(${
389
424
  KEYWORDS.IF
390
425
  } ${stringifyArgs(args)})`
391
426
  )
392
427
  const condition = evaluate(args[0], env)
393
428
  if (condition !== FALSE && condition !== TRUE)
394
429
  throw new TypeError(
395
- `Condition of (${KEYWORDS.IF}) must be ${TRUE} or ${FALSE} but got (${
430
+ `Condition of (${
396
431
  KEYWORDS.IF
397
- } ${stringifyArgs(args)})`
432
+ }) must be ${TRUE} or ${FALSE} but got ${LISP.source(
433
+ args[0]
434
+ )}\n\nat:\n(${KEYWORDS.IF} ${stringifyArgs(args)})`
398
435
  )
399
436
  return condition
400
437
  ? evaluate(args[1], env)
@@ -405,25 +442,27 @@ export const keywords = {
405
442
  [KEYWORDS.NOT]: (args, env) => {
406
443
  if (args.length !== 1)
407
444
  throw new RangeError(
408
- `Invalid number of arguments for (${KEYWORDS.NOT}) (= 1 required) (${
445
+ `Invalid number of arguments for (${
409
446
  KEYWORDS.NOT
410
- } ${stringifyArgs(args)})`
447
+ }) (= 1 required)\n\nat:\n(${KEYWORDS.NOT} ${stringifyArgs(args)})`
411
448
  )
412
449
  const operand = evaluate(args[0], env)
413
450
  if (operand !== FALSE && operand !== TRUE)
414
451
  throw new TypeError(
415
- `Condition of (${KEYWORDS.NOT}) must be ${TRUE} or ${FALSE} but got (${
452
+ `Condition of (${
416
453
  KEYWORDS.NOT
417
- } ${stringifyArgs(args)})`
454
+ }) must be ${TRUE} or ${FALSE} but got ${LISP.source(
455
+ args[0]
456
+ )}\n\nat:\n(${KEYWORDS.NOT} ${stringifyArgs(args)})`
418
457
  )
419
458
  return +!evaluate(args[0], env)
420
459
  },
421
460
  [KEYWORDS.EQUAL]: (args, env) => {
422
461
  if (args.length !== 2)
423
462
  throw new RangeError(
424
- `Invalid number of arguments for (${KEYWORDS.EQUAL}) (= 2 required) (${
463
+ `Invalid number of arguments for (${
425
464
  KEYWORDS.EQUAL
426
- } ${stringifyArgs(args)})`
465
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
427
466
  )
428
467
  const a = evaluate(args[0], env)
429
468
  const b = evaluate(args[1], env)
@@ -431,13 +470,13 @@ export const keywords = {
431
470
  throw new TypeError(
432
471
  `Invalid use of (${KEYWORDS.EQUAL}), first argument is not an ${
433
472
  RUNTIME_TYPES.NUMBER
434
- } (${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
473
+ }\n\nat:\n(${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
435
474
  )
436
475
  if (typeof b !== 'number')
437
476
  throw new TypeError(
438
477
  `Invalid use of (${KEYWORDS.EQUAL}), second argument are not an ${
439
478
  RUNTIME_TYPES.NUMBER
440
- } (${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
479
+ }\n\nat:\n(${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
441
480
  )
442
481
  return +(a === b)
443
482
  },
@@ -446,7 +485,9 @@ export const keywords = {
446
485
  throw new RangeError(
447
486
  `Invalid number of arguments for (${
448
487
  KEYWORDS.LESS_THAN
449
- }) (= 2 required) (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
488
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.LESS_THAN} ${stringifyArgs(
489
+ args
490
+ )})`
450
491
  )
451
492
  const a = evaluate(args[0], env)
452
493
  const b = evaluate(args[1], env)
@@ -454,13 +495,13 @@ export const keywords = {
454
495
  throw new TypeError(
455
496
  `Invalid use of (${KEYWORDS.LESS_THAN}), first argument is not an ${
456
497
  RUNTIME_TYPES.NUMBER
457
- } (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
498
+ }\n\nat:\n(${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
458
499
  )
459
500
  if (typeof b !== 'number')
460
501
  throw new TypeError(
461
502
  `Invalid use of (${KEYWORDS.LESS_THAN}), second argument are not an ${
462
503
  RUNTIME_TYPES.NUMBER
463
- } (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
504
+ }\n\nat:\n(${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
464
505
  )
465
506
  return +(a < b)
466
507
  },
@@ -469,7 +510,9 @@ export const keywords = {
469
510
  throw new RangeError(
470
511
  `Invalid number of arguments for (${
471
512
  KEYWORDS.GREATHER_THAN
472
- }) (= 2 required) (${KEYWORDS.GREATHER_THAN} ${stringifyArgs(args)})`
513
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.GREATHER_THAN} ${stringifyArgs(
514
+ args
515
+ )})`
473
516
  )
474
517
  const a = evaluate(args[0], env)
475
518
  const b = evaluate(args[1], env)
@@ -477,13 +520,13 @@ export const keywords = {
477
520
  throw new TypeError(
478
521
  `Invalid use of (${KEYWORDS.GREATHER_THAN}), first argument is not an ${
479
522
  RUNTIME_TYPES.NUMBER
480
- } (${KEYWORDS.GREATHER_THAN} ${stringifyArgs(args)})`
523
+ }\n\nat:\n(${KEYWORDS.GREATHER_THAN} ${stringifyArgs(args)})`
481
524
  )
482
525
  if (typeof b !== 'number')
483
526
  throw new TypeError(
484
527
  `Invalid use of (${
485
528
  KEYWORDS.GREATHER_THAN
486
- }), second argument are not an ${RUNTIME_TYPES.NUMBER} (${
529
+ }), second argument are not an ${RUNTIME_TYPES.NUMBER}\n\nat:\n(${
487
530
  KEYWORDS.GREATHER_THAN
488
531
  } ${stringifyArgs(args)})`
489
532
  )
@@ -494,9 +537,9 @@ export const keywords = {
494
537
  throw new RangeError(
495
538
  `Invalid number of arguments for (${
496
539
  KEYWORDS.GREATHER_THAN_OR_EQUAL
497
- }) (= 2 required) (${KEYWORDS.GREATHER_THAN_OR_EQUAL} ${stringifyArgs(
498
- args
499
- )})`
540
+ }) (= 2 required)\n\nat:\n(${
541
+ KEYWORDS.GREATHER_THAN_OR_EQUAL
542
+ } ${stringifyArgs(args)})`
500
543
  )
501
544
  const a = evaluate(args[0], env)
502
545
  const b = evaluate(args[1], env)
@@ -504,7 +547,7 @@ export const keywords = {
504
547
  throw new TypeError(
505
548
  `Invalid use of (${
506
549
  KEYWORDS.GREATHER_THAN_OR_EQUAL
507
- }), first argument is not an ${RUNTIME_TYPES.NUMBER} (${
550
+ }), first argument is not an ${RUNTIME_TYPES.NUMBER}\n\nat:\n(${
508
551
  KEYWORDS.GREATHER_THAN_OR_EQUAL
509
552
  } ${stringifyArgs(args)})`
510
553
  )
@@ -512,7 +555,7 @@ export const keywords = {
512
555
  throw new TypeError(
513
556
  `Invalid use of (${
514
557
  KEYWORDS.GREATHER_THAN_OR_EQUAL
515
- }), second argument are not an ${RUNTIME_TYPES.NUMBER} (${
558
+ }), second argument are not an ${RUNTIME_TYPES.NUMBER}\n\nat:\n(${
516
559
  KEYWORDS.GREATHER_THAN_OR_EQUAL
517
560
  } ${stringifyArgs(args)})`
518
561
  )
@@ -523,9 +566,9 @@ export const keywords = {
523
566
  throw new RangeError(
524
567
  `Invalid number of arguments for (${
525
568
  KEYWORDS.LESS_THAN_OR_EQUAL
526
- }) (= 2 required) (${KEYWORDS.LESS_THAN_OR_EQUAL} ${stringifyArgs(
527
- args
528
- )})`
569
+ }) (= 2 required)\n\nat:\n(${
570
+ KEYWORDS.LESS_THAN_OR_EQUAL
571
+ } ${stringifyArgs(args)})`
529
572
  )
530
573
  const a = evaluate(args[0], env)
531
574
  const b = evaluate(args[1], env)
@@ -533,7 +576,7 @@ export const keywords = {
533
576
  throw new TypeError(
534
577
  `Invalid use of (${
535
578
  KEYWORDS.LESS_THAN_OR_EQUAL
536
- }), first argument is not an ${RUNTIME_TYPES.NUMBER} (${
579
+ }), first argument is not an ${RUNTIME_TYPES.NUMBER}\n\nat:\n(${
537
580
  KEYWORDS.LESS_THAN_OR_EQUAL
538
581
  } ${stringifyArgs(args)})`
539
582
  )
@@ -541,7 +584,7 @@ export const keywords = {
541
584
  throw new TypeError(
542
585
  `Invalid use of (${
543
586
  KEYWORDS.LESS_THAN_OR_EQUAL
544
- }), second argument are not an ${RUNTIME_TYPES.NUMBER} (${
587
+ }), second argument are not an ${RUNTIME_TYPES.NUMBER}\n\nat:\n(${
545
588
  KEYWORDS.LESS_THAN_OR_EQUAL
546
589
  } ${stringifyArgs(args)})`
547
590
  )
@@ -550,14 +593,16 @@ export const keywords = {
550
593
  [KEYWORDS.AND]: (args, env) => {
551
594
  if (args.length !== 2)
552
595
  throw new RangeError(
553
- `Invalid number of arguments for (${KEYWORDS.AND}) (= 2 required) (${
596
+ `Invalid number of arguments for (${
554
597
  KEYWORDS.AND
555
- } ${stringifyArgs(args)})`
598
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.AND} ${stringifyArgs(args)})`
556
599
  )
557
600
  const a = evaluate(args[0], env)
558
601
  if (a !== FALSE && a !== TRUE)
559
602
  throw new TypeError(
560
- `Condition of (${KEYWORDS.AND}) must be ${TRUE} or ${FALSE} but got (${
603
+ `Condition of (${
604
+ KEYWORDS.AND
605
+ }) must be ${TRUE} or ${FALSE} but got\n\nat:\n(${
561
606
  KEYWORDS.AND
562
607
  } ${stringifyArgs(args)})`
563
608
  )
@@ -565,7 +610,9 @@ export const keywords = {
565
610
  const b = evaluate(args[1], env)
566
611
  if (b !== FALSE && b !== TRUE)
567
612
  throw new TypeError(
568
- `Condition of (${KEYWORDS.AND}) must be ${TRUE} or ${FALSE} but got (${
613
+ `Condition of (${
614
+ KEYWORDS.AND
615
+ }) must be ${TRUE} or ${FALSE} but got\n\nat:\n(${
569
616
  KEYWORDS.AND
570
617
  } ${stringifyArgs(args)})`
571
618
  )
@@ -574,14 +621,16 @@ export const keywords = {
574
621
  [KEYWORDS.OR]: (args, env) => {
575
622
  if (args.length !== 2)
576
623
  throw new RangeError(
577
- `Invalid number of arguments for (${KEYWORDS.OR}) (= 2 required) (${
624
+ `Invalid number of arguments for (${
578
625
  KEYWORDS.OR
579
- } ${stringifyArgs(args)})`
626
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.OR} ${stringifyArgs(args)})`
580
627
  )
581
628
  const a = evaluate(args[0], env)
582
629
  if (a !== FALSE && a !== TRUE)
583
630
  throw new TypeError(
584
- `Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got (${
631
+ `Condition of (${
632
+ KEYWORDS.OR
633
+ }) must be ${TRUE} or ${FALSE} but got\n\nat:\n(${
585
634
  KEYWORDS.OR
586
635
  } ${stringifyArgs(args)})`
587
636
  )
@@ -589,7 +638,9 @@ export const keywords = {
589
638
  const b = evaluate(args[1], env)
590
639
  if (b !== FALSE && b !== TRUE)
591
640
  throw new TypeError(
592
- `Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got (${
641
+ `Condition of (${
642
+ KEYWORDS.OR
643
+ }) must be ${TRUE} or ${FALSE} but got\n\nat:\n(${
593
644
  KEYWORDS.OR
594
645
  } ${stringifyArgs(args)})`
595
646
  )
@@ -600,7 +651,9 @@ export const keywords = {
600
651
  throw new RangeError(
601
652
  `Invalid number of arguments to (${
602
653
  KEYWORDS.DEFINE_VARIABLE
603
- }) (= 2 required) (${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(args)})`
654
+ }) (= 2 required)\n\nat:\n(${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(
655
+ args
656
+ )})`
604
657
  )
605
658
  const word = args[0]
606
659
  const type = word[TYPE]
@@ -609,11 +662,11 @@ export const keywords = {
609
662
  throw new SyntaxError(
610
663
  `First argument of (${KEYWORDS.DEFINE_VARIABLE}) must be word but got ${
611
664
  TYPES[type]
612
- } (${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(args)})`
665
+ }\n\nat:\n(${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(args)})`
613
666
  )
614
667
  else if (isForbiddenVariableName(name))
615
668
  throw new ReferenceError(
616
- `Variable name ${name} is forbidden at (${
669
+ `Variable name ${name} is forbidden at\n\nat:\n(${
617
670
  KEYWORDS.DEFINE_VARIABLE
618
671
  } ${stringifyArgs(args)})`
619
672
  )
@@ -626,16 +679,14 @@ export const keywords = {
626
679
  [KEYWORDS.ANONYMOUS_FUNCTION]: (args, env) => {
627
680
  const params = args.slice(0, -1)
628
681
  const body = args.at(-1)
629
- return (props = [], scope) => {
682
+ return (props = [], scope, name) => {
630
683
  if (props.length !== params.length)
631
684
  throw new RangeError(
632
- `Incorrect number of arguments for (${
633
- KEYWORDS.ANONYMOUS_FUNCTION
634
- } ${stringifyArgs(params)}) are provided. (expects ${
635
- params.length
636
- } but got ${props.length}) (${
637
- KEYWORDS.ANONYMOUS_FUNCTION
638
- } ${stringifyArgs(args)})`
685
+ `Incorrect number of arguments for (${KEYWORDS.ANONYMOUS_FUNCTION}${
686
+ name ? ` ${name}` : ''
687
+ }) are provided (expects ${params.length} but got ${
688
+ props.length
689
+ })\n\nat:\n(${KEYWORDS.ANONYMOUS_FUNCTION} ${stringifyArgs(params)})`
639
690
  )
640
691
  const localEnv = Object.create(env)
641
692
  // localEnv[KEYWORDS.BLOCK] = block[KEYWORDS.BLOCK]
@@ -646,6 +697,7 @@ export const keywords = {
646
697
  writable: true
647
698
  })
648
699
  }
700
+ if (name) evaluate.stack.push(name)
649
701
  return evaluate(body, localEnv)
650
702
  }
651
703
  },
@@ -654,15 +706,16 @@ export const keywords = {
654
706
  throw new RangeError(
655
707
  `Invalid number of arguments to (${
656
708
  KEYWORDS.CALL_FUNCTION
657
- }) (>= 1 required) (${KEYWORDS.CALL_FUNCTION} ${stringifyArgs(args)})`
709
+ }) (>= 1 required)\n\nat:\n(${KEYWORDS.CALL_FUNCTION} ${stringifyArgs(
710
+ args
711
+ )})`
658
712
  )
659
- const rest = [...args]
660
- const first = rest.pop()
713
+ const first = args.at(-1)
661
714
  if (first[TYPE] === WORD && first[VALUE] in keywords)
662
715
  throw new TypeError(
663
716
  `Preceeding arguments of (${
664
717
  KEYWORDS.CALL_FUNCTION
665
- }) must not be an reserved word (${
718
+ }) must not be an reserved word\n\nat:\n(${
666
719
  KEYWORDS.CALL_FUNCTION
667
720
  } ${stringifyArgs(args)})`
668
721
  )
@@ -671,17 +724,17 @@ export const keywords = {
671
724
  throw new TypeError(
672
725
  `Last argument of (${KEYWORDS.CALL_FUNCTION}) must be a (${
673
726
  KEYWORDS.ANONYMOUS_FUNCTION
674
- }) (${KEYWORDS.CALL_FUNCTION} ${stringifyArgs(args)})`
727
+ })\n\nat:\n(${KEYWORDS.CALL_FUNCTION} ${stringifyArgs(args)})`
675
728
  )
676
729
 
677
- return apply(rest, env)
730
+ return apply(args.slice(0, -1), env)
678
731
  },
679
732
  [KEYWORDS.BLOCK]: (args, env) => {
680
733
  if (!args.length)
681
734
  throw new RangeError(
682
- `Invalid number of arguments to (${KEYWORDS.BLOCK}) (>= 1 required) (${
735
+ `Invalid number of arguments to (${
683
736
  KEYWORDS.BLOCK
684
- } ${stringifyArgs(args)})`
737
+ }) (>= 1 required)\n\nat:\n(${KEYWORDS.BLOCK} ${stringifyArgs(args)})`
685
738
  )
686
739
  return args.reduce((_, x) => evaluate(x, env), FALSE)
687
740
  },
@@ -690,7 +743,7 @@ export const keywords = {
690
743
  throw new RangeError(
691
744
  `Invalid number of arguments for (${
692
745
  KEYWORDS.IS_ATOM
693
- }) (= 1 required) (${KEYWORDS.IS_ATOM} ${stringifyArgs(args)})`
746
+ }) (= 1 required)\n\nat:\n(${KEYWORDS.IS_ATOM} ${stringifyArgs(args)})`
694
747
  )
695
748
  return +(typeof evaluate(args[0], env) === 'number')
696
749
  },
@@ -699,67 +752,10 @@ export const keywords = {
699
752
  throw new RangeError(
700
753
  `Invalid number of arguments for (${
701
754
  KEYWORDS.IS_LAMBDA
702
- }) (= 1 required) (${KEYWORDS.IS_LAMBDA} ${stringifyArgs(args)})`
703
- )
704
- return +(typeof evaluate(args[0], env) === 'function')
705
- },
706
- [KEYWORDS.LOG]: (args, env) => {
707
- if (args.length !== 1)
708
- throw new RangeError(
709
- `Invalid number of arguments to (${KEYWORDS.LOG}) (= 1 required) (${
710
- KEYWORDS.LOG
711
- } ${stringifyArgs(args)})`
712
- )
713
- const expression = evaluate(args[0], env)
714
- console.log(expression)
715
- return expression
716
- },
717
- [KEYWORDS.LOG_STRING]: (args, env) => {
718
- if (args.length !== 1)
719
- throw new RangeError(
720
- `Invalid number of arguments to (${
721
- KEYWORDS.LOG_STRING
722
- }) (= 1 required) (${KEYWORDS.LOG_STRING} ${stringifyArgs(args)})`
723
- )
724
- const expression = evaluate(args[0], env)
725
- if (!Array.isArray(expression))
726
- throw new TypeError(
727
- `Argument of (${KEYWORDS.LOG_STRING}) must be an (${
728
- RUNTIME_TYPES.ARRAY
729
- }) but got (${expression}) (${KEYWORDS.LOG_STRING} ${stringifyArgs(
755
+ }) (= 1 required)\n\nat:\n(${KEYWORDS.IS_LAMBDA} ${stringifyArgs(
730
756
  args
731
757
  )})`
732
758
  )
733
- console.log(expression.map((x) => String.fromCharCode(x)).join(''))
734
- return expression
735
- },
736
- [KEYWORDS.LOG_CHAR]: (args, env) => {
737
- if (args.length !== 1)
738
- throw new RangeError(
739
- `Invalid number of arguments to (${
740
- KEYWORDS.LOG_CHAR
741
- }) (= 1 required) (${KEYWORDS.LOG_CHAR} ${stringifyArgs(args)})`
742
- )
743
- const expression = evaluate(args[0], env)
744
- if (typeof expression !== 'number')
745
- throw new TypeError(
746
- `Argument of (${KEYWORDS.LOG_CHAR}) must be a (${
747
- RUNTIME_TYPES.NUMBER
748
- }) but got (${expression}) (${KEYWORDS.LOG_CHAR} ${stringifyArgs(
749
- args
750
- )})`
751
- )
752
- console.log(String.fromCharCode(expression))
753
- return expression
754
- },
755
- [KEYWORDS.CLEAR_CONSOLE]: (args) => {
756
- if (args.length)
757
- throw new RangeError(
758
- `Invalid number of arguments to (${
759
- KEYWORDS.CLEAR_CONSOLE
760
- }) (= 0 required) (${KEYWORDS.CLEAR_CONSOLE} ${stringifyArgs(args)})`
761
- )
762
- console.clear()
763
- return 0
759
+ return +(typeof evaluate(args[0], env) === 'function')
764
760
  }
765
761
  }