fez-lisp 1.0.7 → 1.0.9

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/src/tokeniser.js CHANGED
@@ -17,14 +17,14 @@ const keywords = {
17
17
  keywords.CONCATENATION
18
18
  }), expected > 1 but got ${args.length}. (${
19
19
  keywords.CONCATENATION
20
- } ${stringifyArgs(args)}).`
20
+ } ${stringifyArgs(args)})`
21
21
  )
22
22
  const operands = args.map((x) => evaluate(x, env))
23
23
  if (operands.some((x) => typeof x !== 'string'))
24
24
  throw new TypeError(
25
25
  `Not all arguments of (${KEYWORDS.CONCATENATION}) are (${
26
26
  KEYWORDS.STRING_TYPE
27
- }) (${KEYWORDS.CONCATENATION} ${stringifyArgs(args)}).`
27
+ }) (${KEYWORDS.CONCATENATION} ${stringifyArgs(args)})`
28
28
  )
29
29
  return operands.reduce((a, b) => a + b, '')
30
30
  },
@@ -35,14 +35,14 @@ const keywords = {
35
35
  KEYWORDS.REMAINDER_OF_DIVISION
36
36
  }), expected > 1 but got ${args.length}. (${
37
37
  KEYWORDS.REMAINDER_OF_DIVISION
38
- } ${stringifyArgs(args)}).`
38
+ } ${stringifyArgs(args)})`
39
39
  )
40
40
  const [a, b] = args.map((x) => evaluate(x, env))
41
41
  if (typeof a !== 'number' || typeof b !== 'number')
42
42
  throw new TypeError(
43
43
  `Not all arguments of (${KEYWORDS.REMAINDER_OF_DIVISION}) are (${
44
44
  KEYWORDS.NUMBER_TYPE
45
- }) (${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)}).`
45
+ }) (${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)})`
46
46
  )
47
47
  if (b === 0)
48
48
  throw new TypeError(
@@ -50,7 +50,7 @@ const keywords = {
50
50
  KEYWORDS.REMAINDER_OF_DIVISION
51
51
  }) can't be a (0) (division by 0 is not allowed) (${
52
52
  KEYWORDS.REMAINDER_OF_DIVISION
53
- } ${stringifyArgs(args)}).`
53
+ } ${stringifyArgs(args)})`
54
54
  )
55
55
 
56
56
  return a % b
@@ -63,7 +63,7 @@ const keywords = {
63
63
  throw new TypeError(
64
64
  `Arguments of (${KEYWORDS.DIVISION}) is not a (${
65
65
  KEYWORDS.NUMBER_TYPE
66
- }) (${KEYWORDS.DIVISION} ${stringifyArgs(args)}).`
66
+ }) (${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
67
67
  )
68
68
  if (number === 0)
69
69
  throw new TypeError(
@@ -71,7 +71,7 @@ const keywords = {
71
71
  KEYWORDS.DIVISION
72
72
  }) can't be a (0) (division by 0 is not allowed) (${
73
73
  KEYWORDS.DIVISION
74
- } ${stringifyArgs(args)}).`
74
+ } ${stringifyArgs(args)})`
75
75
  )
76
76
  return 1 / number
77
77
  }
@@ -80,7 +80,7 @@ const keywords = {
80
80
  throw new TypeError(
81
81
  `Not all arguments of (${KEYWORDS.DIVISION}) are (${
82
82
  KEYWORDS.NUMBER_TYPE
83
- }) (${KEYWORDS.DIVISION} ${stringifyArgs(args)}).`
83
+ }) (${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
84
84
  )
85
85
  return operands.reduce((a, b) => a / b)
86
86
  },
@@ -91,7 +91,7 @@ const keywords = {
91
91
  KEYWORDS.ARRAY_OR_STRING_LENGTH
92
92
  }) (1 required) (${KEYWORDS.ARRAY_OR_STRING_LENGTH} ${stringifyArgs(
93
93
  args
94
- )}).`
94
+ )})`
95
95
  )
96
96
  const array = evaluate(args[0], env)
97
97
  if (!(Array.isArray(array) || typeof array === 'string'))
@@ -100,7 +100,7 @@ const keywords = {
100
100
  KEYWORDS.ARRAY_OR_STRING_LENGTH
101
101
  }) must be an (or ${KEYWORDS.ARRAY_TYPE} ${KEYWORDS.STRING_TYPE}) (${
102
102
  KEYWORDS.ARRAY_OR_STRING_LENGTH
103
- } ${stringifyArgs(args)}).`
103
+ } ${stringifyArgs(args)})`
104
104
  )
105
105
  return array.length
106
106
  },
