fez-lisp 1.0.7 → 1.0.8

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(
@@ -445,6 +432,17 @@ const keywords = {
445
432
  )
446
433
  return +!evaluate(args[0], env)
447
434
  },
435
+ [KEYWORDS.EQUALITY]: (args, env) => {
436
+ if (args.length !== 2)
437
+ throw new RangeError(
438
+ `Invalid number of arguments for (${KEYWORDS.EQUAL}) (2 required) (${
439
+ KEYWORDS.EQUAL
440
+ } ${stringifyArgs(args)})`
441
+ )
442
+ const a = evaluate(args[0], env)
443
+ const b = evaluate(args[1], env)
444
+ return +(a === b)
445
+ },
448
446
  [KEYWORDS.EQUAL]: (args, env) => {
449
447
  if (args.length !== 2)
450
448
  throw new RangeError(
@@ -454,15 +452,16 @@ const keywords = {
454
452
  )
455
453
  const a = evaluate(args[0], env)
456
454
  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
- )
455
+ if (typeof a !== 'number')
463
456
  throw new TypeError(
464
- `Invalid use of (${KEYWORDS.EQUAL}), some arguments are not an ${
465
- KEYWORDS.ATOM
457
+ `Invalid use of (${KEYWORDS.EQUAL}), first arguments are not an ${
458
+ KEYWORDS.NUMBER_TYPE
459
+ } (${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
460
+ )
461
+ if (typeof b !== 'number')
462
+ throw new TypeError(
463
+ `Invalid use of (${KEYWORDS.EQUAL}), second argument are not an ${
464
+ KEYWORDS.NUMBER_TYPE
466
465
  } (${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
467
466
  )
468
467
  return +(a === b)
@@ -476,15 +475,16 @@ const keywords = {
476
475
  )
477
476
  const a = evaluate(args[0], env)
478
477
  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
- )
478
+ if (typeof a !== 'number')
479
+ throw new TypeError(
480
+ `Invalid use of (${KEYWORDS.LESS_THAN}), first arguments are not an ${
481
+ KEYWORDS.NUMBER_TYPE
482
+ } (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
483
+ )
484
+ if (typeof b !== 'number')
485
485
  throw new TypeError(
486
- `Invalid use of (${KEYWORDS.LESS_THAN}), some arguments are not an ${
487
- KEYWORDS.ATOM
486
+ `Invalid use of (${KEYWORDS.LESS_THAN}), second argument are not an ${
487
+ KEYWORDS.NUMBER_TYPE
488
488
  } (${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
489
489
  )
490
490
  return +(a < b)
@@ -498,16 +498,19 @@ const keywords = {
498
498
  )
499
499
  const a = evaluate(args[0], env)
500
500
  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
- )
501
+ if (typeof a !== 'number')
502
+ throw new TypeError(
503
+ `Invalid use of (${
504
+ KEYWORDS.GREATHER_THAN
505
+ }), first arguments are not an ${KEYWORDS.NUMBER_TYPE} (${
506
+ KEYWORDS.GREATHER_THAN
507
+ } ${stringifyArgs(args)})`
508
+ )
509
+ if (typeof b !== 'number')
507
510
  throw new TypeError(
508
511
  `Invalid use of (${
509
512
  KEYWORDS.GREATHER_THAN
510
- }), some arguments are not an ${KEYWORDS.ATOM} (${
513
+ }), second argument are not an ${KEYWORDS.NUMBER_TYPE} (${
511
514
  KEYWORDS.GREATHER_THAN
512
515
  } ${stringifyArgs(args)})`
513
516
  )
@@ -524,16 +527,19 @@ const keywords = {
524
527
  )
525
528
  const a = evaluate(args[0], env)
526
529
  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
- )
530
+ if (typeof a !== 'number')
533
531
  throw new TypeError(
534
532
  `Invalid use of (${
535
533
  KEYWORDS.GREATHER_THAN_OR_EQUAL
536
- }), some arguments are not an ${KEYWORDS.ATOM} (${
534
+ }), first arguments are not an ${KEYWORDS.NUMBER_TYPE} (${
535
+ KEYWORDS.GREATHER_THAN_OR_EQUAL
536
+ } ${stringifyArgs(args)})`
537
+ )
538
+ if (typeof b !== 'number')
539
+ throw new TypeError(
540
+ `Invalid use of (${
541
+ KEYWORDS.GREATHER_THAN_OR_EQUAL
542
+ }), second argument are not an ${KEYWORDS.NUMBER_TYPE} (${
537
543
  KEYWORDS.GREATHER_THAN_OR_EQUAL
538
544
  } ${stringifyArgs(args)})`
539
545
  )
@@ -548,16 +554,19 @@ const keywords = {
548
554
  )
549
555
  const a = evaluate(args[0], env)
550
556
  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
- )
557
+ if (typeof a !== 'number')
557
558
  throw new TypeError(
558
559
  `Invalid use of (${
559
560
  KEYWORDS.LESS_THAN_OR_EQUAL
560
- }), some arguments are not an ${KEYWORDS.ATOM} (${
561
+ }), first arguments are not an ${KEYWORDS.NUMBER_TYPE} (${
562
+ KEYWORDS.LESS_THAN_OR_EQUAL
563
+ } ${stringifyArgs(args)})`
564
+ )
565
+ if (typeof b !== 'number')
566
+ throw new TypeError(
567
+ `Invalid use of (${
568
+ KEYWORDS.LESS_THAN_OR_EQUAL
569
+ }), second argument are not an ${KEYWORDS.NUMBER_TYPE} (${
561
570
  KEYWORDS.LESS_THAN_OR_EQUAL
562
571
  } ${stringifyArgs(args)})`
563
572
  )
@@ -671,7 +680,7 @@ const keywords = {
671
680
  KEYWORDS.NUMBER_TYPE
672
681
  } ("${value}") to a ${KEYWORDS.NUMBER_TYPE} at (${
673
682
  KEYWORDS.CAST_TYPE
674
- }) (${KEYWORDS.CAST_TYPE} ${stringifyArgs(args)}).`
683
+ }) (${KEYWORDS.CAST_TYPE} ${stringifyArgs(args)})`
675
684
  )
676
685
  return num
677
686
  }
@@ -681,14 +690,14 @@ const keywords = {
681
690
  return +!!value
682
691
  case KEYWORDS.ARRAY_TYPE: {
683
692
  if (typeof value === 'number')
684
- return Object.freeze([...Number(value).toString()].map(Number))
693
+ return [...Number(value).toString()].map(Number)
685
694
  else if (typeof value[Symbol.iterator] !== 'function')
686
695
  throw new TypeError(
687
696
  `Arguments are not iterable for ${KEYWORDS.ARRAY_TYPE} at (${
688
697
  KEYWORDS.CAST_TYPE
689
- }) (${KEYWORDS.CAST_TYPE} ${stringifyArgs(args)}).`
698
+ }) (${KEYWORDS.CAST_TYPE} ${stringifyArgs(args)})`
690
699
  )
691
- return Object.freeze([...value])
700
+ return [...value]
692
701
  }
693
702
  case KEYWORDS.CHAR_TYPE: {
694
703
  const index = evaluate(args[0], env)
@@ -698,7 +707,7 @@ const keywords = {
698
707
  KEYWORDS.CHAR_TYPE
699
708
  } at (${KEYWORDS.CAST_TYPE}) (${
700
709
  KEYWORDS.CAST_TYPE
701
- } ${stringifyArgs(args)}).`
710
+ } ${stringifyArgs(args)})`
702
711
  )
703
712
  return String.fromCharCode(index)
704
713
  }
@@ -710,7 +719,7 @@ const keywords = {
710
719
  KEYWORDS.CHAR_CODE_TYPE
711
720
  } at (${KEYWORDS.CAST_TYPE}) (${
712
721
  KEYWORDS.CAST_TYPE
713
- } ${stringifyArgs(args)}).`
722
+ } ${stringifyArgs(args)})`
714
723
  )
715
724
  if (string.length !== 1)
716
725
  throw new RangeError(
@@ -718,7 +727,7 @@ const keywords = {
718
727
  KEYWORDS.CHAR_CODE_TYPE
719
728
  } at (${KEYWORDS.CAST_TYPE}) (${
720
729
  KEYWORDS.CAST_TYPE
721
- } ${stringifyArgs(args)}).`
730
+ } ${stringifyArgs(args)})`
722
731
  )
723
732
  return string.charCodeAt(0)
724
733
  }
@@ -730,7 +739,7 @@ const keywords = {
730
739
  KEYWORDS.CHAR_TYPE
731
740
  } ${KEYWORDS.CHAR_CODE_TYPE}) at (${KEYWORDS.CAST_TYPE}) (${
732
741
  KEYWORDS.CAST_TYPE
733
- } ${stringifyArgs(args)}).`
742
+ } ${stringifyArgs(args)})`
734
743
  )
735
744
  }
736
745
  }
@@ -747,7 +756,7 @@ const keywords = {
747
756
  throw new TypeError(
748
757
  `Not all arguments of (${KEYWORDS.BITWISE_AND}) are ${
749
758
  KEYWORDS.NUMBER_TYPE
750
- } (${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)}).`
759
+ } (${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
751
760
  )
752
761
  return operands.reduce((acc, x) => acc & x)
753
762
  },
@@ -763,7 +772,7 @@ const keywords = {
763
772
  throw new TypeError(
764
773
  `Argument of (${KEYWORDS.BITWISE_NOT}) is not a (${
765
774
  KEYWORDS.NUMBER_TYPE
766
- }) (${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)}).`
775
+ }) (${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)})`
767
776
  )
