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