@@ -109,7 +109,7 @@ const keywords = {
109
109
  throw new RangeError(
110
110
  `Invalid number of arguments for (${KEYWORDS.IS_ARRAY}) (1 required) (${
111
111
  KEYWORDS.IS_ARRAY
112
- } ${stringifyArgs(args)}).`
112
+ } ${stringifyArgs(args)})`
113
113
  )
114
114
  const array = evaluate(args[0], env)
115
115
  return +Array.isArray(array)
@@ -119,7 +119,7 @@ const keywords = {
119
119
  throw new RangeError(
120
120
  `Invalid number of arguments for (${
121
121
  KEYWORDS.IS_NUMBER
122
- }) (1 required) (${KEYWORDS.IS_NUMBER} ${stringifyArgs(args)}).`
122
+ }) (1 required) (${KEYWORDS.IS_NUMBER} ${stringifyArgs(args)})`
123
123
  )
124
124
  return +(typeof evaluate(args[0], env) === 'number')
125
125
  },
@@ -128,7 +128,7 @@ const keywords = {
128
128
  throw new RangeError(
129
129
  `Invalid number of arguments for (${
130
130
  KEYWORDS.IS_STRING
131
- }) (1 required) (${KEYWORDS.IS_STRING} ${stringifyArgs(args)}).`
131
+ }) (1 required) (${KEYWORDS.IS_STRING} ${stringifyArgs(args)})`
132
132
  )
133
133
  return +(typeof evaluate(args[0], env) === 'string')
134
134
  },
@@ -137,30 +137,31 @@ const keywords = {
137
137
  throw new RangeError(
138
138
  `Invalid number of arguments for (${
139
139
  KEYWORDS.IS_FUNCTION
140
- }) (1 required) (${KEYWORDS.IS_FUNCTION} ${stringifyArgs(args)}).`
140
+ }) (1 required) (${KEYWORDS.IS_FUNCTION} ${stringifyArgs(args)})`
141
141
  )
142
142
  return +(typeof evaluate(args[0], env) === 'function')
143
143
  },
144
144
  [KEYWORDS.ADDITION]: (args, env) => {
145
+ if (!args.length) return 0 // identity
145
146
  if (args.length < 2)
146
147
  throw new RangeError(
147
148
  `Invalid number of arguments for (${
148
149
  KEYWORDS.ADDITION
149
- }), expected > 1 but got ${args.length}. (${
150
+ }), expected (or (> 1) (= 0)) but got ${args.length}. (${
150
151
  KEYWORDS.ADDITION
151
- } ${stringifyArgs(args)}).`
152
+ } ${stringifyArgs(args)})`
152
153
  )
153
154
  const operands = args.map((x) => evaluate(x, env))
154
155
  if (operands.some((x) => typeof x !== 'number'))
155
156
  throw new TypeError(
156
157
  `Not all arguments of (${KEYWORDS.ADDITION}) are (${
157
158
  KEYWORDS.NUMBER_TYPE
158
- }) (${KEYWORDS.ADDITION} ${stringifyArgs(args)}).`
159
+ }) (${KEYWORDS.ADDITION} ${stringifyArgs(args)})`
159
160
  )
160
161
  return operands.reduce((a, b) => a + b)
161
162
  },
162
163
  [KEYWORDS.MULTIPLICATION]: (args, env) => {
163
- if (!args.length) return 1
164
+ if (!args.length) return 1 // identity
164
165
  if (args.length < 2)
165
166
  throw new RangeError(
166
167
  `Invalid number of arguments for (${KEYWORDS.MULTIPLICATION}), expected (or (> 1) (= 0)) but got ${args.length}.`
@@ -170,7 +171,7 @@ const keywords = {
170
171
  throw new TypeError(
171
172
  `Not all arguments of (${KEYWORDS.MULTIPLICATION}) are (${
172
173
  KEYWORDS.NUMBER_TYPE
173
- }) (${KEYWORDS.MULTIPLICATION} ${stringifyArgs(args)}).`
174
+ }) (${KEYWORDS.MULTIPLICATION} ${stringifyArgs(args)})`
174
175
  )
175
176
  return operands.reduce((a, b) => a * b)
176
177
  },
@@ -181,14 +182,14 @@ const keywords = {
181
182
  KEYWORDS.SUBTRACTION
182
183
  }), expected >= 1 but got ${args.length}. (${
183
184
  KEYWORDS.SUBTRACTION
184
- } ${stringifyArgs(args)}).`
185
+ } ${stringifyArgs(args)})`
185
186
  )
186
187
  const operands = args.map((x) => evaluate(x, env))
187
188
  if (operands.some((x) => typeof x !== 'number'))
188
189
  throw new TypeError(
189
190
  `Not all arguments of (${KEYWORDS.SUBTRACTION}) are (${
190
191
  KEYWORDS.NUMBER_TYPE
191
- }) (${KEYWORDS.SUBTRACTION} ${stringifyArgs(args)}).`
192
+ }) (${KEYWORDS.SUBTRACTION} ${stringifyArgs(args)})`
192
193
  )
193
194
  return args.length === 1 ? -operands[0] : operands.reduce((a, b) => a - b)
194
195
  },
@@ -199,7 +200,7 @@ const keywords = {
199
200
  KEYWORDS.IF
200
201
  }), expected (= 3) but got ${args.length} (${
201
202
  KEYWORDS.IF
202
- } ${stringifyArgs(args)}).`
203
+ } ${stringifyArgs(args)})`
203
204
  )
