fez-lisp 1.0.7 → 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +18 -18
- package/lib/baked/std.js +1 -1
- package/package.json +2 -2
- package/src/compiler.js +16 -3
- package/src/enums.js +1 -0
- package/src/interpreter.js +3 -3
- package/src/parser.js +2 -1
- package/src/tokeniser.js +197 -119
- package/src/utils.js +5 -5
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
|
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}),
|
465
|
-
KEYWORDS.
|
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
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
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}),
|
487
|
-
KEYWORDS.
|
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
|
-
}),
|
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
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
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
|
-
}),
|
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
|
-
}),
|
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
|
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
|
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
|
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 }
|