fez-lisp 1.6.28 → 1.6.30
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 +33 -4
- package/package.json +1 -1
- package/src/debugger.js +1086 -60
- package/src/keywords.js +0 -2
- package/src/parser.js +9 -0
- package/src/types.js +0 -18
- package/src/utils.js +3 -1
package/README.md
CHANGED
@@ -28,8 +28,17 @@
|
|
28
28
|
|
29
29
|
```lisp
|
30
30
|
; Lisp programming language. It's not exactly like other Lisps.
|
31
|
+
; This is a CUSTOM lisp language that does not fully follow the general Lisp conventions
|
32
|
+
|
33
|
+
; Plase strictly follow the language rules as described in this document
|
34
|
+
|
31
35
|
; Everything is an expression.
|
32
36
|
|
37
|
+
; Build-in keywords
|
38
|
+
(/ ...) (+ ...) (* ...) (- ...) (= ...) (< ...) (> ...) (>= ...) (<= ...) (& ...) (~ ...) (| ...) (^ ...) (<< ...) (>> ...)
|
39
|
+
(mod ...) (let ...) (if ...) (not ...) (and ...) (or ...) (atom? ...) (lambda? ...)
|
40
|
+
(length ...) (do ...) (array ...) (set! ...) (pop! ...) (get ...) (lambda ...) (apply ...)
|
41
|
+
|
33
42
|
; Important Note:
|
34
43
|
; In this programming language, parentheses are used to group expressions and define the structure of code.
|
35
44
|
; It is essential to keep the number of opening and closing parentheses balanced.
|
@@ -83,7 +92,7 @@
|
|
83
92
|
(array:push! xs (length xs) 10) ; add the value 10 at the end of array xs
|
84
93
|
(array:get xs 0) ; get the first element of array xs
|
85
94
|
|
86
|
-
; Note:
|
95
|
+
; Note: set! and pop! are functions that update arrays (set! xs idx value, pop! xs).
|
87
96
|
; If you want to update variables (scalars), use the variable helpers: var:def to define, var:set! to update, and var:get to retrieve the value.
|
88
97
|
|
89
98
|
; Mathematical operations
|
@@ -164,7 +173,7 @@
|
|
164
173
|
; IMPORTANT: Variable Handling and set! Usage
|
165
174
|
; ===========================================
|
166
175
|
;
|
167
|
-
;
|
176
|
+
; set! is ONLY for arrays - it cannot be used to update scalar variables.
|
168
177
|
; If you want to update variables (scalars), use the appropriate variable helper functions.
|
169
178
|
;
|
170
179
|
; There are three types of variable systems in this language:
|
@@ -226,8 +235,8 @@
|
|
226
235
|
xs)))
|
227
236
|
(let arr:merge (lambda a b (do
|
228
237
|
(let out (array)) initialize an empty array for output
|
229
|
-
(arr:for a (lambda x (do (
|
230
|
-
(arr:for b (lambda x (do (
|
238
|
+
(arr:for a (lambda x (do (set! out (length out) x))))
|
239
|
+
(arr:for b (lambda x (do (set! out (length out) x)))) out)))
|
231
240
|
(let arr:reverse (lambda xs (do
|
232
241
|
(let tail-call:arr:reverse (lambda i out (do
|
233
242
|
(if (> (length xs) i)
|
@@ -256,4 +265,24 @@
|
|
256
265
|
; pipe operator with destructuring
|
257
266
|
|
258
267
|
"Hello World!" ; syntactic suggar for string but it's array of character codes
|
268
|
+
|
269
|
+
; syntactic suggar for variables
|
270
|
+
|
271
|
+
(let xs [])
|
272
|
+
(variable i 0) ; define number variables
|
273
|
+
(get i) ; getting nubmer variable
|
274
|
+
(loop (< (get i) 10) (do
|
275
|
+
(array:push! xs (get i))
|
276
|
+
(++ i) ; increment number variaable
|
277
|
+
))
|
278
|
+
|
279
|
+
(boolean x false) ; define boolean variable as false
|
280
|
+
(boolean y true) ; define boolean variable as true
|
281
|
+
(boole-set x true) ; set boolean variable
|
282
|
+
(and (boole:true? x) (boole:true? y)) ; check if boolean variable is true (this is using boole:* from std)
|
283
|
+
(variable n 10) ; define number variable
|
284
|
+
(++ n) ; increment number variable by 1
|
285
|
+
(+= n 10) ; increment number variable by 10
|
286
|
+
(get n) ; get number variable
|
287
|
+
|
259
288
|
```
|
package/package.json
CHANGED
package/src/debugger.js
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
import
|
1
|
+
import stdT from '../lib/baked/std-T.js'
|
2
|
+
import std from '../lib/baked/std.js'
|
3
|
+
import { typeCheck } from './check.js'
|
4
|
+
import { enhance } from './enhance.js'
|
2
5
|
import {
|
3
6
|
APPLY,
|
4
7
|
ATOM,
|
@@ -8,85 +11,817 @@ import {
|
|
8
11
|
WORD,
|
9
12
|
TRUE,
|
10
13
|
FALSE,
|
11
|
-
STATIC_TYPES
|
14
|
+
STATIC_TYPES,
|
15
|
+
DEBUG,
|
16
|
+
SPECIAL_FORMS_SET
|
12
17
|
} from './keywords.js'
|
13
18
|
import { isLeaf, LISP } from './parser.js'
|
19
|
+
import { definedTypes, filteredDefinedTypes, withCtxTypes } from './types.js'
|
20
|
+
import { isForbiddenVariableName } from './utils.js'
|
14
21
|
const keywords = {
|
15
|
-
[KEYWORDS.REMAINDER_OF_DIVISION]: (args, env) =>
|
16
|
-
evaluate(args[0], env) % evaluate(args[1], env),
|
17
|
-
[KEYWORDS.DIVISION]: (args, env) =>
|
18
|
-
evaluate(args[0], env) / evaluate(args[1], env),
|
19
|
-
[KEYWORDS.ARRAY_LENGTH]: (args, env) => evaluate(args[0], env).length,
|
20
|
-
[KEYWORDS.IS_ATOM]: (args, env) =>
|
21
|
-
+(typeof evaluate(args[0], env) === 'number'),
|
22
|
-
[KEYWORDS.IS_LAMBDA]: (args, env) =>
|
23
|
-
+(typeof evaluate(args[0], env) === 'function'),
|
24
|
-
[KEYWORDS.ADDITION]: (args, env) =>
|
25
|
-
evaluate(args[0], env) + evaluate(args[1], env),
|
26
|
-
[KEYWORDS.MULTIPLICATION]: (args, env) =>
|
27
|
-
evaluate(args[0], env) * evaluate(args[1], env),
|
28
|
-
[KEYWORDS.SUBTRACTION]: (args, env) =>
|
29
|
-
evaluate(args[0], env) - evaluate(args[1], env),
|
30
|
-
[KEYWORDS.CREATE_ARRAY]: (args, env) =>
|
31
|
-
args.length ? args.map((x) => evaluate(x, env)) : [],
|
32
|
-
[KEYWORDS.GET_ARRAY]: (args, env) =>
|
33
|
-
evaluate(args[0], env)[evaluate(args[1], env)],
|
34
|
-
[KEYWORDS.BLOCK]: (args, env) =>
|
35
|
-
args.reduce((_, x) => evaluate(x, env), FALSE),
|
36
|
-
[KEYWORDS.NOT]: (args, env) => +!evaluate(args[0], env),
|
37
|
-
[KEYWORDS.EQUAL]: (args, env) =>
|
38
|
-
+(evaluate(args[0], env) === evaluate(args[1], env)),
|
39
|
-
[KEYWORDS.LESS_THAN]: (args, env) =>
|
40
|
-
+(evaluate(args[0], env) < evaluate(args[1], env)),
|
41
|
-
[KEYWORDS.GREATHER_THAN]: (args, env) =>
|
42
|
-
+(evaluate(args[0], env) > evaluate(args[1], env)),
|
43
|
-
[KEYWORDS.GREATHER_THAN_OR_EQUAL]: (args, env) =>
|
44
|
-
+(evaluate(args[0], env) >= evaluate(args[1], env)),
|
45
|
-
[KEYWORDS.LESS_THAN_OR_EQUAL]: (args, env) =>
|
46
|
-
+(evaluate(args[0], env) <= evaluate(args[1], env)),
|
47
|
-
[KEYWORDS.AND]: (args, env) =>
|
48
|
-
!evaluate(args[0], env) ? FALSE : evaluate(args[1], env),
|
49
|
-
[KEYWORDS.OR]: (args, env) =>
|
50
|
-
evaluate(args[0], env) ? TRUE : evaluate(args[1], env),
|
51
|
-
[KEYWORDS.CALL_FUNCTION]: (args, env) => evaluate(args.pop(), env)(args, env),
|
52
|
-
[KEYWORDS.DEFINE_VARIABLE]: (args, env) =>
|
53
|
-
(env[args[0][VALUE]] = evaluate(args[1], env)),
|
54
|
-
[KEYWORDS.BITWISE_AND]: (args, env) =>
|
55
|
-
evaluate(args[0], env) & evaluate(args[1], env),
|
56
|
-
[KEYWORDS.BITWISE_NOT]: (args, env) => ~evaluate(args[0], env),
|
57
|
-
[KEYWORDS.BITWISE_OR]: (args, env) =>
|
58
|
-
evaluate(args[0], env) | evaluate(args[1], env),
|
59
|
-
[KEYWORDS.BITWISE_XOR]: (args, env) =>
|
60
|
-
evaluate(args[0], env) ^ evaluate(args[1], env),
|
61
|
-
[KEYWORDS.BITWISE_LEFT_SHIFT]: (args, env) =>
|
62
|
-
evaluate(args[0], env) << evaluate(args[1], env),
|
63
|
-
[KEYWORDS.BITWISE_RIGHT_SHIFT]: (args, env) =>
|
64
|
-
evaluate(args[0], env) >> evaluate(args[1], env),
|
65
|
-
[KEYWORDS.IF]: (args, env) =>
|
66
|
-
evaluate(args[0], env) ? evaluate(args[1], env) : evaluate(args[2], env),
|
67
22
|
[KEYWORDS.LOOP]: (args, env) => {
|
23
|
+
if (args.length != 2)
|
24
|
+
throw new RangeError(`Wrong number of args to ${KEYWORDS.LOOP}`)
|
68
25
|
while (evaluate(args[0], env) === TRUE) evaluate(args[1], env)
|
69
26
|
return -1
|
70
27
|
},
|
28
|
+
[KEYWORDS.ADDITION]: (args, env) => {
|
29
|
+
if (args.length !== 2)
|
30
|
+
throw new RangeError(
|
31
|
+
`Invalid number of arguments for (${
|
32
|
+
KEYWORDS.ADDITION
|
33
|
+
}), expected (= 2) but got ${args.length}\n\n(${
|
34
|
+
KEYWORDS.ADDITION
|
35
|
+
} ${stringifyArgs(args)})`
|
36
|
+
)
|
37
|
+
const a = evaluate(args[0], env)
|
38
|
+
if (typeof a !== 'number')
|
39
|
+
throw new TypeError(
|
40
|
+
`First arguments of (${KEYWORDS.ADDITION}) must be a (${
|
41
|
+
RUNTIME_TYPES.NUMBER
|
42
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
43
|
+
KEYWORDS.ADDITION
|
44
|
+
} ${stringifyArgs(args)})`
|
45
|
+
)
|
46
|
+
const b = evaluate(args[1], env)
|
47
|
+
if (typeof b !== 'number')
|
48
|
+
throw new TypeError(
|
49
|
+
`Second arguments of (${KEYWORDS.ADDITION}) must be a (${
|
50
|
+
RUNTIME_TYPES.NUMBER
|
51
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
52
|
+
KEYWORDS.ADDITION
|
53
|
+
} ${stringifyArgs(args)})`
|
54
|
+
)
|
55
|
+
return a + b
|
56
|
+
},
|
57
|
+
[KEYWORDS.MULTIPLICATION]: (args, env) => {
|
58
|
+
if (args.length !== 2)
|
59
|
+
throw new RangeError(
|
60
|
+
`Invalid number of arguments for (${
|
61
|
+
KEYWORDS.MULTIPLICATION
|
62
|
+
}), expected (= 2) but got ${args.length}\n\n(${
|
63
|
+
KEYWORDS.MULTIPLICATION
|
64
|
+
} ${stringifyArgs(args)})`
|
65
|
+
)
|
66
|
+
const a = evaluate(args[0], env)
|
67
|
+
if (typeof a !== 'number')
|
68
|
+
throw new TypeError(
|
69
|
+
`First arguments of (${KEYWORDS.MULTIPLICATION}) must be a (${
|
70
|
+
RUNTIME_TYPES.NUMBER
|
71
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
72
|
+
KEYWORDS.MULTIPLICATION
|
73
|
+
} ${stringifyArgs(args)})`
|
74
|
+
)
|
75
|
+
const b = evaluate(args[1], env)
|
76
|
+
if (typeof b !== 'number')
|
77
|
+
throw new TypeError(
|
78
|
+
`Second arguments of (${KEYWORDS.MULTIPLICATION}) must be a (${
|
79
|
+
RUNTIME_TYPES.NUMBER
|
80
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
81
|
+
KEYWORDS.MULTIPLICATION
|
82
|
+
} ${stringifyArgs(args)})`
|
83
|
+
)
|
84
|
+
return a * b
|
85
|
+
},
|
86
|
+
[KEYWORDS.SUBTRACTION]: (args, env) => {
|
87
|
+
if (args.length !== 2)
|
88
|
+
throw new RangeError(
|
89
|
+
`Invalid number of arguments for (${
|
90
|
+
KEYWORDS.SUBTRACTION
|
91
|
+
}), expected (= 2) but got ${args.length}\n\n(${
|
92
|
+
KEYWORDS.SUBTRACTION
|
93
|
+
} ${stringifyArgs(args)})`
|
94
|
+
)
|
95
|
+
const a = evaluate(args[0], env)
|
96
|
+
if (typeof a !== 'number')
|
97
|
+
throw new TypeError(
|
98
|
+
`First argument of (${KEYWORDS.SUBTRACTION}) must be a (${
|
99
|
+
RUNTIME_TYPES.NUMBER
|
100
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
101
|
+
KEYWORDS.SUBTRACTION
|
102
|
+
} ${stringifyArgs(args)})`
|
103
|
+
)
|
104
|
+
const b = evaluate(args[1], env)
|
105
|
+
if (typeof b !== 'number')
|
106
|
+
throw new TypeError(
|
107
|
+
`Second argument of (${KEYWORDS.SUBTRACTION}) must be a (${
|
108
|
+
RUNTIME_TYPES.NUMBER
|
109
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
110
|
+
KEYWORDS.SUBTRACTION
|
111
|
+
} ${stringifyArgs(args)})`
|
112
|
+
)
|
113
|
+
return a - b
|
114
|
+
},
|
115
|
+
[KEYWORDS.DIVISION]: (args, env) => {
|
116
|
+
if (args.length !== 2)
|
117
|
+
throw new RangeError(
|
118
|
+
`Invalid number of arguments for (${
|
119
|
+
KEYWORDS.DIVISION
|
120
|
+
}), expected (= 2) but got ${args.length}\n\n(${
|
121
|
+
KEYWORDS.DIVISION
|
122
|
+
} ${stringifyArgs(args)})`
|
123
|
+
)
|
124
|
+
const a = evaluate(args[0], env)
|
125
|
+
if (typeof a !== 'number')
|
126
|
+
throw new TypeError(
|
127
|
+
`First argument of (${KEYWORDS.DIVISION}) is not (${
|
128
|
+
RUNTIME_TYPES.NUMBER
|
129
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
130
|
+
KEYWORDS.DIVISION
|
131
|
+
} ${stringifyArgs(args)})`
|
132
|
+
)
|
133
|
+
const b = evaluate(args[1], env)
|
134
|
+
if (typeof b !== 'number')
|
135
|
+
throw new TypeError(
|
136
|
+
`Second argument of (${KEYWORDS.DIVISION}) is not (${
|
137
|
+
RUNTIME_TYPES.NUMBER
|
138
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
139
|
+
KEYWORDS.DIVISION
|
140
|
+
} ${stringifyArgs(args)})`
|
141
|
+
)
|
142
|
+
if (b === 0)
|
143
|
+
throw new TypeError(
|
144
|
+
`Second Argument of (${
|
145
|
+
KEYWORDS.DIVISION
|
146
|
+
}) can't be a 0 (division by 0 is not allowed) but ${LISP.source(
|
147
|
+
args[1]
|
148
|
+
)} is 0\n\n(${KEYWORDS.DIVISION} ${stringifyArgs(args)})`
|
149
|
+
)
|
150
|
+
return a / b
|
151
|
+
},
|
152
|
+
[KEYWORDS.REMAINDER_OF_DIVISION]: (args, env) => {
|
153
|
+
if (args.length !== 2)
|
154
|
+
throw new RangeError(
|
155
|
+
`Invalid number of arguments for (${
|
156
|
+
KEYWORDS.REMAINDER_OF_DIVISION
|
157
|
+
}), expected (= 2) but got ${args.length}\n\n(${
|
158
|
+
KEYWORDS.REMAINDER_OF_DIVISION
|
159
|
+
} ${stringifyArgs(args)})`
|
160
|
+
)
|
161
|
+
const a = evaluate(args[0], env)
|
162
|
+
if (typeof a !== 'number')
|
163
|
+
throw new TypeError(
|
164
|
+
`First argument of (${KEYWORDS.REMAINDER_OF_DIVISION}) is not (${
|
165
|
+
RUNTIME_TYPES.NUMBER
|
166
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
167
|
+
KEYWORDS.REMAINDER_OF_DIVISION
|
168
|
+
} ${stringifyArgs(args)})`
|
169
|
+
)
|
170
|
+
const b = evaluate(args[1], env)
|
171
|
+
if (typeof b !== 'number')
|
172
|
+
throw new TypeError(
|
173
|
+
`Second argument of (${KEYWORDS.REMAINDER_OF_DIVISION}) is not (${
|
174
|
+
RUNTIME_TYPES.NUMBER
|
175
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
176
|
+
KEYWORDS.REMAINDER_OF_DIVISION
|
177
|
+
} ${stringifyArgs(args)})`
|
178
|
+
)
|
179
|
+
if (b === 0)
|
180
|
+
throw new TypeError(
|
181
|
+
`Second argument of (${
|
182
|
+
KEYWORDS.REMAINDER_OF_DIVISION
|
183
|
+
}) can't be a 0 (division by 0 is not allowed) but ${LISP.source(
|
184
|
+
args[1]
|
185
|
+
)} is 0\n\n(${KEYWORDS.REMAINDER_OF_DIVISION} ${stringifyArgs(args)})`
|
186
|
+
)
|
187
|
+
|
188
|
+
return a % b
|
189
|
+
},
|
190
|
+
[KEYWORDS.BITWISE_AND]: (args, env) => {
|
191
|
+
if (args.length !== 2)
|
192
|
+
throw new RangeError(
|
193
|
+
`Invalid number of arguments to (${
|
194
|
+
KEYWORDS.BITWISE_AND
|
195
|
+
}) (= 2 required)\n\n(${KEYWORDS.BITWISE_AND} ${stringifyArgs(args)})`
|
196
|
+
)
|
197
|
+
const a = evaluate(args[0], env)
|
198
|
+
if (typeof a !== 'number')
|
199
|
+
throw new TypeError(
|
200
|
+
`First arguments of (${KEYWORDS.BITWISE_AND}) must be a (${
|
201
|
+
RUNTIME_TYPES.NUMBER
|
202
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
203
|
+
KEYWORDS.BITWISE_AND
|
204
|
+
} ${stringifyArgs(args)})`
|
205
|
+
)
|
206
|
+
const b = evaluate(args[1], env)
|
207
|
+
if (typeof b !== 'number')
|
208
|
+
throw new TypeError(
|
209
|
+
`Second arguments of (${KEYWORDS.BITWISE_AND}) must be a (${
|
210
|
+
RUNTIME_TYPES.NUMBER
|
211
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
212
|
+
KEYWORDS.BITWISE_AND
|
213
|
+
} ${stringifyArgs(args)})`
|
214
|
+
)
|
215
|
+
return a & b
|
216
|
+
},
|
217
|
+
[KEYWORDS.BITWISE_NOT]: (args, env) => {
|
218
|
+
if (args.length !== 1)
|
219
|
+
throw new RangeError(
|
220
|
+
`Invalid number of arguments to (${
|
221
|
+
KEYWORDS.BITWISE_NOT
|
222
|
+
}) (= 1 required)\n\n(${KEYWORDS.BITWISE_NOT} ${stringifyArgs(args)})`
|
223
|
+
)
|
224
|
+
const operand = evaluate(args[0], env)
|
225
|
+
if (typeof operand !== 'number')
|
226
|
+
throw new TypeError(
|
227
|
+
`Argument of (${KEYWORDS.BITWISE_NOT}) must be a (${
|
228
|
+
RUNTIME_TYPES.NUMBER
|
229
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
230
|
+
KEYWORDS.BITWISE_NOT
|
231
|
+
} ${stringifyArgs(args)})`
|
232
|
+
)
|
233
|
+
return ~operand
|
234
|
+
},
|
235
|
+
[KEYWORDS.BITWISE_OR]: (args, env) => {
|
236
|
+
if (args.length !== 2)
|
237
|
+
throw new RangeError(
|
238
|
+
`Invalid number of arguments to (${
|
239
|
+
KEYWORDS.BITWISE_OR
|
240
|
+
}) (= 2 required)\n\n(${KEYWORDS.BITWISE_OR} ${stringifyArgs(args)})`
|
241
|
+
)
|
242
|
+
const a = evaluate(args[0], env)
|
243
|
+
if (typeof a !== 'number')
|
244
|
+
throw new TypeError(
|
245
|
+
`First arguments of (${KEYWORDS.BITWISE_OR}) must be a (${
|
246
|
+
RUNTIME_TYPES.NUMBER
|
247
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
248
|
+
KEYWORDS.BITWISE_OR
|
249
|
+
} ${stringifyArgs(args)})`
|
250
|
+
)
|
251
|
+
const b = evaluate(args[1], env)
|
252
|
+
if (typeof b !== 'number')
|
253
|
+
throw new TypeError(
|
254
|
+
`Second arguments of (${KEYWORDS.BITWISE_OR}) must be a (${
|
255
|
+
RUNTIME_TYPES.NUMBER
|
256
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
257
|
+
KEYWORDS.BITWISE_OR
|
258
|
+
} ${stringifyArgs(args)})`
|
259
|
+
)
|
260
|
+
return a | b
|
261
|
+
},
|
262
|
+
[KEYWORDS.BITWISE_XOR]: (args, env) => {
|
263
|
+
if (args.length !== 2)
|
264
|
+
throw new RangeError(
|
265
|
+
`Invalid number of arguments to (${
|
266
|
+
KEYWORDS.BITWISE_XOR
|
267
|
+
}) (= 2 required)\n\n(${KEYWORDS.BITWISE_XOR} ${stringifyArgs(args)})`
|
268
|
+
)
|
269
|
+
const a = evaluate(args[0], env)
|
270
|
+
if (typeof a !== 'number')
|
271
|
+
throw new TypeError(
|
272
|
+
`First arguments of (${KEYWORDS.BITWISE_XOR}) must be a (${
|
273
|
+
RUNTIME_TYPES.NUMBER
|
274
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
275
|
+
KEYWORDS.BITWISE_XOR
|
276
|
+
} ${stringifyArgs(args)})`
|
277
|
+
)
|
278
|
+
const b = evaluate(args[1], env)
|
279
|
+
if (typeof b !== 'number')
|
280
|
+
throw new TypeError(
|
281
|
+
`Second arguments of (${KEYWORDS.BITWISE_XOR}) must be a (${
|
282
|
+
RUNTIME_TYPES.NUMBER
|
283
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
284
|
+
KEYWORDS.BITWISE_XOR
|
285
|
+
} ${stringifyArgs(args)})`
|
286
|
+
)
|
287
|
+
return a ^ b
|
288
|
+
},
|
289
|
+
[KEYWORDS.BITWISE_LEFT_SHIFT]: (args, env) => {
|
290
|
+
if (args.length !== 2)
|
291
|
+
throw new RangeError(
|
292
|
+
`Invalid number of arguments to (${
|
293
|
+
KEYWORDS.BITWISE_LEFT_SHIFT
|
294
|
+
}) (= 2 required)\n\n(${KEYWORDS.BITWISE_LEFT_SHIFT} ${stringifyArgs(
|
295
|
+
args
|
296
|
+
)})`
|
297
|
+
)
|
298
|
+
const a = evaluate(args[0], env)
|
299
|
+
if (typeof a !== 'number')
|
300
|
+
throw new TypeError(
|
301
|
+
`First arguments of (${KEYWORDS.BITWISE_LEFT_SHIFT}) must be a (${
|
302
|
+
RUNTIME_TYPES.NUMBER
|
303
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
304
|
+
KEYWORDS.BITWISE_LEFT_SHIFT
|
305
|
+
} ${stringifyArgs(args)})`
|
306
|
+
)
|
307
|
+
const b = evaluate(args[1], env)
|
308
|
+
if (typeof b !== 'number')
|
309
|
+
throw new TypeError(
|
310
|
+
`Second arguments of (${KEYWORDS.BITWISE_LEFT_SHIFT}) must be a (${
|
311
|
+
RUNTIME_TYPES.NUMBER
|
312
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
313
|
+
KEYWORDS.BITWISE_LEFT_SHIFT
|
314
|
+
} ${stringifyArgs(args)})`
|
315
|
+
)
|
316
|
+
return a << b
|
317
|
+
},
|
318
|
+
[KEYWORDS.BITWISE_RIGHT_SHIFT]: (args, env) => {
|
319
|
+
if (args.length !== 2)
|
320
|
+
throw new RangeError(
|
321
|
+
`Invalid number of arguments to (${
|
322
|
+
KEYWORDS.BITWISE_RIGHT_SHIFT
|
323
|
+
}) (= 2 required)\n\n(${KEYWORDS.BITWISE_RIGHT_SHIFT} ${stringifyArgs(
|
324
|
+
args
|
325
|
+
)})`
|
326
|
+
)
|
327
|
+
const a = evaluate(args[0], env)
|
328
|
+
if (typeof a !== 'number')
|
329
|
+
throw new TypeError(
|
330
|
+
`First arguments of (${KEYWORDS.BITWISE_RIGHT_SHIFT}) must be a (${
|
331
|
+
RUNTIME_TYPES.NUMBER
|
332
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
333
|
+
KEYWORDS.BITWISE_RIGHT_SHIFT
|
334
|
+
} ${stringifyArgs(args)})`
|
335
|
+
)
|
336
|
+
const b = evaluate(args[1], env)
|
337
|
+
if (typeof b !== 'number')
|
338
|
+
throw new TypeError(
|
339
|
+
`Second arguments of (${KEYWORDS.BITWISE_RIGHT_SHIFT}) must be a (${
|
340
|
+
RUNTIME_TYPES.NUMBER
|
341
|
+
}) but ${LISP.source(args[1])} is not\n\n(${
|
342
|
+
KEYWORDS.BITWISE_RIGHT_SHIFT
|
343
|
+
} ${stringifyArgs(args)})`
|
344
|
+
)
|
345
|
+
return a >> b
|
346
|
+
},
|
347
|
+
[KEYWORDS.CREATE_ARRAY]: (args, env) => {
|
348
|
+
return args.length ? args.map((x) => evaluate(x, env)) : []
|
349
|
+
},
|
350
|
+
[KEYWORDS.GET_ARRAY]: (args, env) => {
|
351
|
+
if (args.length !== 2)
|
352
|
+
throw new RangeError(
|
353
|
+
`Invalid number of arguments for (${
|
354
|
+
KEYWORDS.GET_ARRAY
|
355
|
+
}) (= 2 required)\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
356
|
+
)
|
357
|
+
const array = evaluate(args[0], env)
|
358
|
+
if (!Array.isArray(array))
|
359
|
+
throw new TypeError(
|
360
|
+
`First argument of (${KEYWORDS.GET_ARRAY}) must be an (${
|
361
|
+
RUNTIME_TYPES.ARRAY
|
362
|
+
})\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
363
|
+
)
|
364
|
+
if (array.length === 0)
|
365
|
+
throw new RangeError(
|
366
|
+
`First argument of (${KEYWORDS.GET_ARRAY}) is an empty (${
|
367
|
+
RUNTIME_TYPES.ARRAY
|
368
|
+
})\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
369
|
+
)
|
370
|
+
const index = evaluate(args[1], env)
|
371
|
+
if (!Number.isInteger(index) || index < 0)
|
372
|
+
throw new TypeError(
|
373
|
+
`Second argument of (${
|
374
|
+
KEYWORDS.GET_ARRAY
|
375
|
+
}) must be a positive (interger ${
|
376
|
+
RUNTIME_TYPES.NUMBER
|
377
|
+
}) (= i ${index})\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
378
|
+
)
|
379
|
+
if (index > array.length - 1)
|
380
|
+
throw new RangeError(
|
381
|
+
`Second argument of (${KEYWORDS.GET_ARRAY}) is outside of (${
|
382
|
+
RUNTIME_TYPES.ARRAY
|
383
|
+
}) bounds (= i ${index}) expected (and (>= i 0) (< i ${
|
384
|
+
array.length
|
385
|
+
}))\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
386
|
+
)
|
387
|
+
const value = array.at(index)
|
388
|
+
if (value == undefined)
|
389
|
+
throw new RangeError(
|
390
|
+
`Trying to get a null value in (${RUNTIME_TYPES.ARRAY}) at (${
|
391
|
+
KEYWORDS.GET_ARRAY
|
392
|
+
})\n\n(${KEYWORDS.GET_ARRAY} ${stringifyArgs(args)})`
|
393
|
+
)
|
394
|
+
return value
|
395
|
+
},
|
71
396
|
[KEYWORDS.SET_ARRAY]: (args, env) => {
|
397
|
+
if (args.length !== 3)
|
398
|
+
throw new RangeError(
|
399
|
+
`Invalid number of arguments for (${
|
400
|
+
KEYWORDS.SET_ARRAY
|
401
|
+
}) (= 3) required\n\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
|
402
|
+
)
|
72
403
|
const array = evaluate(args[0], env)
|
73
|
-
|
404
|
+
if (!Array.isArray(array))
|
405
|
+
throw new TypeError(
|
406
|
+
`First argument of (${KEYWORDS.SET_ARRAY}) must be an (${
|
407
|
+
RUNTIME_TYPES.ARRAY
|
408
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
409
|
+
KEYWORDS.SET_ARRAY
|
410
|
+
} ${stringifyArgs(args)})`
|
411
|
+
)
|
412
|
+
const index = evaluate(args[1], env)
|
413
|
+
if (!Number.isInteger(index) || index < 0)
|
414
|
+
throw new TypeError(
|
415
|
+
`Second argument of (${KEYWORDS.SET_ARRAY}) must be a positive (${
|
416
|
+
RUNTIME_TYPES.NUMBER
|
417
|
+
} integer) (= i ${index}) but ${LISP.source(args[1])} is not\n\n(${
|
418
|
+
KEYWORDS.SET_ARRAY
|
419
|
+
} ${stringifyArgs(args)})`
|
420
|
+
)
|
421
|
+
if (index > array.length)
|
422
|
+
throw new RangeError(
|
423
|
+
`Second argument of (${KEYWORDS.SET_ARRAY}) is outside of the (${
|
424
|
+
RUNTIME_TYPES.ARRAY
|
425
|
+
}) bounds (${index}) expected (and (>= i 0) (< i ${
|
426
|
+
array.length
|
427
|
+
})) but ${LISP.source(args[1])} is not\n\n(${
|
428
|
+
KEYWORDS.SET_ARRAY
|
429
|
+
} ${stringifyArgs(args)})`
|
430
|
+
)
|
431
|
+
const value = evaluate(args[2], env)
|
432
|
+
if (value == undefined)
|
433
|
+
throw new RangeError(
|
434
|
+
`Trying to set a null value in (${RUNTIME_TYPES.ARRAY}) at (${
|
435
|
+
KEYWORDS.SET_ARRAY
|
436
|
+
})\n\n(${KEYWORDS.SET_ARRAY} ${stringifyArgs(args)})`
|
437
|
+
)
|
438
|
+
array[index] = value
|
74
439
|
return array
|
75
440
|
},
|
76
441
|
[KEYWORDS.POP_ARRAY]: (args, env) => {
|
442
|
+
if (args.length !== 1)
|
443
|
+
throw new RangeError(
|
444
|
+
`Invalid number of arguments for (${
|
445
|
+
KEYWORDS.POP_ARRAY
|
446
|
+
}) (= 1) required\n\n(${KEYWORDS.POP_ARRAY} ${stringifyArgs(args)})`
|
447
|
+
)
|
77
448
|
const array = evaluate(args[0], env)
|
449
|
+
if (!Array.isArray(array))
|
450
|
+
throw new TypeError(
|
451
|
+
`First argument of (${KEYWORDS.POP_ARRAY}) must be an (${
|
452
|
+
RUNTIME_TYPES.ARRAY
|
453
|
+
}) but ${LISP.source(args[0])} is not\n\n(${
|
454
|
+
KEYWORDS.POP_ARRAY
|
455
|
+
} ${stringifyArgs(args)})`
|
456
|
+
)
|
78
457
|
array.pop()
|
79
458
|
return array
|
80
459
|
},
|
460
|
+
[KEYWORDS.ARRAY_LENGTH]: (args, env) => {
|
461
|
+
if (args.length !== 1)
|
462
|
+
throw new RangeError(
|
463
|
+
`Invalid number of arguments for (${
|
464
|
+
KEYWORDS.ARRAY_LENGTH
|
465
|
+
}) (= 1 required)\n\n(${KEYWORDS.ARRAY_LENGTH} ${stringifyArgs(args)})`
|
466
|
+
)
|
467
|
+
const array = evaluate(args[0], env)
|
468
|
+
if (!Array.isArray(array))
|
469
|
+
throw new TypeError(
|
470
|
+
`First argument of (${KEYWORDS.ARRAY_LENGTH}) must be an ${
|
471
|
+
RUNTIME_TYPES.ARRAY
|
472
|
+
} but ${LISP.source(args[0])} is not\n\n(${
|
473
|
+
KEYWORDS.ARRAY_LENGTH
|
474
|
+
} ${stringifyArgs(args)})`
|
475
|
+
)
|
476
|
+
return array.length
|
477
|
+
},
|
478
|
+
[KEYWORDS.IF]: (args, env) => {
|
479
|
+
if (args.length !== 3)
|
480
|
+
throw new RangeError(
|
481
|
+
`Invalid number of arguments for (${
|
482
|
+
KEYWORDS.IF
|
483
|
+
}), expected (= 3) but got ${args.length}\n\n(${
|
484
|
+
KEYWORDS.IF
|
485
|
+
} ${stringifyArgs(args)})`
|
486
|
+
)
|
487
|
+
const condition = evaluate(args[0], env)
|
488
|
+
if (condition !== FALSE && condition !== TRUE)
|
489
|
+
throw new TypeError(
|
490
|
+
`Condition of (${
|
491
|
+
KEYWORDS.IF
|
492
|
+
}) must be ${TRUE} or ${FALSE} but ${LISP.source(args[0])} is not\n\n(${
|
493
|
+
KEYWORDS.IF
|
494
|
+
} ${stringifyArgs(args)})`
|
495
|
+
)
|
496
|
+
return condition ? evaluate(args[1], env) : evaluate(args[2], env)
|
497
|
+
},
|
498
|
+
[KEYWORDS.NOT]: (args, env) => {
|
499
|
+
if (args.length !== 1)
|
500
|
+
throw new RangeError(
|
501
|
+
`Invalid number of arguments for (${KEYWORDS.NOT}) (= 1 required)\n\n(${
|
502
|
+
KEYWORDS.NOT
|
503
|
+
} ${stringifyArgs(args)})`
|
504
|
+
)
|
505
|
+
const operand = evaluate(args[0], env)
|
506
|
+
if (operand !== FALSE && operand !== TRUE)
|
507
|
+
throw new TypeError(
|
508
|
+
`Condition of (${
|
509
|
+
KEYWORDS.NOT
|
510
|
+
}) must be ${TRUE} or ${FALSE} but ${LISP.source(args[0])} is not\n\n(${
|
511
|
+
KEYWORDS.NOT
|
512
|
+
} ${stringifyArgs(args)})`
|
513
|
+
)
|
514
|
+
return +!operand
|
515
|
+
},
|
516
|
+
[KEYWORDS.EQUAL]: (args, env) => {
|
517
|
+
if (args.length !== 2)
|
518
|
+
throw new RangeError(
|
519
|
+
`Invalid number of arguments for (${
|
520
|
+
KEYWORDS.EQUAL
|
521
|
+
}) (= 2 required)\n\n(${KEYWORDS.EQUAL} ${stringifyArgs(args)})`
|
522
|
+
)
|
523
|
+
const a = evaluate(args[0], env)
|
524
|
+
const b = evaluate(args[1], env)
|
525
|
+
if (typeof a !== 'number')
|
526
|
+
throw new TypeError(
|
527
|
+
`First argument of (${KEYWORDS.EQUAL}) must be a ${
|
528
|
+
RUNTIME_TYPES.NUMBER
|
529
|
+
} but ${LISP.source(args[0])} is not\n\n(${
|
530
|
+
KEYWORDS.EQUAL
|
531
|
+
} ${stringifyArgs(args)})`
|
532
|
+
)
|
533
|
+
if (typeof b !== 'number')
|
534
|
+
throw new TypeError(
|
535
|
+
`Second argument of (${KEYWORDS.EQUAL}) must be a ${
|
536
|
+
RUNTIME_TYPES.NUMBER
|
537
|
+
} but ${LISP.source(args[1])} is not\n\n(${
|
538
|
+
KEYWORDS.EQUAL
|
539
|
+
} ${stringifyArgs(args)})`
|
540
|
+
)
|
541
|
+
return +(a === b)
|
542
|
+
},
|
543
|
+
[KEYWORDS.LESS_THAN]: (args, env) => {
|
544
|
+
if (args.length !== 2)
|
545
|
+
throw new RangeError(
|
546
|
+
`Invalid number of arguments for (${
|
547
|
+
KEYWORDS.LESS_THAN
|
548
|
+
}) (= 2 required)\n\n(${KEYWORDS.LESS_THAN} ${stringifyArgs(args)})`
|
549
|
+
)
|
550
|
+
const a = evaluate(args[0], env)
|
551
|
+
const b = evaluate(args[1], env)
|
552
|
+
if (typeof a !== 'number')
|
553
|
+
throw new TypeError(
|
554
|
+
`First argument of (${KEYWORDS.LESS_THAN}) must be a ${
|
555
|
+
RUNTIME_TYPES.NUMBER
|
556
|
+
} but ${LISP.source(args[0])} is not\n\n(${
|
557
|
+
KEYWORDS.LESS_THAN
|
558
|
+
} ${stringifyArgs(args)})`
|
559
|
+
)
|
560
|
+
if (typeof b !== 'number')
|
561
|
+
throw new TypeError(
|
562
|
+
`Second argument of (${KEYWORDS.LESS_THAN}) must be a ${
|
563
|
+
RUNTIME_TYPES.NUMBER
|
564
|
+
} but ${LISP.source(args[1])} is not\n\n(${
|
565
|
+
KEYWORDS.LESS_THAN
|
566
|
+
} ${stringifyArgs(args)})`
|
567
|
+
)
|
568
|
+
return +(a < b)
|
569
|
+
},
|
570
|
+
[KEYWORDS.GREATHER_THAN]: (args, env) => {
|
571
|
+
if (args.length !== 2)
|
572
|
+
throw new RangeError(
|
573
|
+
`Invalid number of arguments for (${
|
574
|
+
KEYWORDS.GREATHER_THAN
|
575
|
+
}) (= 2 required)\n\n(${KEYWORDS.GREATHER_THAN} ${stringifyArgs(args)})`
|
576
|
+
)
|
577
|
+
const a = evaluate(args[0], env)
|
578
|
+
const b = evaluate(args[1], env)
|
579
|
+
if (typeof a !== 'number')
|
580
|
+
throw new TypeError(
|
581
|
+
`First argument of (${KEYWORDS.GREATHER_THAN}) must be a ${
|
582
|
+
RUNTIME_TYPES.NUMBER
|
583
|
+
} but ${LISP.source(args[0])} is not\n\n(${
|
584
|
+
KEYWORDS.GREATHER_THAN
|
585
|
+
} ${stringifyArgs(args)})`
|
586
|
+
)
|
587
|
+
if (typeof b !== 'number')
|
588
|
+
throw new TypeError(
|
589
|
+
`Second argument of (${KEYWORDS.GREATHER_THAN}) must be a ${
|
590
|
+
RUNTIME_TYPES.NUMBER
|
591
|
+
} but ${LISP.source(args[1])} is not\n\n(${
|
592
|
+
KEYWORDS.GREATHER_THAN
|
593
|
+
} ${stringifyArgs(args)})`
|
594
|
+
)
|
595
|
+
return +(a > b)
|
596
|
+
},
|
597
|
+
[KEYWORDS.GREATHER_THAN_OR_EQUAL]: (args, env) => {
|
598
|
+
if (args.length !== 2)
|
599
|
+
throw new RangeError(
|
600
|
+
`Invalid number of arguments for (${
|
601
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL
|
602
|
+
}) (= 2 required)\n\n(${
|
603
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL
|
604
|
+
} ${stringifyArgs(args)})`
|
605
|
+
)
|
606
|
+
const a = evaluate(args[0], env)
|
607
|
+
const b = evaluate(args[1], env)
|
608
|
+
if (typeof a !== 'number')
|
609
|
+
throw new TypeError(
|
610
|
+
`First argument of (${KEYWORDS.GREATHER_THAN_OR_EQUAL}) must be a ${
|
611
|
+
RUNTIME_TYPES.NUMBER
|
612
|
+
} but ${LISP.source(args[0])} is not\n\n(${
|
613
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL
|
614
|
+
} ${stringifyArgs(args)})`
|
615
|
+
)
|
616
|
+
if (typeof b !== 'number')
|
617
|
+
throw new TypeError(
|
618
|
+
`Second argument of (${KEYWORDS.GREATHER_THAN_OR_EQUAL}) must be a ${
|
619
|
+
RUNTIME_TYPES.NUMBER
|
620
|
+
} but ${LISP.source(args[1])} is not\n\n(${
|
621
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL
|
622
|
+
} ${stringifyArgs(args)})`
|
623
|
+
)
|
624
|
+
return +(a >= b)
|
625
|
+
},
|
626
|
+
[KEYWORDS.LESS_THAN_OR_EQUAL]: (args, env) => {
|
627
|
+
if (args.length !== 2)
|
628
|
+
throw new RangeError(
|
629
|
+
`Invalid number of arguments for (${
|
630
|
+
KEYWORDS.LESS_THAN_OR_EQUAL
|
631
|
+
}) (= 2 required)\n\n(${KEYWORDS.LESS_THAN_OR_EQUAL} ${stringifyArgs(
|
632
|
+
args
|
633
|
+
)})`
|
634
|
+
)
|
635
|
+
const a = evaluate(args[0], env)
|
636
|
+
const b = evaluate(args[1], env)
|
637
|
+
if (typeof a !== 'number')
|
638
|
+
throw new TypeError(
|
639
|
+
`First argument of (${KEYWORDS.LESS_THAN_OR_EQUAL}) must be a ${
|
640
|
+
RUNTIME_TYPES.NUMBER
|
641
|
+
} but ${LISP.source(args[0])} is not\n\n(${
|
642
|
+
KEYWORDS.LESS_THAN_OR_EQUAL
|
643
|
+
} ${stringifyArgs(args)})`
|
644
|
+
)
|
645
|
+
if (typeof b !== 'number')
|
646
|
+
throw new TypeError(
|
647
|
+
`Second argument of (${KEYWORDS.LESS_THAN_OR_EQUAL}) must be a ${
|
648
|
+
RUNTIME_TYPES.NUMBER
|
649
|
+
} but ${LISP.source(args[1])} is not\n\n(${
|
650
|
+
KEYWORDS.LESS_THAN_OR_EQUAL
|
651
|
+
} ${stringifyArgs(args)})`
|
652
|
+
)
|
653
|
+
return +(a <= b)
|
654
|
+
},
|
655
|
+
[KEYWORDS.AND]: (args, env) => {
|
656
|
+
if (args.length !== 2)
|
657
|
+
throw new RangeError(
|
658
|
+
`Invalid number of arguments for (${KEYWORDS.AND}) (= 2 required)\n\n(${
|
659
|
+
KEYWORDS.AND
|
660
|
+
} ${stringifyArgs(args)})`
|
661
|
+
)
|
662
|
+
const a = evaluate(args[0], env)
|
663
|
+
if (a !== FALSE && a !== TRUE)
|
664
|
+
throw new TypeError(
|
665
|
+
`Condition of (${
|
666
|
+
KEYWORDS.AND
|
667
|
+
}) must be ${TRUE} or ${FALSE} but got\n\n(${
|
668
|
+
KEYWORDS.AND
|
669
|
+
} ${stringifyArgs(args)})`
|
670
|
+
)
|
671
|
+
if (!a) return FALSE
|
672
|
+
const b = evaluate(args[1], env)
|
673
|
+
if (b !== FALSE && b !== TRUE)
|
674
|
+
throw new TypeError(
|
675
|
+
`Condition of (${
|
676
|
+
KEYWORDS.AND
|
677
|
+
}) must be ${TRUE} or ${FALSE} but got\n\n(${
|
678
|
+
KEYWORDS.AND
|
679
|
+
} ${stringifyArgs(args)})`
|
680
|
+
)
|
681
|
+
return b
|
682
|
+
},
|
683
|
+
[KEYWORDS.OR]: (args, env) => {
|
684
|
+
if (args.length !== 2)
|
685
|
+
throw new RangeError(
|
686
|
+
`Invalid number of arguments for (${KEYWORDS.OR}) (= 2 required)\n\n(${
|
687
|
+
KEYWORDS.OR
|
688
|
+
} ${stringifyArgs(args)})`
|
689
|
+
)
|
690
|
+
const a = evaluate(args[0], env)
|
691
|
+
if (a !== FALSE && a !== TRUE)
|
692
|
+
throw new TypeError(
|
693
|
+
`Condition of (${
|
694
|
+
KEYWORDS.OR
|
695
|
+
}) must be ${TRUE} or ${FALSE} but got\n\n(${
|
696
|
+
KEYWORDS.OR
|
697
|
+
} ${stringifyArgs(args)})`
|
698
|
+
)
|
699
|
+
if (a) return TRUE
|
700
|
+
const b = evaluate(args[1], env)
|
701
|
+
if (b !== FALSE && b !== TRUE)
|
702
|
+
throw new TypeError(
|
703
|
+
`Condition of (${
|
704
|
+
KEYWORDS.OR
|
705
|
+
}) must be ${TRUE} or ${FALSE} but got\n\n(${
|
706
|
+
KEYWORDS.OR
|
707
|
+
} ${stringifyArgs(args)})`
|
708
|
+
)
|
709
|
+
return b
|
710
|
+
},
|
711
|
+
[KEYWORDS.DEFINE_VARIABLE]: (args, env) => {
|
712
|
+
if (args.length !== 2)
|
713
|
+
throw new RangeError(
|
714
|
+
`Invalid number of arguments to (${
|
715
|
+
KEYWORDS.DEFINE_VARIABLE
|
716
|
+
}) (= 2 required)\n\n(${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(
|
717
|
+
args
|
718
|
+
)})`
|
719
|
+
)
|
720
|
+
const word = args[0]
|
721
|
+
const type = word[TYPE]
|
722
|
+
const name = word[VALUE]
|
723
|
+
if (type !== WORD)
|
724
|
+
throw new SyntaxError(
|
725
|
+
`First argument of (${KEYWORDS.DEFINE_VARIABLE}) must be word but got ${
|
726
|
+
TYPES[type]
|
727
|
+
}\n\n(${KEYWORDS.DEFINE_VARIABLE} ${stringifyArgs(args)})`
|
728
|
+
)
|
729
|
+
else if (isForbiddenVariableName(name))
|
730
|
+
throw new ReferenceError(
|
731
|
+
`Variable name ${name} is forbidden \n\n(${
|
732
|
+
KEYWORDS.DEFINE_VARIABLE
|
733
|
+
} ${stringifyArgs(args)})`
|
734
|
+
)
|
735
|
+
env[name] = evaluate(args[1], env)
|
736
|
+
return env[name]
|
737
|
+
},
|
81
738
|
[KEYWORDS.ANONYMOUS_FUNCTION]: (args, env) => {
|
739
|
+
if (!args.length)
|
740
|
+
throw new RangeError(
|
741
|
+
`At lest one argument (the body) is required for (${KEYWORDS.ANONYMOUS_FUNCTION})`
|
742
|
+
)
|
82
743
|
const params = args.slice(0, -1)
|
83
|
-
|
744
|
+
const body = args.at(-1)
|
745
|
+
return (props = [], scope, name) => {
|
746
|
+
if (props.length !== params.length)
|
747
|
+
throw new RangeError(
|
748
|
+
`Incorrect number of arguments for (${KEYWORDS.ANONYMOUS_FUNCTION}${
|
749
|
+
name ? ` ${name}` : ''
|
750
|
+
}) are provided (expects ${params.length} but got ${
|
751
|
+
props.length
|
752
|
+
})\n\n${
|
753
|
+
name
|
754
|
+
? `(${name} ${stringifyArgs(params)})`
|
755
|
+
: `(${KEYWORDS.ANONYMOUS_FUNCTION} ${stringifyArgs(params)})`
|
756
|
+
}`
|
757
|
+
)
|
84
758
|
const localEnv = Object.create(env)
|
85
|
-
for (let i = 0; i < props.length; ++i)
|
86
|
-
|
87
|
-
|
759
|
+
for (let i = 0; i < props.length; ++i) {
|
760
|
+
const value = evaluate(props[i], scope)
|
761
|
+
localEnv[params[i][VALUE]] = value
|
762
|
+
}
|
763
|
+
return evaluate(body, localEnv)
|
88
764
|
}
|
89
765
|
},
|
766
|
+
[KEYWORDS.CALL_FUNCTION]: (args, env) => {
|
767
|
+
if (!args.length)
|
768
|
+
throw new RangeError(
|
769
|
+
`Invalid number of arguments to (${
|
770
|
+
KEYWORDS.CALL_FUNCTION
|
771
|
+
}) (>= 1 required)\n\n(${KEYWORDS.CALL_FUNCTION} ${stringifyArgs(
|
772
|
+
args
|
773
|
+
)})`
|
774
|
+
)
|
775
|
+
const first = args.at(-1)
|
776
|
+
if (first[TYPE] === WORD && first[VALUE] in keywords)
|
777
|
+
throw new TypeError(
|
778
|
+
`Preceeding arguments of (${
|
779
|
+
KEYWORDS.CALL_FUNCTION
|
780
|
+
}) must not be an reserved word\n\n(${
|
781
|
+
KEYWORDS.CALL_FUNCTION
|
782
|
+
} ${stringifyArgs(args)})`
|
783
|
+
)
|
784
|
+
const apply = evaluate(first, env)
|
785
|
+
if (typeof apply !== 'function')
|
786
|
+
throw new TypeError(
|
787
|
+
`Last argument of (${KEYWORDS.CALL_FUNCTION}) must be a (${
|
788
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
789
|
+
}) but got ${LISP.stringify(apply)}\n\n(${
|
790
|
+
KEYWORDS.CALL_FUNCTION
|
791
|
+
} ${stringifyArgs(args)})`
|
792
|
+
)
|
793
|
+
|
794
|
+
return apply(args.slice(0, -1), env)
|
795
|
+
},
|
796
|
+
[KEYWORDS.BLOCK]: (args, env) => {
|
797
|
+
if (!args.length)
|
798
|
+
throw new RangeError(
|
799
|
+
`Invalid number of arguments to (${
|
800
|
+
KEYWORDS.BLOCK
|
801
|
+
}) (>= 1 required)\n\n(${KEYWORDS.BLOCK} ${stringifyArgs(args)})`
|
802
|
+
)
|
803
|
+
let out = FALSE
|
804
|
+
for (const exp of args) out = evaluate(exp, env)
|
805
|
+
return out
|
806
|
+
},
|
807
|
+
[KEYWORDS.IS_ATOM]: (args, env) => {
|
808
|
+
if (args.length !== 1)
|
809
|
+
throw new RangeError(
|
810
|
+
`Invalid number of arguments for (${
|
811
|
+
KEYWORDS.IS_ATOM
|
812
|
+
}) (= 1 required)\n\n(${KEYWORDS.IS_ATOM} ${stringifyArgs(args)})`
|
813
|
+
)
|
814
|
+
return +(typeof evaluate(args[0], env) === 'number')
|
815
|
+
},
|
816
|
+
[KEYWORDS.IS_LAMBDA]: (args, env) => {
|
817
|
+
if (args.length !== 1)
|
818
|
+
throw new RangeError(
|
819
|
+
`Invalid number of arguments for (${
|
820
|
+
KEYWORDS.IS_LAMBDA
|
821
|
+
}) (= 1 required)\n\n(${KEYWORDS.IS_LAMBDA} ${stringifyArgs(args)})`
|
822
|
+
)
|
823
|
+
return +(typeof evaluate(args[0], env) === 'function')
|
824
|
+
},
|
90
825
|
// Only for type checking
|
91
826
|
[STATIC_TYPES.UNKNOWN]: (args, env) => evaluate(args[0], env),
|
92
827
|
[STATIC_TYPES.ANY]: (args, env) => evaluate(args[0], env),
|
@@ -126,7 +861,7 @@ const evaluate = (exp, env = keywords) => {
|
|
126
861
|
// typeof res === 'function' ? '(lambda)' : serialise(res)
|
127
862
|
// }\x1b[0m`
|
128
863
|
// )
|
129
|
-
const out = typeof res === 'function' ? '(lambda)' : serialise(res)
|
864
|
+
const out = typeof res === 'function' ? '(lambda)' : LISP.serialise(res)
|
130
865
|
if (debugStack.at(-1)?.result !== out)
|
131
866
|
debugStack.push({
|
132
867
|
function: value,
|
@@ -163,3 +898,294 @@ export const startDebug = (ast, speed = 250, start, end) => {
|
|
163
898
|
}
|
164
899
|
return stack
|
165
900
|
}
|
901
|
+
|
902
|
+
// const types = typeCheck(std[0], withCtxTypes(definedTypes(stdT)))[1]
|
903
|
+
const __debugStack__ = []
|
904
|
+
export const debug = (ast, checkTypes = true, userDefinedTypes) => {
|
905
|
+
let types = new Map()
|
906
|
+
const debugEnv = {
|
907
|
+
...keywords,
|
908
|
+
[STATIC_TYPES.ABSTRACTION]: (args, env) => {
|
909
|
+
const T = evaluate(args[0], env)
|
910
|
+
const t = typeof T
|
911
|
+
if (t !== 'function')
|
912
|
+
throw new TypeError(
|
913
|
+
`Argument of (${STATIC_TYPES.ABSTRACTION}) must be an (${
|
914
|
+
RUNTIME_TYPES.LAMBDA
|
915
|
+
}) but got something else (${
|
916
|
+
STATIC_TYPES.ABSTRACTION
|
917
|
+
} ${stringifyArgs(args)})`
|
918
|
+
)
|
919
|
+
return T
|
920
|
+
},
|
921
|
+
[STATIC_TYPES.ATOM]: (args, env) => {
|
922
|
+
const T = evaluate(args[0], env)
|
923
|
+
const t = typeof T
|
924
|
+
if (t !== 'number')
|
925
|
+
throw new TypeError(
|
926
|
+
`Argument of (${STATIC_TYPES.ATOM}) must be an (${
|
927
|
+
RUNTIME_TYPES.NUMBER
|
928
|
+
}) but got something else (${STATIC_TYPES.ATOM} ${stringifyArgs(
|
929
|
+
args
|
930
|
+
)})`
|
931
|
+
)
|
932
|
+
return T
|
933
|
+
},
|
934
|
+
[STATIC_TYPES.COLLECTION]: (args, env) => {
|
935
|
+
const T = evaluate(args[0], env)
|
936
|
+
if (!Array.isArray(T))
|
937
|
+
throw new TypeError(
|
938
|
+
`Argument of (${STATIC_TYPES.COLLECTION}) must be an (${
|
939
|
+
RUNTIME_TYPES.ARRAY
|
940
|
+
}) but got something else (${STATIC_TYPES.COLLECTION} ${stringifyArgs(
|
941
|
+
args
|
942
|
+
)})`
|
943
|
+
)
|
944
|
+
return T
|
945
|
+
},
|
946
|
+
[DEBUG.TYPE_SIGNATURE]: (args, env) => {
|
947
|
+
if (args.length !== 2)
|
948
|
+
throw new RangeError(
|
949
|
+
`Invalid number of arguments to (${DEBUG.TYPE_SIGNATURE}) (= 1) (${
|
950
|
+
DEBUG.TYPE_SIGNATURE
|
951
|
+
} ${stringifyArgs(args)})`
|
952
|
+
)
|
953
|
+
const name =
|
954
|
+
Array.isArray(args[0]) && args[0][0][VALUE] === DEBUG.STRING
|
955
|
+
? args[0][1]
|
956
|
+
.slice(1)
|
957
|
+
.map((x) => String.fromCharCode(x[VALUE]))
|
958
|
+
.join('')
|
959
|
+
: args[0][VALUE]
|
960
|
+
const option = args[1][VALUE]
|
961
|
+
const wildcard = name === '*'
|
962
|
+
if (option === 'Scope') {
|
963
|
+
if (wildcard) {
|
964
|
+
return [...types.entries()]
|
965
|
+
.sort((a, b) => a[0].localeCompare(b[0]))
|
966
|
+
.map(([k, v]) => `${k}\n${v()}`)
|
967
|
+
.join('\n\n')
|
968
|
+
}
|
969
|
+
const t = types.get(`; 1 ${name}`)
|
970
|
+
return t ? t() : ''
|
971
|
+
} else if (option === 'Search') {
|
972
|
+
return [...types.entries()]
|
973
|
+
.filter((x) => x[0].includes(name))
|
974
|
+
.sort((a, b) => a[0].localeCompare(b[0]))
|
975
|
+
.map(([k, v]) => `${k}\n${v()}`)
|
976
|
+
.join('\n\n')
|
977
|
+
} else if (option === 'Special') {
|
978
|
+
return formatType(name, SPECIAL_FORM_TYPES)
|
979
|
+
} else if (option === 'Type') {
|
980
|
+
const [from, to] = name.split(KEYWORDS.BLOCK).map((x) => x.trim())
|
981
|
+
return [...types.entries()]
|
982
|
+
.filter(([k, v]) => {
|
983
|
+
const T = v()
|
984
|
+
if (T && T.includes(KEYWORDS.BLOCK)) {
|
985
|
+
const [left, right] = T.split(KEYWORDS.BLOCK).map((x) => x.trim())
|
986
|
+
return left.includes(from) && right.includes(to)
|
987
|
+
}
|
988
|
+
})
|
989
|
+
.sort((a, b) => a[0].length - b[0].length)
|
990
|
+
.map(([k, v]) => `${k}\n${v()}`)
|
991
|
+
.join('\n\n')
|
992
|
+
} else if (option === 'Library') {
|
993
|
+
types = typeCheck(std[0], withCtxTypes(definedTypes(stdT)))[1]
|
994
|
+
const matches = wildcard
|
995
|
+
? [...types.entries()]
|
996
|
+
: [...types.entries()].filter(([k, v]) => v().includes(name))
|
997
|
+
return matches
|
998
|
+
.sort((a, b) => a[0].length - b[0].length)
|
999
|
+
.map(([k, v]) => `${k}\n${v()}`)
|
1000
|
+
.join('\n\n')
|
1001
|
+
} else {
|
1002
|
+
return ''
|
1003
|
+
}
|
1004
|
+
},
|
1005
|
+
[DEBUG.SIGNATURE]: (args, env) => {
|
1006
|
+
const name =
|
1007
|
+
Array.isArray(args[0]) && args[0][0][VALUE] === DEBUG.STRING
|
1008
|
+
? args[0][1]
|
1009
|
+
.slice(1)
|
1010
|
+
.map((x) => String.fromCharCode(x[VALUE]))
|
1011
|
+
.join('')
|
1012
|
+
: args[0][VALUE]
|
1013
|
+
const signatures =
|
1014
|
+
args.length === 0
|
1015
|
+
? std[0][1][1].slice(1)
|
1016
|
+
: std[0][1][1].filter(
|
1017
|
+
(x) =>
|
1018
|
+
x[0][TYPE] === APPLY &&
|
1019
|
+
x[0][VALUE] === KEYWORDS.DEFINE_VARIABLE &&
|
1020
|
+
x[1][TYPE] === WORD &&
|
1021
|
+
x[1][VALUE].toString().includes(name)
|
1022
|
+
)
|
1023
|
+
return signatures.length === 0
|
1024
|
+
? 'Not defined in library'
|
1025
|
+
: signatures.map(LISP.source).join('\n\n')
|
1026
|
+
},
|
1027
|
+
[DEBUG.STRING]: (args, env) => {
|
1028
|
+
if (args.length !== 1)
|
1029
|
+
throw new RangeError(
|
1030
|
+
`Invalid number of arguments to (${DEBUG.STRING}) (= 1) (${
|
1031
|
+
DEBUG.STRING
|
1032
|
+
} but got (${args.length}) ${stringifyArgs(args)})`
|
1033
|
+
)
|
1034
|
+
const expression = evaluate(args[0], env)
|
1035
|
+
if (!Array.isArray(expression))
|
1036
|
+
throw new TypeError(
|
1037
|
+
`Argument of (${DEBUG.STRING}) must be an (${
|
1038
|
+
RUNTIME_TYPES.ARRAY
|
1039
|
+
}) but got (${expression}) (${DEBUG.STRING} ${stringifyArgs(args)})`
|
1040
|
+
)
|
1041
|
+
return `"${expression.map((x) => String.fromCharCode(x)).join('')}"`
|
1042
|
+
},
|
1043
|
+
[DEBUG.UNQUOTED_STRING]: (args, env) => {
|
1044
|
+
if (args.length !== 1)
|
1045
|
+
throw new RangeError(
|
1046
|
+
`Invalid number of arguments to (${DEBUG.UNQUOTED_STRING}) (= 1) (${
|
1047
|
+
DEBUG.UNQUOTED_STRING
|
1048
|
+
} but got (${args.length}) ${stringifyArgs(args)})`
|
1049
|
+
)
|
1050
|
+
const expression = evaluate(args[0], env)
|
1051
|
+
if (!Array.isArray(expression))
|
1052
|
+
throw new TypeError(
|
1053
|
+
`Argument of (${DEBUG.UNQUOTED_STRING}) must be an (${
|
1054
|
+
RUNTIME_TYPES.ARRAY
|
1055
|
+
}) but got (${expression}) (${DEBUG.UNQUOTED_STRING} ${stringifyArgs(
|
1056
|
+
args
|
1057
|
+
)})`
|
1058
|
+
)
|
1059
|
+
return `${expression.map((x) => String.fromCharCode(x)).join('')}`
|
1060
|
+
},
|
1061
|
+
[DEBUG.LOG]: (args, env) => {
|
1062
|
+
if (args.length !== 1 && args.length !== 2)
|
1063
|
+
throw new RangeError(
|
1064
|
+
`Invalid number of arguments to (${DEBUG.LOG}) (or (= 1) (= 2)) (${
|
1065
|
+
DEBUG.LOG
|
1066
|
+
} ${stringifyArgs(args)})`
|
1067
|
+
)
|
1068
|
+
const expression = evaluate(args[0], env)
|
1069
|
+
if (args.length === 2) {
|
1070
|
+
const option = evaluate(args[1], env)
|
1071
|
+
if (!Array.isArray(option)) {
|
1072
|
+
throw new TypeError(
|
1073
|
+
`Second argument of (${DEBUG.LOG}) must be an (${
|
1074
|
+
RUNTIME_TYPES.ARRAY
|
1075
|
+
}) but got (${expression}) (${DEBUG.LOG} ${stringifyArgs(args)})`
|
1076
|
+
)
|
1077
|
+
}
|
1078
|
+
const type = option.map((x) => String.fromCharCode(x)).join('')
|
1079
|
+
switch (type) {
|
1080
|
+
case 'string':
|
1081
|
+
case 'str':
|
1082
|
+
{
|
1083
|
+
if (!Array.isArray(expression))
|
1084
|
+
throw new TypeError(
|
1085
|
+
`Argument of (${DEBUG.LOG}) must be an (${
|
1086
|
+
RUNTIME_TYPES.ARRAY
|
1087
|
+
}) in the case ${type} but got (${expression}) (${
|
1088
|
+
DEBUG.LOG
|
1089
|
+
} ${stringifyArgs(args)})`
|
1090
|
+
)
|
1091
|
+
console.log(
|
1092
|
+
expression.map((x) => String.fromCharCode(x)).join('')
|
1093
|
+
)
|
1094
|
+
}
|
1095
|
+
break
|
1096
|
+
case 'char':
|
1097
|
+
case 'ch':
|
1098
|
+
{
|
1099
|
+
if (typeof expression !== 'number')
|
1100
|
+
throw new TypeError(
|
1101
|
+
`Argument argument of (${DEBUG.LOG}) must be a (${
|
1102
|
+
RUNTIME_TYPES.NUMBER
|
1103
|
+
}) in the case ${type} but got (${expression}) (${
|
1104
|
+
DEBUG.LOG
|
1105
|
+
} ${stringifyArgs(args)})`
|
1106
|
+
)
|
1107
|
+
console.log(String.fromCharCode(expression))
|
1108
|
+
}
|
1109
|
+
|
1110
|
+
break
|
1111
|
+
case '*':
|
1112
|
+
console.log(expression)
|
1113
|
+
break
|
1114
|
+
case '!':
|
1115
|
+
__debugStack__.push(structuredClone(expression))
|
1116
|
+
break
|
1117
|
+
default:
|
1118
|
+
throw new TypeError(
|
1119
|
+
`Invalid option to (${DEBUG.LOG}) got ${option} ${stringifyArgs(
|
1120
|
+
args
|
1121
|
+
)})`
|
1122
|
+
)
|
1123
|
+
}
|
1124
|
+
} else console.log(expression)
|
1125
|
+
return expression
|
1126
|
+
}
|
1127
|
+
}
|
1128
|
+
try {
|
1129
|
+
types = checkTypes
|
1130
|
+
? typeCheck(
|
1131
|
+
ast,
|
1132
|
+
withCtxTypes(
|
1133
|
+
userDefinedTypes
|
1134
|
+
? {
|
1135
|
+
...definedTypes(filteredDefinedTypes(ast, std, stdT)),
|
1136
|
+
...definedTypes(LISP.parse(removeNoCode(userDefinedTypes)))
|
1137
|
+
}
|
1138
|
+
: definedTypes(filteredDefinedTypes(ast, std, stdT))
|
1139
|
+
)
|
1140
|
+
)[1]
|
1141
|
+
: new Map()
|
1142
|
+
const evaluated = evaluate(enhance(ast), debugEnv)
|
1143
|
+
const exp = ast.at(-1).at(-1).at(-1)
|
1144
|
+
const [head, ...rest] = isLeaf(exp) ? [exp] : exp
|
1145
|
+
let type = ''
|
1146
|
+
switch (head[TYPE]) {
|
1147
|
+
case ATOM:
|
1148
|
+
type = STATIC_TYPES.ATOM
|
1149
|
+
break
|
1150
|
+
case WORD:
|
1151
|
+
case APPLY:
|
1152
|
+
switch (head[VALUE]) {
|
1153
|
+
case DEBUG.TYPE_SIGNATURE:
|
1154
|
+
break
|
1155
|
+
case KEYWORDS.DEFINE_VARIABLE:
|
1156
|
+
type = debugEnv[DEBUG.TYPE_SIGNATURE]([rest[0], [WORD, 'Scope']])
|
1157
|
+
break
|
1158
|
+
default:
|
1159
|
+
if (SPECIAL_FORMS_SET.has(head[VALUE])) {
|
1160
|
+
// type = debugEnv[DEBUG.TYPE_SIGNATURE]([head, [WORD, 'Special']])
|
1161
|
+
type = `${debugEnv[DEBUG.TYPE_SIGNATURE]([
|
1162
|
+
head,
|
1163
|
+
[WORD, 'Special']
|
1164
|
+
])}`
|
1165
|
+
} else
|
1166
|
+
type = `${debugEnv[DEBUG.TYPE_SIGNATURE]([
|
1167
|
+
head,
|
1168
|
+
[WORD, 'Scope']
|
1169
|
+
])}`
|
1170
|
+
break
|
1171
|
+
}
|
1172
|
+
|
1173
|
+
break
|
1174
|
+
}
|
1175
|
+
type = type.split('\n').pop()
|
1176
|
+
return {
|
1177
|
+
type,
|
1178
|
+
evaluated,
|
1179
|
+
error: null
|
1180
|
+
}
|
1181
|
+
} catch (error) {
|
1182
|
+
// console.log(error)
|
1183
|
+
return {
|
1184
|
+
type: null,
|
1185
|
+
evaluated: null,
|
1186
|
+
error: {
|
1187
|
+
message: error.message
|
1188
|
+
}
|
1189
|
+
}
|
1190
|
+
}
|
1191
|
+
}
|
package/src/keywords.js
CHANGED
package/src/parser.js
CHANGED
@@ -42,6 +42,15 @@ export const LISP = {
|
|
42
42
|
.join(' ')})`
|
43
43
|
else return array
|
44
44
|
},
|
45
|
+
serialise: (arg) => {
|
46
|
+
if (typeof arg === 'number' || typeof arg === 'string')
|
47
|
+
return arg.toString()
|
48
|
+
else if (Array.isArray(arg))
|
49
|
+
return arg.length
|
50
|
+
? `[${arg.map((a) => LISP.serialise(a)).join(' ')}]`
|
51
|
+
: '[]'
|
52
|
+
else return '(lambda)'
|
53
|
+
},
|
45
54
|
json: (item) => {
|
46
55
|
if (item === null) return 0
|
47
56
|
else if (typeof item === 'boolean') return item
|
package/src/types.js
CHANGED
@@ -464,24 +464,6 @@ export const SPECIAL_FORM_TYPES = {
|
|
464
464
|
[RETURNS]: [UNKNOWN]
|
465
465
|
}
|
466
466
|
},
|
467
|
-
[DEBUG.LIST_THEMES]: {
|
468
|
-
[STATS]: {
|
469
|
-
[TYPE_PROP]: [APPLY],
|
470
|
-
[SIGNATURE]: DEBUG.LIST_THEMES,
|
471
|
-
retried: Infinity,
|
472
|
-
[ARG_COUNT]: VARIADIC,
|
473
|
-
[RETURNS]: [UNKNOWN]
|
474
|
-
}
|
475
|
-
},
|
476
|
-
[DEBUG.SET_THEME]: {
|
477
|
-
[STATS]: {
|
478
|
-
[TYPE_PROP]: [APPLY],
|
479
|
-
[SIGNATURE]: DEBUG.SET_THEME,
|
480
|
-
retried: Infinity,
|
481
|
-
[ARG_COUNT]: VARIADIC,
|
482
|
-
[RETURNS]: [UNKNOWN]
|
483
|
-
}
|
484
|
-
},
|
485
467
|
[KEYWORDS.BLOCK]: {
|
486
468
|
[STATS]: {
|
487
469
|
[TYPE_PROP]: [APPLY],
|
package/src/utils.js
CHANGED
@@ -26,7 +26,7 @@ import {
|
|
26
26
|
withCtxTypes
|
27
27
|
} from './types.js'
|
28
28
|
import { compile } from './compiler.js'
|
29
|
-
import { startDebug } from './debugger.js'
|
29
|
+
import { debugStackToString, startDebug, debug } from './debugger.js'
|
30
30
|
export const logError = (error) =>
|
31
31
|
console.log('\x1b[31m', `\n${error}\n`, '\x1b[0m')
|
32
32
|
export const logSuccess = (output) => console.log('\x1b[32m', output, '\x1b[0m')
|
@@ -366,7 +366,9 @@ export const isInputVariable = (x) =>
|
|
366
366
|
x[1][VALUE] === 'INPUT'
|
367
367
|
|
368
368
|
export const UTILS = {
|
369
|
+
debug,
|
369
370
|
startDebug,
|
371
|
+
debugStackToString,
|
370
372
|
handleUnbalancedQuotes,
|
371
373
|
handleUnbalancedParens,
|
372
374
|
logError,
|