204
205
  return evaluate(args[0], env)
205
206
  ? evaluate(args[1], env)
@@ -212,7 +213,7 @@ const keywords = {
212
213
  KEYWORDS.UNLESS
213
214
  }), expected (= 3) but got ${args.length} (${
214
215
  KEYWORDS.UNLESS
215
- } ${stringifyArgs(args)}).`
216
+ } ${stringifyArgs(args)})`
216
217
  )
217
218
  return evaluate(args[0], env)
218
219
  ? evaluate(args[2], env)
@@ -225,7 +226,7 @@ const keywords = {
225
226
  KEYWORDS.WHEN
226
227
  }), expected 2 but got ${args.length} (${KEYWORDS.WHEN} ${stringifyArgs(
227
228
  args
228
- )}).`
229
+ )})`
229
230
  )
230
231
  return evaluate(args[0], env) ? evaluate(args[1], env) : 0
231
232
  },
@@ -236,7 +237,7 @@ const keywords = {
236
237
  KEYWORDS.OTHERWISE
237
238
  }), expected 2 but got ${args.length} (${
238
239
  KEYWORDS.OTHERWISE
239
- } ${stringifyArgs(args)}).`
240
+ } ${stringifyArgs(args)})`
240
241
  )
241
242
  return evaluate(args[0], env) ? 0 : evaluate(args[1], env)
242
243
  },
@@ -247,7 +248,7 @@ const keywords = {
247
248
  KEYWORDS.CONDITION
248
249
  }), expected (> 2 required) but got ${args.length} (${
249
250
  KEYWORDS.CONDITION
250
- } ${stringifyArgs(args)}).`
251
+ } ${stringifyArgs(args)})`
251
252
  )
252
253
  for (let i = 0; i < args.length; i += 2) {
253
254
  if (evaluate(args[i], env)) return evaluate(args[i + 1], env)
@@ -274,14 +275,14 @@ const keywords = {
274
275
  )
275
276
  return new Array(N).fill(0)
276
277
  }
277
- return Object.freeze(args.map((x) => evaluate(x, env)))
278
+ return args.map((x) => evaluate(x, env))
278
279
  },
279
280
  [KEYWORDS.IS_ATOM]: (args, env) => {
280
281
  if (args.length !== 1)
281
282
  throw new RangeError(
282
283
  `Invalid number of arguments for (${KEYWORDS.IS_ATOM}) (1 required) (${
283
284
  KEYWORDS.IS_ATOM
284
- } ${stringifyArgs(args)}).`
285
+ } ${stringifyArgs(args)})`
285
286
  )
286
287
  return isAtom(args[0], env)
287
288
  },
@@ -290,27 +291,27 @@ const keywords = {
290
291
  throw new RangeError(
291
292
  `Invalid number of arguments for (${
292
293
  KEYWORDS.FIRST_ARRAY
293
- }) (1 required) (${KEYWORDS.FIRST_ARRAY} ${stringifyArgs(args)}).`
294
+ }) (1 required) (${KEYWORDS.FIRST_ARRAY} ${stringifyArgs(args)})`
294
295
  )
295
296
  const array = evaluate(args[0], env)
296
297
  if (!Array.isArray(array))
297
298
  throw new TypeError(
298
299
  `Argument of (${KEYWORDS.FIRST_ARRAY}) must be an (${
299
300
  KEYWORDS.ARRAY_TYPE
300
- }) (${KEYWORDS.FIRST_ARRAY} ${stringifyArgs(args)}).`
301
+ }) (${KEYWORDS.FIRST_ARRAY} ${stringifyArgs(args)})`
301
302
  )
302
303
  if (array.length === 0)
303
304
  throw new RangeError(
304
305
  `Argument of (${KEYWORDS.FIRST_ARRAY}) is an empty (${
305
306
  KEYWORDS.ARRAY_TYPE
306
- }) (${KEYWORDS.FIRST_ARRAY} ${stringifyArgs(args)}).`
307
+ }) (${KEYWORDS.FIRST_ARRAY} ${stringifyArgs(args)})`
307
308
  )
308
309
  const value = array.at(0)
309
310
  if (value == undefined)
310
311
  throw new RangeError(
311
312
  `Trying to get a null value in (${KEYWORDS.ARRAY_TYPE}) at (${
312
313
  KEYWORDS.FIRST_ARRAY
313
- }) (${KEYWORDS.FIRST_ARRAY} ${stringifyArgs(args)}).`
314
+ }) (${KEYWORDS.FIRST_ARRAY} ${stringifyArgs(args)})`
314
315
  )
315
316
  return value
316
317
  },
@@ -326,13 +327,13 @@ const keywords = {
326
327
  throw new TypeError(
327
328
  `Argument of (${KEYWORDS.REST_ARRAY}) must be an (${
328
329
  KEYWORDS.ARRAY_TYPE
329
- }) (${KEYWORDS.REST_ARRAY} ${stringifyArgs(args)}).`
330
+ }) (${KEYWORDS.REST_ARRAY} ${stringifyArgs(args)})`
330
331
  )
