fez-lisp 1.5.19 → 1.5.21
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 +3 -3
- package/lib/baked/macros.js +1 -1
- package/lib/baked/std.js +1 -1
- package/package.json +1 -1
- package/src/check.js +10 -2
- package/src/compiler.js +6 -4
- package/src/interpreter.js +51 -40
- package/src/keywords.js +2 -1
- package/src/macros.js +14 -0
package/package.json
CHANGED
package/src/check.js
CHANGED
@@ -224,7 +224,7 @@ export const typeCheck = (ast) => {
|
|
224
224
|
[KEYWORDS.SET_ARRAY]: {
|
225
225
|
[STATS]: {
|
226
226
|
type: APPLY,
|
227
|
-
[ARGS_COUNT]: new Set([
|
227
|
+
[ARGS_COUNT]: new Set([3]),
|
228
228
|
[ARGS]: [
|
229
229
|
[UNKNOWN, PLACEHOLDER],
|
230
230
|
[ATOM, PLACEHOLDER],
|
@@ -233,6 +233,14 @@ export const typeCheck = (ast) => {
|
|
233
233
|
[RETURNS]: UNKNOWN
|
234
234
|
}
|
235
235
|
},
|
236
|
+
[KEYWORDS.POP_ARRAY]: {
|
237
|
+
[STATS]: {
|
238
|
+
type: APPLY,
|
239
|
+
[ARGS_COUNT]: new Set([1]),
|
240
|
+
[ARGS]: [[UNKNOWN, PLACEHOLDER]],
|
241
|
+
[RETURNS]: UNKNOWN
|
242
|
+
}
|
243
|
+
},
|
236
244
|
[KEYWORDS.ARRAY_LENGTH]: {
|
237
245
|
[STATS]: {
|
238
246
|
type: APPLY,
|
@@ -244,7 +252,7 @@ export const typeCheck = (ast) => {
|
|
244
252
|
[KEYWORDS.IF]: {
|
245
253
|
[STATS]: {
|
246
254
|
type: APPLY,
|
247
|
-
[ARGS_COUNT]: new Set([
|
255
|
+
[ARGS_COUNT]: new Set([3]),
|
248
256
|
[ARGS]: [
|
249
257
|
[ATOM, PLACEHOLDER, PREDICATE],
|
250
258
|
[UNKNOWN, PLACEHOLDER],
|
package/src/compiler.js
CHANGED
@@ -112,7 +112,8 @@ const Helpers = {
|
|
112
112
|
atom_predicate: `atom_predicate=(number)=>+(typeof number==='number')`,
|
113
113
|
lambda_predicate: `lambda_predicate=(fn)=>+(typeof fn==='function')`,
|
114
114
|
__error: `__error=(error)=>{throw new Error(error.map((x)=>String.fromCharCode(x)).join(''))}`,
|
115
|
-
|
115
|
+
set_effect: `set_effect=(array,index,value)=>{array[index] = value;return array}`,
|
116
|
+
pop_effect: `pop_effect=(array)=>{array.pop();return array}`
|
116
117
|
}
|
117
118
|
const semiColumnEdgeCases = new Set([
|
118
119
|
';)',
|
@@ -250,9 +251,10 @@ const comp = (tree, Drill) => {
|
|
250
251
|
case KEYWORDS.NOT:
|
251
252
|
return `(+!${comp(tail[0], Drill)})`
|
252
253
|
case KEYWORDS.IF: {
|
253
|
-
return `(${comp(tail[0], Drill)}?${comp(tail[1], Drill)}:${
|
254
|
-
tail
|
255
|
-
|
254
|
+
return `(${comp(tail[0], Drill)}?${comp(tail[1], Drill)}:${comp(
|
255
|
+
tail[2],
|
256
|
+
Drill
|
257
|
+
)});`
|
256
258
|
}
|
257
259
|
case KEYWORDS.LOOP: {
|
258
260
|
return `(()=>{while(${comp(tail[0], Drill)}){${comp(
|
package/src/interpreter.js
CHANGED
@@ -389,11 +389,11 @@ export const keywords = {
|
|
389
389
|
return value
|
390
390
|
},
|
391
391
|
[KEYWORDS.SET_ARRAY]: (args, env) => {
|
392
|
-
if (args.length !==
|
392
|
+
if (args.length !== 3)
|
393
393
|
throw new RangeError(
|
394
394
|
`Invalid number of arguments for (${
|
395
395
|
KEYWORDS.SET_ARRAY
|
396
|
-
}) (
|
396
|
+
}) (= 3) required\n\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
|
397
397
|
)
|
398
398
|
const array = evaluate(args[0], env)
|
399
399
|
if (!Array.isArray(array))
|
@@ -404,37 +404,52 @@ export const keywords = {
|
|
404
404
|
KEYWORDS.SET_ARRAY
|
405
405
|
} ${stringifyArgs(args)})`
|
406
406
|
)
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
)
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
407
|
+
const index = evaluate(args[1], env)
|
408
|
+
if (!Number.isInteger(index) || index < 0)
|
409
|
+
throw new TypeError(
|
410
|
+
`Second argument of (${KEYWORDS.SET_ARRAY}) must be a positive (${
|
411
|
+
RUNTIME_TYPES.NUMBER
|
412
|
+
} integer) (= i ${index}) but ${LISP.source(args[1])} is not\n\n(${
|
413
|
+
KEYWORDS.SET_ARRAY
|
414
|
+
} ${stringifyArgs(args)})`
|
415
|
+
)
|
416
|
+
if (index > array.length)
|
417
|
+
throw new RangeError(
|
418
|
+
`Second argument of (${KEYWORDS.SET_ARRAY}) is outside of the (${
|
419
|
+
RUNTIME_TYPES.ARRAY
|
420
|
+
}) bounds (${index}) expected (and (>= i 0) (< i ${
|
421
|
+
array.length
|
422
|
+
})) but ${LISP.source(args[1])} is not\n\n(${
|
423
|
+
KEYWORDS.SET_ARRAY
|
424
|
+
} ${stringifyArgs(args)})`
|
425
|
+
)
|
426
|
+
const value = evaluate(args[2], env)
|
427
|
+
if (value == undefined)
|
428
|
+
throw new RangeError(
|
429
|
+
`Trying to set a null value in (${RUNTIME_TYPES.ARRAY}) at (${
|
430
|
+
KEYWORDS.SET_ARRAY
|
431
|
+
})\n\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
|
432
|
+
)
|
433
|
+
array[index] = value
|
434
|
+
return array
|
435
|
+
},
|
436
|
+
[KEYWORDS.POP_ARRAY]: (args, env) => {
|
437
|
+
if (args.length !== 1)
|
438
|
+
throw new RangeError(
|
439
|
+
`Invalid number of arguments for (${
|
440
|
+
KEYWORDS.POP_ARRAY
|
441
|
+
}) (= 1) required\n\n(${KEYWORDS.POP_ARRAY} ${stringifyArgs(args)})`
|
442
|
+
)
|
443
|
+
const array = evaluate(args[0], env)
|
444
|
+
if (!Array.isArray(array))
|
445
|
+
throw new TypeError(
|
446
|
+
`First argument of (${KEYWORDS.POP_ARRAY}) must be an (${
|
447
|
+
RUNTIME_TYPES.ARRAY
|
448
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
449
|
+
KEYWORDS.POP_ARRAY
|
450
|
+
} ${stringifyArgs(args)})`
|
451
|
+
)
|
452
|
+
array.pop()
|
438
453
|
return array
|
439
454
|
},
|
440
455
|
[KEYWORDS.ARRAY_LENGTH]: (args, env) => {
|
@@ -456,11 +471,11 @@ export const keywords = {
|
|
456
471
|
return array.length
|
457
472
|
},
|
458
473
|
[KEYWORDS.IF]: (args, env) => {
|
459
|
-
if (args.length
|
474
|
+
if (args.length !== 3)
|
460
475
|
throw new RangeError(
|
461
476
|
`Invalid number of arguments for (${
|
462
477
|
KEYWORDS.IF
|
463
|
-
}), expected (
|
478
|
+
}), expected (= 3) but got ${args.length}\n\n(${
|
464
479
|
KEYWORDS.IF
|
465
480
|
} ${stringifyArgs(args)})`
|
466
481
|
)
|
@@ -473,11 +488,7 @@ export const keywords = {
|
|
473
488
|
KEYWORDS.IF
|
474
489
|
} ${stringifyArgs(args)})`
|
475
490
|
)
|
476
|
-
return condition
|
477
|
-
? evaluate(args[1], env)
|
478
|
-
: args.length === 3
|
479
|
-
? evaluate(args[2], env)
|
480
|
-
: FALSE
|
491
|
+
return condition ? evaluate(args[1], env) : evaluate(args[2], env)
|
481
492
|
},
|
482
493
|
[KEYWORDS.NOT]: (args, env) => {
|
483
494
|
if (args.length !== 1)
|
package/src/keywords.js
CHANGED
package/src/macros.js
CHANGED
@@ -362,6 +362,20 @@ export const deSuggarAst = (ast, scope) => {
|
|
362
362
|
}
|
363
363
|
deSuggarAst(exp, scope)
|
364
364
|
break
|
365
|
+
case KEYWORDS.IF:
|
366
|
+
{
|
367
|
+
if (rest.length > 3 || rest.length < 2)
|
368
|
+
throw new RangeError(
|
369
|
+
`Invalid number of arguments for (${
|
370
|
+
KEYWORDS.IF
|
371
|
+
}), expected (or (= 3) (= 2)) but got ${rest.length} (${
|
372
|
+
KEYWORDS.IF
|
373
|
+
} ${stringifyArgs(rest)})`
|
374
|
+
)
|
375
|
+
if (rest.length === 2) exp.push([ATOM, FALSE])
|
376
|
+
}
|
377
|
+
deSuggarAst(exp[1], scope)
|
378
|
+
break
|
365
379
|
case SUGGAR.REMAINDER_OF_DIVISION_1:
|
366
380
|
{
|
367
381
|
if (rest.length !== 2)
|