768
777
  return ~operand
769
778
  },
@@ -779,7 +788,7 @@ const keywords = {
779
788
  throw new TypeError(
780
789
  `Not all arguments of (${KEYWORDS.BITWISE_OR}) are (${
781
790
  KEYWORDS.NUMBER_TYPE
782
- }) (${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)}).`
791
+ }) (${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)})`
783
792
  )
784
793
  return operands.reduce((acc, x) => acc | x)
785
794
  },
@@ -788,14 +797,14 @@ const keywords = {
788
797
  throw new RangeError(
789
798
  `Invalid number of arguments to (${
790
799
  KEYWORDS.BITWISE_XOR
791
- }) (>= 2 required). (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)}).`
800
+ }) (>= 2 required). (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
792
801
  )
793
802
  const operands = args.map((a) => evaluate(a, env))
794
803
  if (operands.some((x) => typeof x !== 'number'))
795
804
  throw new TypeError(
796
805
  `Not all arguments of (${KEYWORDS.BITWISE_XOR}) are (${
797
806
  KEYWORDS.NUMBER_TYPE
798
- }) (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)}).`
807
+ }) (${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
799
808
  )
800
809
  return operands.reduce((acc, x) => acc ^ x)
801
810
  },
@@ -806,14 +815,14 @@ const keywords = {
806
815
  KEYWORDS.BITWISE_LEFT_SHIFT
807
816
  }) (>= 2 required). (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(
808
817
  args
809
- )}).`
818
+ )})`
810
819
  )
811
820
  const operands = args.map((a) => evaluate(a, env))
812
821
  if (operands.some((x) => typeof x !== 'number'))
813
822
  throw new TypeError(
814
823
  `Not all arguments of (${KEYWORDS.BITWISE_LEFT_SHIFT}) are (${
815
824
  KEYWORDS.NUMBER_TYPE
816
- }) (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(args)}).`
825
+ }) (${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(args)})`
817
826
  )