331
332
  if (array.length === 0)
332
333
  throw new RangeError(
333
334
  `Argument of (${KEYWORDS.REST_ARRAY}) is an empty (${
334
335
  KEYWORDS.ARRAY_TYPE
335
- }) (${KEYWORDS.REST_ARRAY} ${stringifyArgs(args)}).`
336
+ }) (${KEYWORDS.REST_ARRAY} ${stringifyArgs(args)})`
336
337
  )
337
338
  return array.slice(1)
338
339
  },
@@ -348,33 +349,33 @@ const keywords = {
348
349
  throw new TypeError(
349
350
  `First argument of (${KEYWORDS.GET_ARRAY}) must be an (${
350
351
  KEYWORDS.ARRAY_TYPE
351
- })) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)}).`
352
+ })) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
352
353
  )
353
354
  if (array.length === 0)
354
355
  throw new RangeError(
355
356
  `First argument of (${KEYWORDS.GET_ARRAY}) is an empty (${
356
357
  KEYWORDS.ARRAY_TYPE
357
- })) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})).`
358
+ })) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)}))`
358
359
  )
359
360
  const index = evaluate(args[1], env)
360
361
  if (!Number.isInteger(index))
361
362
  throw new TypeError(
362
363
  `Second argument of (${KEYWORDS.GET_ARRAY}) must be an (32 bit ${
363
364
  KEYWORDS.NUMBER_TYPE
364
- }) (${index}) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)}).`
365
+ }) (${index}) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
365
366
  )
366
367
  if (index > array.length - 1 || index * -1 > array.length)
367
368
  throw new RangeError(
368
369
  `Second argument of (${KEYWORDS.GET_ARRAY}) is outside of (${
369
370
  KEYWORDS.ARRAY_TYPE
370
- }) bounds (${index}) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)}).`
371
+ }) bounds (${index}) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
371
372
  )
372
373
  const value = array.at(index)
373
374
  if (value == undefined)
374
375
  throw new RangeError(
375
376
  `Trying to get a null value in (${KEYWORDS.ARRAY_TYPE}) at (${
376
377
  KEYWORDS.GET_ARRAY
377
- }) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)}).`
378
+ }) (${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
378
379
  )
379
380
  return value
380
381
  },
@@ -389,20 +390,6 @@ const keywords = {
389
390
  console.log(...expressions)
390
391
  return expressions.at(-1)
391
392
  },
