fez-lisp 1.2.34 → 1.2.36
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 +4 -3
- package/lib/baked/std.js +1 -1
- package/package.json +1 -1
- package/src/compiler.js +10 -2
- package/src/interpreter.js +92 -7
- package/src/keywords.js +3 -0
package/package.json
CHANGED
package/src/compiler.js
CHANGED
@@ -109,7 +109,8 @@ const Helpers = {
|
|
109
109
|
__tco: `__tco=fn=>(...args)=>{let result=fn(...args);while(typeof result==='function')result=result();return result}`,
|
110
110
|
atom_predicate: `atom_predicate=(number)=>+(typeof number==='number')`,
|
111
111
|
lambda_predicate: `lambda_predicate=(fm)=>+(typeof fn==='function')`,
|
112
|
-
set_effect: `set_effect=(array,index,value)=>{if(index<0){const target=array.length+index;while(array.length!==target)array.pop()}else array[index] = value;return array}
|
112
|
+
set_effect: `set_effect=(array,index,value)=>{if(index<0){const target=array.length+index;while(array.length!==target)array.pop()}else array[index] = value;return array}`,
|
113
|
+
__error: `__error=(error)=>{throw new Error(error.map((x)=>String.fromCharCode(x)).join(''))}`
|
113
114
|
}
|
114
115
|
const semiColumnEdgeCases = new Set([
|
115
116
|
';)',
|
@@ -129,7 +130,8 @@ const semiColumnEdgeCases = new Set([
|
|
129
130
|
';?',
|
130
131
|
',,',
|
131
132
|
';;',
|
132
|
-
';]'
|
133
|
+
';]',
|
134
|
+
';^'
|
133
135
|
])
|
134
136
|
const parse = (Arguments, Drill) => Arguments.map((x) => compile(x, Drill))
|
135
137
|
const parseArgs = (Arguments, Drill, separator = ',') =>
|
@@ -141,6 +143,8 @@ const compile = (tree, Drill) => {
|
|
141
143
|
const token = first[VALUE]
|
142
144
|
if (first[TYPE] === APPLY) {
|
143
145
|
switch (token) {
|
146
|
+
case KEYWORDS.ASSERT:
|
147
|
+
return '0'
|
144
148
|
case KEYWORDS.BLOCK: {
|
145
149
|
if (Arguments.length > 1) {
|
146
150
|
return `(${Arguments.map((x) =>
|
@@ -292,6 +296,10 @@ const compile = (tree, Drill) => {
|
|
292
296
|
out += '0);'
|
293
297
|
return out
|
294
298
|
}
|
299
|
+
case KEYWORDS.THROW: {
|
300
|
+
Drill.Helpers.add('__error')
|
301
|
+
return `__error(${compile(Arguments[0], Drill)})`
|
302
|
+
}
|
295
303
|
default: {
|
296
304
|
const camelCased = lispToJavaScriptVariableName(token)
|
297
305
|
if (camelCased in Helpers) Drill.Helpers.add(camelCased)
|
package/src/interpreter.js
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
TYPE,
|
3
|
+
VALUE,
|
4
|
+
WORD,
|
5
|
+
KEYWORDS,
|
6
|
+
FALSE,
|
7
|
+
TRUE,
|
8
|
+
TYPES,
|
9
|
+
APPLY
|
10
|
+
} from './keywords.js'
|
2
11
|
import { evaluate } from './evaluator.js'
|
3
12
|
import { isForbiddenVariableName, stringifyArgs } from './utils.js'
|
4
13
|
const keywords = {
|
@@ -161,7 +170,9 @@ const keywords = {
|
|
161
170
|
const condition = evaluate(args[0], env)
|
162
171
|
if (condition !== FALSE && condition !== TRUE)
|
163
172
|
throw new TypeError(
|
164
|
-
`Condition of (${KEYWORDS.IF}) must be ${TRUE} or ${FALSE} but got ${
|
173
|
+
`Condition of (${KEYWORDS.IF}) must be ${TRUE} or ${FALSE} but got (${
|
174
|
+
KEYWORDS.IF
|
175
|
+
} ${stringifyArgs(args)})`
|
165
176
|
)
|
166
177
|
return condition
|
167
178
|
? evaluate(args[1], env)
|
@@ -190,7 +201,11 @@ const keywords = {
|
|
190
201
|
const condition = evaluate(args[i], env)
|
191
202
|
if (condition !== FALSE && condition !== TRUE)
|
192
203
|
throw new TypeError(
|
193
|
-
`Condition of (${
|
204
|
+
`Condition of (${
|
205
|
+
KEYWORDS.CONDITION
|
206
|
+
}) must be ${TRUE} or ${FALSE} but got (${
|
207
|
+
KEYWORDS.CONDITION
|
208
|
+
} ${stringifyArgs(args)})`
|
194
209
|
)
|
195
210
|
if (condition) return evaluate(args[i + 1], env)
|
196
211
|
}
|
@@ -426,7 +441,11 @@ const keywords = {
|
|
426
441
|
circuit = evaluate(args[i], env)
|
427
442
|
if (circuit !== FALSE && circuit !== TRUE)
|
428
443
|
throw new TypeError(
|
429
|
-
`Condition of (${
|
444
|
+
`Condition of (${
|
445
|
+
KEYWORDS.AND
|
446
|
+
}) must be ${TRUE} or ${FALSE} but got (${
|
447
|
+
KEYWORDS.AND
|
448
|
+
} ${stringifyArgs(args)})`
|
430
449
|
)
|
431
450
|
if (circuit) continue
|
432
451
|
else return 0
|
@@ -434,7 +453,9 @@ const keywords = {
|
|
434
453
|
const end = evaluate(args.at(-1), env)
|
435
454
|
if (end !== FALSE && end !== TRUE)
|
436
455
|
throw new TypeError(
|
437
|
-
`Condition of (${KEYWORDS.AND}) must be ${TRUE} or ${FALSE} but got ${
|
456
|
+
`Condition of (${KEYWORDS.AND}) must be ${TRUE} or ${FALSE} but got (${
|
457
|
+
KEYWORDS.AND
|
458
|
+
} ${stringifyArgs(args)})`
|
438
459
|
)
|
439
460
|
return end
|
440
461
|
},
|
@@ -450,7 +471,9 @@ const keywords = {
|
|
450
471
|
circuit = evaluate(args[i], env)
|
451
472
|
if (circuit !== FALSE && circuit !== TRUE)
|
452
473
|
throw new TypeError(
|
453
|
-
`Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got ${
|
474
|
+
`Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got (${
|
475
|
+
KEYWORDS.OR
|
476
|
+
} ${stringifyArgs(args)})`
|
454
477
|
)
|
455
478
|
if (circuit) return 1
|
456
479
|
else continue
|
@@ -458,7 +481,9 @@ const keywords = {
|
|
458
481
|
const end = evaluate(args.at(-1), env)
|
459
482
|
if (end !== FALSE && end !== TRUE)
|
460
483
|
throw new TypeError(
|
461
|
-
`Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got ${
|
484
|
+
`Condition of (${KEYWORDS.OR}) must be ${TRUE} or ${FALSE} but got (${
|
485
|
+
KEYWORDS.OR
|
486
|
+
} ${stringifyArgs(args)})`
|
462
487
|
)
|
463
488
|
return end
|
464
489
|
},
|
@@ -784,6 +809,66 @@ const keywords = {
|
|
784
809
|
)
|
785
810
|
console.clear()
|
786
811
|
return 0
|
812
|
+
},
|
813
|
+
|
814
|
+
// Not sure about these
|
815
|
+
[KEYWORDS.THROW]: (args, env) => {
|
816
|
+
if (args.length !== 1)
|
817
|
+
throw new RangeError(
|
818
|
+
`Invalid number of arguments to (${KEYWORDS.THROW}) (= 1 required) (${
|
819
|
+
KEYWORDS.THROW
|
820
|
+
} ${stringifyArgs(args)})`
|
821
|
+
)
|
822
|
+
const expression = evaluate(args[0], env)
|
823
|
+
if (!Array.isArray(expression))
|
824
|
+
throw new TypeError(
|
825
|
+
`Argument of (${KEYWORDS.THROW}) must be an (${
|
826
|
+
KEYWORDS.ARRAY_TYPE
|
827
|
+
}) but got (${expression}) (${KEYWORDS.THROW} ${stringifyArgs(args)})`
|
828
|
+
)
|
829
|
+
throw new Error(expression.map((x) => String.fromCharCode(x)).join(''))
|
830
|
+
},
|
831
|
+
|
832
|
+
[KEYWORDS.ASSERT]: (args, env) => {
|
833
|
+
if (args.length < 2)
|
834
|
+
throw new RangeError(
|
835
|
+
`Invalid number of arguments for (${
|
836
|
+
KEYWORDS.ASSERT
|
837
|
+
}), expected (> 2 required) but got ${args.length} (${
|
838
|
+
KEYWORDS.ASSERT
|
839
|
+
} ${stringifyArgs(args)})`
|
840
|
+
)
|
841
|
+
if (args.length % 2 !== 0)
|
842
|
+
throw new RangeError(
|
843
|
+
`Invalid number of arguments for (${
|
844
|
+
KEYWORDS.ASSERT
|
845
|
+
}), expected even number of arguments but got ${args.length} (${
|
846
|
+
KEYWORDS.ASSERT
|
847
|
+
} ${stringifyArgs(args)})`
|
848
|
+
)
|
849
|
+
for (let i = 0; i < args.length; i += 2) {
|
850
|
+
const condition = evaluate(args[i], env)
|
851
|
+
if (condition !== FALSE && condition !== TRUE)
|
852
|
+
throw new TypeError(
|
853
|
+
`Condition of (${
|
854
|
+
KEYWORDS.ASSERT
|
855
|
+
}) must be ${TRUE} or ${FALSE} but got (${
|
856
|
+
KEYWORDS.ASSERT
|
857
|
+
} ${stringifyArgs(args)})`
|
858
|
+
)
|
859
|
+
if (condition) {
|
860
|
+
const error = args[i + 1]
|
861
|
+
if (error[0][TYPE] === APPLY && error[0][VALUE] === KEYWORDS.THROW)
|
862
|
+
return evaluate(error, env)
|
863
|
+
else
|
864
|
+
throw new TypeError(
|
865
|
+
`Concequence of (${KEYWORDS.ASSERT}) must be (${
|
866
|
+
KEYWORDS.THROW
|
867
|
+
}) but got (${KEYWORDS.ASSERT} ${stringifyArgs(args)})`
|
868
|
+
)
|
869
|
+
}
|
870
|
+
}
|
871
|
+
return 0
|
787
872
|
}
|
788
873
|
}
|
789
874
|
|