818
827
  return operands.reduce((acc, x) => acc << x)
819
828
  },
@@ -824,14 +833,14 @@ const keywords = {
824
833
  KEYWORDS.BITWISE_RIGHT_SHIFT
825
834
  }) (>= 2 required). (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(
826
835
  args
827
- )}).`
836
+ )})`
828
837
  )
829
838
  const operands = args.map((a) => evaluate(a, env))
830
839
  if (operands.some((x) => typeof x !== 'number'))
831
840
  throw new TypeError(
832
841
  `Not all arguments of (${KEYWORDS.BITWISE_RIGHT_SHIFT}) are (${
833
842
  KEYWORDS.NUMBER_TYPE
834
- }) (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(args)}).`
843
+ }) (${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(args)})`
835
844
  )
836
845
  return operands.reduce((acc, x) => acc >> x)
837
846
  },
@@ -842,14 +851,14 @@ const keywords = {
842
851
  KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT
843
852
  }) (>= 2 required). (${
844
853
  KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT
845
- } ${stringifyArgs(args)}).`
854
+ } ${stringifyArgs(args)})`
846
855
  )
847
856
  const operands = args.map((a) => evaluate(a, env))
848
857
  if (operands.some((x) => typeof x !== 'number'))
849
858
  throw new TypeError(
850
859
  `Not all arguments of (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT}) are (${
851
860
  KEYWORDS.NUMBER_TYPE
852
- }) (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT} ${stringifyArgs(args)}).`
861
+ }) (${KEYWORDS.BITWISE_UNSIGNED_RIGHT_SHIFT} ${stringifyArgs(args)})`
853
862
  )