392
- [KEYWORDS.READ]: (args, env) => {
393
- if (args.length)
394
- throw new RangeError(
395
- `Invalid number of arguments to (${KEYWORDS.READ}) (= 0 required) (${
396
- KEYWORDS.READ
397
- } ${stringifyArgs(args)})`
398
- )
399
- const inp = env[KEYWORDS.INPUT]
400
- if (inp.length) return inp
401
- else
402
- throw new ReferenceError(
403
- `${KEYWORDS.INPUT} is empty! at (${KEYWORDS.READ})`
404
- )
405
- },
406
393
  [KEYWORDS.BLOCK]: (args, env) => {
407
394
  if (!args.length)
408
395
  throw new RangeError(
@@ -454,15 +441,16 @@ const keywords = {
454
441
  )
455
442
  const a = evaluate(args[0], env)
456
443
  const b = evaluate(args[1], env)
457
- if (
458
- Array.isArray(a) ||
459
- Array.isArray(b) ||
460
- typeof a === 'function' ||
461
- typeof b === 'function'
462
- )
444
+ if (typeof a !== 'number')
463
445
  throw new TypeError(
464
- `Invalid use of (${KEYWORDS.EQUAL}), some arguments are not an ${
465
- KEYWORDS.ATOM
446
+ `Invalid use of (${KEYWORDS.EQUAL}), first arguments are not an ${
447
+ KEYWORDS.NUMBER_TYPE
448
+ } (${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
449
+ )
450
+ if (typeof b !== 'number')
451
+ throw new TypeError(
452
+ `Invalid use of (${KEYWORDS.EQUAL}), second argument are not an ${
453
+ KEYWORDS.NUMBER_TYPE
466
454
  } (${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
467
455
  )
468
456
  return +(a === b)
@@ -476,15 +464,16 @@ const keywords = {
476
464
  )
477
465
  const a = evaluate(args[0], env)
478
466
  const b = evaluate(args[1], env)
479
- if (
480
- Array.isArray(a) ||
481
- Array.isArray(b) ||
482
- typeof a === 'function' ||
483
- typeof b === 'function'
484
- )
467
+ if (typeof a !== 'number')
468
+ throw new TypeError(
469
+ `Invalid use of (${KEYWORDS.LESS_THAN}), first arguments are not an ${
470
+ KEYWORDS.NUMBER_TYPE
471
+ } (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
472
+ )
473
+ if (typeof b !== 'number')
485
474
  throw new TypeError(
486
- `Invalid use of (${KEYWORDS.LESS_THAN}), some arguments are not an ${
487
- KEYWORDS.ATOM
475
+ `Invalid use of (${KEYWORDS.LESS_THAN}), second argument are not an ${
476
+ KEYWORDS.NUMBER_TYPE
488
477
  } (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
489
478
  )
490
479
  return +(a < b)
@@ -498,16 +487,19 @@ const keywords = {
498
487
  )
499
488
  const a = evaluate(args[0], env)
500
489
  const b = evaluate(args[1], env)
501
- if (
502
- Array.isArray(a) ||
503
- Array.isArray(b) ||
504
- typeof a === 'function' ||
505
- typeof b === 'function'
506
- )
490
+ if (typeof a !== 'number')
507
491
  throw new TypeError(
508
492
  `Invalid use of (${
509
493
  KEYWORDS.GREATHER_THAN
510
- }), some arguments are not an ${KEYWORDS.ATOM} (${
494
+ }), first arguments are not an ${KEYWORDS.NUMBER_TYPE} (${
495
+ KEYWORDS.GREATHER_THAN
496
+ } ${stringifyArgs(args)})`
497
+ )
498
+ if (typeof b !== 'number')
499
+ throw new TypeError(
500
+ `Invalid use of (${
501
+ KEYWORDS.GREATHER_THAN
502
+ }), second argument are not an ${KEYWORDS.NUMBER_TYPE} (${
511
503
  KEYWORDS.GREATHER_THAN
512
504
  } ${stringifyArgs(args)})`
513
505
  )
@@ -524,16 +516,19 @@ const keywords = {
524
516
  )
525
517
  const a = evaluate(args[0], env)
526
518
  const b = evaluate(args[1], env)
527
- if (
528
- Array.isArray(a) ||
529
- Array.isArray(b) ||
530
- typeof a === 'function' ||
531
- typeof b === 'function'
532
- )
519
+ if (typeof a !== 'number')
520
+ throw new TypeError(
521
+ `Invalid use of (${
522
+ KEYWORDS.GREATHER_THAN_OR_EQUAL
523
+ }), first arguments are not an ${KEYWORDS.NUMBER_TYPE} (${
524
+ KEYWORDS.GREATHER_THAN_OR_EQUAL
525
+ } ${stringifyArgs(args)})`
526
+ )
527
+ if (typeof b !== 'number')
533
528
  throw new TypeError(
534
529
  `Invalid use of (${
535
530
  KEYWORDS.GREATHER_THAN_OR_EQUAL
536
- }), some arguments are not an ${KEYWORDS.ATOM} (${
531
+ }), second argument are not an ${KEYWORDS.NUMBER_TYPE} (${
537
532
  KEYWORDS.GREATHER_THAN_OR_EQUAL
538
533
  } ${stringifyArgs(args)})`
539
534
  )
@@ -548,16 +543,19 @@ const keywords = {
548
543
  )
549
544
  const a = evaluate(args[0], env)
550
545
  const b = evaluate(args[1], env)
551
- if (
552
- Array.isArray(a) ||
553
- Array.isArray(b) ||
554
- typeof a === 'function' ||
555
- typeof b === 'function'
556
- )
546
+ if (typeof a !== 'number')
557
547
  throw new TypeError(
558
548
  `Invalid use of (${
559
549
  KEYWORDS.LESS_THAN_OR_EQUAL
560
- }), some arguments are not an ${KEYWORDS.ATOM} (${
550
+ }), first arguments are not an ${KEYWORDS.NUMBER_TYPE} (${
551
+ KEYWORDS.LESS_THAN_OR_EQUAL
552
+ } ${stringifyArgs(args)})`
553
+ )
554
+ if (typeof b !== 'number')
555
+ throw new TypeError(
556
+ `Invalid use of (${
557
+ KEYWORDS.LESS_THAN_OR_EQUAL
558
+ }), second argument are not an ${KEYWORDS.NUMBER_TYPE} (${
561
559
  KEYWORDS.LESS_THAN_OR_EQUAL
562
560
  } ${stringifyArgs(args)})`
563
561
  )
@@ -671,7 +669,7 @@ const keywords = {
671
669
  KEYWORDS.NUMBER_TYPE
672
670
  } ("${value}") to a ${KEYWORDS.NUMBER_TYPE} at (${
673
671
  KEYWORDS.CAST_TYPE
674
- }) (${KEYWORDS.CAST_TYPE} ${stringifyArgs(args)}).`
672
+ }) (${KEYWORDS.CAST_TYPE} ${stringifyArgs(args)})`
675
673
  )
676
674
  return num
677
675
  }
@@ -681,14 +679,14 @@ const keywords = {
681
679
  return +!!value
682
680
  case KEYWORDS.ARRAY_TYPE: {
683
681
  if (typeof value === 'number')
684
- return Object.freeze([...Number(value).toString()].map(Number))
682
+ return [...Number(value).toString()].map(Number)
685
683
  else if (typeof value[Symbol.iterator] !== 'function')
686
684
  throw new TypeError(
687
685
  `Arguments are not iterable for ${KEYWORDS.ARRAY_TYPE} at (${
688
686
  KEYWORDS.CAST_TYPE
689
- }) (${KEYWORDS.CAST_TYPE} ${stringifyArgs(args)}).`
687
+ }) (${KEYWORDS.CAST_TYPE} ${stringifyArgs(args)})`
690
688
  )
691
- return Object.freeze([...value])
689
+ return [...value]
692
690
  }
693
691
  case KEYWORDS.CHAR_TYPE: {
694
692
  const index = evaluate(args[0], env)
@@ -698,7 +696,7 @@ const keywords = {
698
696
  KEYWORDS.CHAR_TYPE
699
697
  } at (${KEYWORDS.CAST_TYPE}) (${
700
698
  KEYWORDS.CAST_TYPE
701
- } ${stringifyArgs(args)}).`
699
+ } ${stringifyArgs(args)})`
702
700
  )
703
701
  return String.fromCharCode(index)
704
702
  }
@@ -710,7 +708,7 @@ const keywords = {
710
708
  KEYWORDS.CHAR_CODE_TYPE
711
709
  } at (${KEYWORDS.CAST_TYPE}) (${
712
710
  KEYWORDS.CAST_TYPE
713
- } ${stringifyArgs(args)}).`
711
+ } ${stringifyArgs(args)})`
714
712
  )
715
713
  if (string.length !== 1)
716
714
  throw new RangeError(
@@ -718,7 +716,7 @@ const keywords = {
718
716
  KEYWORDS.CHAR_CODE_TYPE
719
717
  } at (${KEYWORDS.CAST_TYPE}) (${
720
718
  KEYWORDS.CAST_TYPE
721
- } ${stringifyArgs(args)}).`
719
+ } ${stringifyArgs(args)})`
722
720
  )
723
721
  return string.charCodeAt(0)
724
722
  }
@@ -730,7 +728,7 @@ const keywords = {
730
728
  KEYWORDS.CHAR_TYPE
731
729
  } ${KEYWORDS.CHAR_CODE_TYPE}) at (${KEYWORDS.CAST_TYPE}) (${
732
730
  KEYWORDS.CAST_TYPE
733
- } ${stringifyArgs(args)}).`
731
+ } ${stringifyArgs(args)})`
734
732
  )
735
733
  }
736
734
  }
@@ -747,7 +745,7 @@ const keywords = {
747
745
  throw new TypeError(
748
746
  `Not all arguments of (${KEYWORDS.BITWISE_AND}) are ${
749
747
  KEYWORDS.NUMBER_TYPE
750
- } (${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)}).`
748
+ } (${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
751
749
  )
752
750
  return operands.reduce((acc, x) => acc & x)
753
751
  },
@@ -763,7 +761,7 @@ const keywords = {
763
761
  throw new TypeError(
764
762
  `Argument of (${KEYWORDS.BITWISE_NOT}) is not a (${
765
763
  KEYWORDS.NUMBER_TYPE
766
- }) (${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)}).`
764
+ }) (${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)})`
767
765
  )
768
766
  return ~operand
769
767
  },
@@ -779,7 +777,7 @@ const keywords = {
779
777
  throw new TypeError(
780
778
  `Not all arguments of (${KEYWORDS.BITWISE_OR}) are (${
781
779
  KEYWORDS.NUMBER_TYPE
782
- }) (${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)}).`
780
+ }) (${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)})`
783
781
  )
784
782
  return operands.reduce((acc, x) => acc | x)
785
783
  },
@@ -788,14 +786,14 @@ const keywords = {
788
786
  throw new RangeError(
789
787
  `Invalid number of arguments to (${
790
788
  KEYWORDS.BITWISE_XOR
791
- }) (>= 2 required). (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)}).`
789
+ }) (>= 2 required). (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
792
790
  )
793
791
  const operands = args.map((a) => evaluate(a, env))
794
792
  if (operands.some((x) => typeof x !== 'number'))
795
793
  throw new TypeError(
796
794
  `Not all arguments of (${KEYWORDS.BITWISE_XOR}) are (${
797
795
  KEYWORDS.NUMBER_TYPE
798
- }) (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)}).`
796
+ }) (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
799
797
  )
800
798
  return operands.reduce((acc, x) => acc ^ x)
801
799
  },
@@ -806,14 +804,14 @@ const keywords = {
806
804
  KEYWORDS.BITWISE_LEFT_SHIFT
807
805
  }) (>= 2 required). (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(
808
806
  args
809
- )}).`
807
+ )})`
810
808
  )
811
809
  const operands = args.map((a) => evaluate(a, env))
812
810
  if (operands.some((x) => typeof x !== 'number'))
813
811
  throw new TypeError(
814
812
  `Not all arguments of (${KEYWORDS.BITWISE_LEFT_SHIFT}) are (${
815
813
  KEYWORDS.NUMBER_TYPE
816
- }) (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(args)}).`
814
+ }) (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(args)})`
817
815
  )