854
863
  return operands.reduce((acc, x) => acc >>> x)
855
864
  },
@@ -879,14 +888,14 @@ const keywords = {
879
888
  throw new RangeError(
880
889
  `Invalid number of arguments to (${
881
890
  KEYWORDS.THROW_ERROR
882
- }) (1 required). (${KEYWORDS.THROW_ERROR} ${stringifyArgs(args)}).`
891
+ }) (1 required). (${KEYWORDS.THROW_ERROR} ${stringifyArgs(args)})`
883
892
  )
884
893
  const string = evaluate(args[0], env)
885
894
  if (typeof string !== 'string')
886
895
  throw new TypeError(
887
896
  `First argument of (${KEYWORDS.THROW_ERROR}) must be an (${
888
897
  KEYWORDS.STRING_TYPE
889
- }) (${KEYWORDS.THROW_ERROR} ${stringifyArgs(args)}).`
898
+ }) (${KEYWORDS.THROW_ERROR} ${stringifyArgs(args)})`
890
899
  )
891
900
  throw new Error(string)
892
901
  },
@@ -895,16 +904,16 @@ const keywords = {
895
904
  throw new RangeError(
896
905
  `Invalid number of arguments to (${KEYWORDS.MERGE}) (>= 2 required). (${
897
906
  KEYWORDS.MERGE
898
- } ${stringifyArgs(args)}).`
907
+ } ${stringifyArgs(args)})`
899
908
  )
900
909
  const arrays = args.map((arg) => evaluate(arg, env))
901
910
  if (arrays.some((maybe) => !Array.isArray(maybe)))
902
911
  throw new TypeError(
903
912
  `Arguments of (${KEYWORDS.MERGE}) must be (${KEYWORDS.ARRAY_TYPE}) (${
904
913
  KEYWORDS.MERGE
905
- } ${stringifyArgs(args)}).`
914
+ } ${stringifyArgs(args)})`
906
915
  )
907
- return Object.freeze(arrays.reduce((a, b) => a.concat(b), []))
916
+ return arrays.reduce((a, b) => a.concat(b), [])
908
917
  },
909
918
  [KEYWORDS.TAIL_CALLS_OPTIMISED_RECURSIVE_FUNCTION]: (args, env) => {
910
919
  if (!args.length)
@@ -913,7 +922,7 @@ const keywords = {
913
922
  KEYWORDS.TAIL_CALLS_OPTIMISED_RECURSIVE_FUNCTION
914
923
  }) (>= 2 required). (${
915
924
  KEYWORDS.TAIL_CALLS_OPTIMISED_RECURSIVE_FUNCTION
916
- } ${stringifyArgs(args)}).`
925
+ } ${stringifyArgs(args)})`
917
926
  )
918
927
  // TODO: Add validation for TCO recursion
919
928
  return keywords[KEYWORDS.DEFINE_VARIABLE](args, env)
@@ -925,7 +934,7 @@ const keywords = {
925
934
  KEYWORDS.IMMUTABLE_FUNCTION
926
935
  }) (>= 2 required). (${KEYWORDS.IMMUTABLE_FUNCTION} ${stringifyArgs(
927
936
  args
928
- )}).`
937
+ )})`
929
938
  )
930
939
  const [definition, ...functionArgs] = args
931
940
  const token = definition[VALUE]
@@ -1024,14 +1033,14 @@ const keywords = {
1024
1033
  throw new TypeError(
1025
1034
  `First argument of (${KEYWORDS.SET_ARRAY}) must be an (${
1026
1035
  KEYWORDS.ARRAY_TYPE
1027
- }) but got (${array}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)}).`
1036
+ }) but got (${array}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
1028
1037
  )
1029
1038
  const index = evaluate(args[1], env)
1030
1039
  if (!Number.isInteger(index))