818
816
  return operands.reduce((acc, x) => acc << x)
819
817
  },
@@ -824,14 +822,14 @@ const keywords = {
824
822
  KEYWORDS.BITWISE_RIGHT_SHIFT
825
823
  }) (>= 2 required). (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(
826
824
  args
827
- )}).`
825
+ )})`
828
826
  )
829
827
  const operands = args.map((a) => evaluate(a, env))
830
828
  if (operands.some((x) => typeof x !== 'number'))
831
829
  throw new TypeError(
832
830
  `Not all arguments of (${KEYWORDS.BITWISE_RIGHT_SHIFT}) are (${
833
831
  KEYWORDS.NUMBER_TYPE
834
- }) (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(args)}).`
832
+ }) (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(args)})`
835
833
  )
836
834
  return operands.reduce((acc, x) => acc >> x)
837
835
  },
@@ -842,14 +840,14 @@ const keywords = {
842
840
  KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT
843
841
  }) (>= 2 required). (${
844
842
  KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT
845
- } ${stringifyArgs(args)}).`
843
+ } ${stringifyArgs(args)})`
846
844
  )
847
845
  const operands = args.map((a) => evaluate(a, env))
848
846
  if (operands.some((x) => typeof x !== 'number'))
849
847
  throw new TypeError(
850
848
  `Not all arguments of (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT}) are (${
851
849
  KEYWORDS.NUMBER_TYPE
852
- }) (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT} ${stringifyArgs(args)}).`
850
+ }) (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT} ${stringifyArgs(args)})`
853
851
  )
854
852
  return operands.reduce((acc, x) => acc >>> x)
855
853
  },
@@ -879,14 +877,14 @@ const keywords = {
879
877
  throw new RangeError(
880
878
  `Invalid number of arguments to (${
881
879
  KEYWORDS.THROW_ERROR
882
- }) (1 required). (${KEYWORDS.THROW_ERROR} ${stringifyArgs(args)}).`
880
+ }) (1 required). (${KEYWORDS.THROW_ERROR} ${stringifyArgs(args)})`
883
881
  )
884
882
  const string = evaluate(args[0], env)
885
883
  if (typeof string !== 'string')
886
884
  throw new TypeError(
887
885
  `First argument of (${KEYWORDS.THROW_ERROR}) must be an (${
888
886
  KEYWORDS.STRING_TYPE
889
- }) (${KEYWORDS.THROW_ERROR} ${stringifyArgs(args)}).`
887
+ }) (${KEYWORDS.THROW_ERROR} ${stringifyArgs(args)})`
890
888
  )
891
889
  throw new Error(string)
892
890
  },
@@ -895,16 +893,16 @@ const keywords = {
895
893
  throw new RangeError(
896
894
  `Invalid number of arguments to (${KEYWORDS.MERGE}) (>= 2 required). (${
897
895
  KEYWORDS.MERGE
898
- } ${stringifyArgs(args)}).`
896
+ } ${stringifyArgs(args)})`
899
897
  )
900
898
  const arrays = args.map((arg) => evaluate(arg, env))
901
899
  if (arrays.some((maybe) => !Array.isArray(maybe)))
902
900
  throw new TypeError(
903
901
  `Arguments of (${KEYWORDS.MERGE}) must be (${KEYWORDS.ARRAY_TYPE}) (${
904
902
  KEYWORDS.MERGE
905
- } ${stringifyArgs(args)}).`
903
+ } ${stringifyArgs(args)})`
906
904
  )
907
- return Object.freeze(arrays.reduce((a, b) => a.concat(b), []))
905
+ return arrays.reduce((a, b) => a.concat(b), [])
908
906
  },
909
907
  [KEYWORDS.TAIL_CALLS_OPTIMISED_RECURSIVE_FUNCTION]: (args, env) => {
910
908
  if (!args.length)
@@ -913,7 +911,7 @@ const keywords = {
913
911
  KEYWORDS.TAIL_CALLS_OPTIMISED_RECURSIVE_FUNCTION
914
912
  }) (>= 2 required). (${
915
913
  KEYWORDS.TAIL_CALLS_OPTIMISED_RECURSIVE_FUNCTION
916
- } ${stringifyArgs(args)}).`
914
+ } ${stringifyArgs(args)})`
917
915
  )
918
916
  // TODO: Add validation for TCO recursion
919
917
  return keywords[KEYWORDS.DEFINE_VARIABLE](args, env)
@@ -925,7 +923,7 @@ const keywords = {
925
923
  KEYWORDS.IMMUTABLE_FUNCTION
926
924
  }) (>= 2 required). (${KEYWORDS.IMMUTABLE_FUNCTION} ${stringifyArgs(
927
925
  args
928
- )}).`
926
+ )})`
929
927
  )
930
928
  const [definition, ...functionArgs] = args
931
929
  const token = definition[VALUE]
@@ -1024,14 +1022,14 @@ const keywords = {
1024
1022
  throw new TypeError(
1025
1023
  `First argument of (${KEYWORDS.SET_ARRAY}) must be an (${
1026
1024
  KEYWORDS.ARRAY_TYPE
1027
- }) but got (${array}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)}).`
1025
+ }) but got (${array}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
1028
1026
  )
1029
1027
  const index = evaluate(args[1], env)
1030
1028
  if (!Number.isInteger(index))
1031
1029
  throw new TypeError(
1032
1030
  `Second argument of (${KEYWORDS.SET_ARRAY}) must be an (${
1033
1031
  KEYWORDS.NUMBER_TYPE
1034
- } integer) (${index}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)}).`
1032
+ } integer) (${index}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
1035
1033
  )
1036
1034
  if (index > array.length)
1037
1035
  throw new RangeError(
@@ -1039,7 +1037,7 @@ const keywords = {
1039
1037
  KEYWORDS.ARRAY_TYPE
1040
1038
  }) bounds (index ${index} bounds ${array.length}) (${
1041
1039
  KEYWORDS.SET_ARRAY
1042
- } ${stringifyArgs(args)}).`
1040
+ } ${stringifyArgs(args)})`
1043
1041
  )
1044
1042
  if (index < 0) {
1045
1043
  if (args.length !== 2)
@@ -1080,6 +1078,86 @@ const keywords = {
1080
1078
  }
1081
1079
  return array
1082
1080
  },
1081
+
1082
+ [KEYWORDS.SET_IMMUTABLE_ARRAY]: (args, env) => {
1083
+ if (args.length !== 2 && args.length !== 3)
1084
+ throw new RangeError(
1085
+ `Invalid number of arguments for (${
1086
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1087
+ }) (or 2 3) required (${KEYWORDS.SET_IMMUTABLE_ARRAY} ${stringifyArgs(
1088
+ args
1089
+ )})`
1090
+ )
1091
+ let array = evaluate(args[0], env)
1092
+ if (!Array.isArray(array))
1093
+ throw new TypeError(
1094
+ `First argument of (${KEYWORDS.SET_IMMUTABLE_ARRAY}) must be an (${
1095
+ KEYWORDS.ARRAY_TYPE
1096
+ }) but got (${array}) (${KEYWORDS.SET_IMMUTABLE_ARRAY} ${stringifyArgs(
1097
+ args
1098
+ )})`
1099
+ )
1100
+ array = [...array]
1101
+ const index = evaluate(args[1], env)
1102
+ if (!Number.isInteger(index))
1103
+ throw new TypeError(
1104
+ `Second argument of (${KEYWORDS.SET_IMMUTABLE_ARRAY}) must be an (${
1105
+ KEYWORDS.NUMBER_TYPE
1106
+ } integer) (${index}) (${KEYWORDS.SET_IMMUTABLE_ARRAY} ${stringifyArgs(
1107
+ args
1108
+ )})`
1109
+ )
1110
+ if (index > array.length)
1111
+ throw new RangeError(
1112
+ `Second argument of (${
1113
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1114
+ }) is outside of the (${
1115
+ KEYWORDS.ARRAY_TYPE
1116
+ }) bounds (index ${index} bounds ${array.length}) (${
1117
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1118
+ } ${stringifyArgs(args)})`
1119
+ )
1120
+ if (index < 0) {
1121
+ if (args.length !== 2)
1122
+ throw new RangeError(
1123
+ `Invalid number of arguments for (${
1124
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1125
+ }) (if (< index 0) then 2 required) (${
1126
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1127
+ } ${stringifyArgs(args)})`
1128
+ )
1129
+ if (index * -1 > array.length)
1130
+ throw new RangeError(
1131
+ `Second argument of (${
1132
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1133
+ }) is outside of the (${
1134
+ KEYWORDS.ARRAY_TYPE
1135
+ }) bounds (index ${index} bounds ${array.length}) (${
1136
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1137
+ } ${stringifyArgs(args)})`
1138
+ )
1139
+ const target = array.length + index
1140
+ while (array.length !== target) array.pop()
1141
+ } else {
1142
+ if (args.length !== 3)
1143
+ throw new RangeError(
1144
+ `Invalid number of arguments for (${
1145
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1146
+ }) (if (>= index 0) then 3 required) (${
1147
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1148
+ } ${stringifyArgs(args)})`
1149
+ )
1150
+ const value = evaluate(args[2], env)
1151
+ if (value == undefined)
1152
+ throw new RangeError(
1153
+ `Trying to set a null value in (${KEYWORDS.ARRAY_TYPE}) at (${
1154
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1155
+ }). (${KEYWORDS.SET_IMMUTABLE_ARRAY} ${stringifyArgs(args)})`
1156
+ )
1157
+ array[index] = value
1158
+ }
1159
+ return array
1160
+ },
1083
1161
  }
1084
1162
  keywords[KEYWORDS.NOT_COMPILED_BLOCK] = keywords[KEYWORDS.BLOCK]
1085
1163
  export { keywords }