1031
1040
  throw new TypeError(
1032
1041
  `Second argument of (${KEYWORDS.SET_ARRAY}) must be an (${
1033
1042
  KEYWORDS.NUMBER_TYPE
1034
- } integer) (${index}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)}).`
1043
+ } integer) (${index}) (${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
1035
1044
  )
1036
1045
  if (index > array.length)
1037
1046
  throw new RangeError(
@@ -1039,7 +1048,7 @@ const keywords = {
1039
1048
  KEYWORDS.ARRAY_TYPE
1040
1049
  }) bounds (index ${index} bounds ${array.length}) (${
1041
1050
  KEYWORDS.SET_ARRAY
1042
- } ${stringifyArgs(args)}).`
1051
+ } ${stringifyArgs(args)})`
1043
1052
  )
1044
1053
  if (index < 0) {
1045
1054
  if (args.length !== 2)
@@ -1080,6 +1089,86 @@ const keywords = {
1080
1089
  }
1081
1090
  return array
1082
1091
  },
1092
+
1093
+ [KEYWORDS.SET_IMMUTABLE_ARRAY]: (args, env) => {
1094
+ if (args.length !== 2 && args.length !== 3)
1095
+ throw new RangeError(
1096
+ `Invalid number of arguments for (${
1097
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1098
+ }) (or 2 3) required (${KEYWORDS.SET_IMMUTABLE_ARRAY} ${stringifyArgs(
1099
+ args
1100
+ )})`
1101
+ )
1102
+ let array = evaluate(args[0], env)
1103
+ if (!Array.isArray(array))
1104
+ throw new TypeError(
1105
+ `First argument of (${KEYWORDS.SET_IMMUTABLE_ARRAY}) must be an (${
1106
+ KEYWORDS.ARRAY_TYPE
1107
+ }) but got (${array}) (${KEYWORDS.SET_IMMUTABLE_ARRAY} ${stringifyArgs(
1108
+ args
1109
+ )})`
1110
+ )
1111
+ array = [...array]
1112
+ const index = evaluate(args[1], env)
1113
+ if (!Number.isInteger(index))
1114
+ throw new TypeError(
1115
+ `Second argument of (${KEYWORDS.SET_IMMUTABLE_ARRAY}) must be an (${
1116
+ KEYWORDS.NUMBER_TYPE
1117
+ } integer) (${index}) (${KEYWORDS.SET_IMMUTABLE_ARRAY} ${stringifyArgs(
1118
+ args
1119
+ )})`
1120
+ )
1121
+ if (index > array.length)
1122
+ throw new RangeError(
1123
+ `Second argument of (${
1124
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1125
+ }) is outside of the (${
1126
+ KEYWORDS.ARRAY_TYPE
1127
+ }) bounds (index ${index} bounds ${array.length}) (${
1128
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1129
+ } ${stringifyArgs(args)})`
1130
+ )
1131
+ if (index < 0) {
1132
+ if (args.length !== 2)
1133
+ throw new RangeError(
1134
+ `Invalid number of arguments for (${
1135
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1136
+ }) (if (< index 0) then 2 required) (${
1137
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1138
+ } ${stringifyArgs(args)})`
1139
+ )
1140
+ if (index * -1 > array.length)
1141
+ throw new RangeError(
1142
+ `Second argument of (${
1143
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1144
+ }) is outside of the (${
1145
+ KEYWORDS.ARRAY_TYPE
1146
+ }) bounds (index ${index} bounds ${array.length}) (${
1147
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1148
+ } ${stringifyArgs(args)})`
1149
+ )
1150
+ const target = array.length + index
1151
+ while (array.length !== target) array.pop()
1152
+ } else {
1153
+ if (args.length !== 3)
1154
+ throw new RangeError(
1155
+ `Invalid number of arguments for (${
1156
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1157
+ }) (if (>= index 0) then 3 required) (${
1158
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1159
+ } ${stringifyArgs(args)})`
1160
+ )
1161
+ const value = evaluate(args[2], env)
1162
+ if (value == undefined)
1163
+ throw new RangeError(
1164
+ `Trying to set a null value in (${KEYWORDS.ARRAY_TYPE}) at (${
1165
+ KEYWORDS.SET_IMMUTABLE_ARRAY
1166
+ }). (${KEYWORDS.SET_IMMUTABLE_ARRAY} ${stringifyArgs(args)})`
1167
+ )
1168
+ array[index] = value
1169
+ }
1170
+ return array
1171
+ },
1083
1172
  }
1084
1173
  keywords[KEYWORDS.NOT_COMPILED_BLOCK] = keywords[KEYWORDS.BLOCK]
1085
1174
  export { keywords }