@weborigami/language 0.3.3-jse.2 → 0.3.3-jse.3
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/main.js +2 -0
- package/package.json +3 -3
- package/src/compiler/compile.js +8 -2
- package/src/compiler/optimize.js +147 -93
- package/src/compiler/origami.pegjs +74 -60
- package/src/compiler/parse.js +946 -766
- package/src/compiler/parserHelpers.js +148 -48
- package/src/runtime/HandleExtensionsTransform.js +10 -1
- package/src/runtime/evaluate.js +28 -35
- package/src/runtime/expressionObject.js +4 -4
- package/src/runtime/getHandlers.js +10 -0
- package/src/runtime/handlers.js +14 -53
- package/src/runtime/jsGlobals.js +99 -0
- package/src/runtime/mergeTrees.js +0 -5
- package/src/runtime/ops.js +69 -148
- package/src/runtime/symbols.js +1 -0
- package/test/compiler/codeHelpers.js +3 -1
- package/test/compiler/compile.test.js +52 -27
- package/test/compiler/optimize.test.js +92 -23
- package/test/compiler/parse.test.js +480 -366
- package/test/runtime/evaluate.test.js +4 -20
- package/test/runtime/expressionObject.test.js +5 -4
- package/test/runtime/handlers.test.js +19 -10
- package/test/runtime/mergeTrees.test.js +0 -5
- package/test/runtime/ops.test.js +94 -82
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
3
|
import { parse } from "../../src/compiler/parse.js";
|
|
4
|
-
import {
|
|
4
|
+
import { markers } from "../../src/compiler/parserHelpers.js";
|
|
5
5
|
import * as ops from "../../src/runtime/ops.js";
|
|
6
6
|
import { assertCodeEqual } from "./codeHelpers.js";
|
|
7
7
|
|
|
@@ -19,44 +19,61 @@ describe("Origami parser", () => {
|
|
|
19
19
|
]);
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
[
|
|
45
|
-
|
|
22
|
+
describe("angleBracketLiteral", () => {
|
|
23
|
+
test("with path", () => {
|
|
24
|
+
assertParse(
|
|
25
|
+
"angleBracketLiteral",
|
|
26
|
+
"<index.html>",
|
|
27
|
+
[[ops.scope], [ops.literal, "index.html"]],
|
|
28
|
+
"jse"
|
|
29
|
+
);
|
|
30
|
+
assertParse(
|
|
31
|
+
"angleBracketLiteral",
|
|
32
|
+
"<foo/bar/baz>",
|
|
33
|
+
[
|
|
34
|
+
[ops.scope],
|
|
35
|
+
[ops.literal, "foo/"],
|
|
36
|
+
[ops.literal, "bar/"],
|
|
37
|
+
[ops.literal, "baz"],
|
|
38
|
+
],
|
|
39
|
+
"jse"
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("root directory", () => {
|
|
44
|
+
assertParse("angleBracketLiteral", "</>", [ops.rootDirectory]);
|
|
45
|
+
assertParse("angleBracketLiteral", "</etc/passwd>", [
|
|
46
|
+
[ops.rootDirectory],
|
|
47
|
+
[ops.literal, "etc/"],
|
|
48
|
+
[ops.literal, "passwd"],
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("home directory", () => {
|
|
53
|
+
assertParse("angleBracketLiteral", "<~>", [ops.homeDirectory]);
|
|
54
|
+
assertParse("angleBracketLiteral", "<~/.bash_profile>", [
|
|
55
|
+
[ops.homeDirectory],
|
|
56
|
+
[ops.literal, ".bash_profile"],
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("with protocol URL", () => {
|
|
61
|
+
assertParse("angleBracketLiteral", "<files:src/assets>", [
|
|
62
|
+
[markers.global, "files:"],
|
|
46
63
|
[ops.literal, "src/"],
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
);
|
|
64
|
+
[ops.literal, "assets"],
|
|
65
|
+
]);
|
|
66
|
+
assertParse(
|
|
67
|
+
"angleBracketLiteral",
|
|
68
|
+
"<https://example.com/data.yaml>",
|
|
69
|
+
[
|
|
70
|
+
[markers.global, "https:"],
|
|
71
|
+
[ops.literal, "example.com/"],
|
|
72
|
+
[ops.literal, "data.yaml"],
|
|
73
|
+
],
|
|
74
|
+
"jse"
|
|
75
|
+
);
|
|
76
|
+
});
|
|
60
77
|
});
|
|
61
78
|
|
|
62
79
|
test("arrayLiteral", () => {
|
|
@@ -81,7 +98,7 @@ describe("Origami parser", () => {
|
|
|
81
98
|
[ops.literal, 4],
|
|
82
99
|
]);
|
|
83
100
|
assertParse("arrayLiteral", "[ 1, ...[2, 3]]", [
|
|
84
|
-
ops.
|
|
101
|
+
ops.flat,
|
|
85
102
|
[ops.array, [ops.literal, 1]],
|
|
86
103
|
[ops.array, [ops.literal, 2], [ops.literal, 3]],
|
|
87
104
|
]);
|
|
@@ -100,12 +117,12 @@ describe("Origami parser", () => {
|
|
|
100
117
|
assertParse("arrowFunction", "() => foo", [
|
|
101
118
|
ops.lambda,
|
|
102
119
|
[],
|
|
103
|
-
[ops.
|
|
120
|
+
[markers.reference, [ops.literal, "foo"]],
|
|
104
121
|
]);
|
|
105
122
|
assertParse("arrowFunction", "x => y", [
|
|
106
123
|
ops.lambda,
|
|
107
124
|
[[ops.literal, "x"]],
|
|
108
|
-
[ops.
|
|
125
|
+
[markers.reference, [ops.literal, "y"]],
|
|
109
126
|
]);
|
|
110
127
|
assertParse("arrowFunction", "(a, b, c) ⇒ fn(a, b, c)", [
|
|
111
128
|
ops.lambda,
|
|
@@ -115,10 +132,10 @@ describe("Origami parser", () => {
|
|
|
115
132
|
[ops.literal, "c"],
|
|
116
133
|
],
|
|
117
134
|
[
|
|
118
|
-
[
|
|
119
|
-
[ops.
|
|
120
|
-
[ops.
|
|
121
|
-
[ops.
|
|
135
|
+
[markers.global, "fn"],
|
|
136
|
+
[markers.reference, [ops.literal, "a"]],
|
|
137
|
+
[markers.reference, [ops.literal, "b"]],
|
|
138
|
+
[markers.reference, [ops.literal, "c"]],
|
|
122
139
|
],
|
|
123
140
|
]);
|
|
124
141
|
assertParse("arrowFunction", "a => b => fn(a, b)", [
|
|
@@ -128,9 +145,9 @@ describe("Origami parser", () => {
|
|
|
128
145
|
ops.lambda,
|
|
129
146
|
[[ops.literal, "b"]],
|
|
130
147
|
[
|
|
131
|
-
[
|
|
132
|
-
[ops.
|
|
133
|
-
[ops.
|
|
148
|
+
[markers.global, "fn"],
|
|
149
|
+
[markers.reference, [ops.literal, "a"]],
|
|
150
|
+
[markers.reference, [ops.literal, "b"]],
|
|
134
151
|
],
|
|
135
152
|
],
|
|
136
153
|
]);
|
|
@@ -160,147 +177,177 @@ describe("Origami parser", () => {
|
|
|
160
177
|
]);
|
|
161
178
|
});
|
|
162
179
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
[ops.
|
|
222
|
-
[ops.literal, "
|
|
223
|
-
]
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
[
|
|
247
|
-
[ops.
|
|
248
|
-
[ops.literal, "
|
|
249
|
-
]
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
[
|
|
255
|
-
|
|
256
|
-
[ops.literal, "
|
|
257
|
-
]
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
[
|
|
267
|
-
ops.traverse,
|
|
180
|
+
describe("callExpression", () => {
|
|
181
|
+
test("with parentheses arguments", () => {
|
|
182
|
+
assertParse("callExpression", "fn()", [
|
|
183
|
+
[markers.global, "fn"],
|
|
184
|
+
undefined,
|
|
185
|
+
]);
|
|
186
|
+
assertParse("callExpression", "foo.js(arg)", [
|
|
187
|
+
[markers.reference, [ops.literal, "foo.js"]],
|
|
188
|
+
[markers.reference, [ops.literal, "arg"]],
|
|
189
|
+
]);
|
|
190
|
+
assertParse("callExpression", "fn(a, b)", [
|
|
191
|
+
[markers.global, "fn"],
|
|
192
|
+
[markers.reference, [ops.literal, "a"]],
|
|
193
|
+
[markers.reference, [ops.literal, "b"]],
|
|
194
|
+
]);
|
|
195
|
+
assertParse("callExpression", "foo.js( a , b )", [
|
|
196
|
+
[markers.reference, [ops.literal, "foo.js"]],
|
|
197
|
+
[markers.reference, [ops.literal, "a"]],
|
|
198
|
+
[markers.reference, [ops.literal, "b"]],
|
|
199
|
+
]);
|
|
200
|
+
assertParse("callExpression", "fn()(arg)", [
|
|
201
|
+
[[markers.global, "fn"], undefined],
|
|
202
|
+
[markers.reference, [ops.literal, "arg"]],
|
|
203
|
+
]);
|
|
204
|
+
});
|
|
205
|
+
test("call chains", () => {
|
|
206
|
+
assertParse("callExpression", "(foo.js())('arg')", [
|
|
207
|
+
[[markers.reference, [ops.literal, "foo.js"]], undefined],
|
|
208
|
+
[ops.literal, "arg"],
|
|
209
|
+
]);
|
|
210
|
+
assertParse("callExpression", "fn('a')('b')", [
|
|
211
|
+
[
|
|
212
|
+
[markers.global, "fn"],
|
|
213
|
+
[ops.literal, "a"],
|
|
214
|
+
],
|
|
215
|
+
[ops.literal, "b"],
|
|
216
|
+
]);
|
|
217
|
+
assertParse("callExpression", "(foo.js())(a, b)", [
|
|
218
|
+
[[markers.reference, [ops.literal, "foo.js"]], undefined],
|
|
219
|
+
[markers.reference, [ops.literal, "a"]],
|
|
220
|
+
[markers.reference, [ops.literal, "b"]],
|
|
221
|
+
]);
|
|
222
|
+
});
|
|
223
|
+
test("with paths", () => {
|
|
224
|
+
assertParse("callExpression", "/", [ops.rootDirectory]);
|
|
225
|
+
assertParse("callExpression", "tree/", [
|
|
226
|
+
ops.unpack,
|
|
227
|
+
[markers.reference, [ops.literal, "tree/"]],
|
|
228
|
+
]);
|
|
229
|
+
assertParse("callExpression", "tree/foo/bar", [
|
|
230
|
+
markers.reference,
|
|
231
|
+
[ops.literal, "tree/"],
|
|
232
|
+
[ops.literal, "foo/"],
|
|
233
|
+
[ops.literal, "bar"],
|
|
234
|
+
]);
|
|
235
|
+
assertParse("callExpression", "tree/foo/bar/", [
|
|
236
|
+
markers.reference,
|
|
237
|
+
[ops.literal, "tree/"],
|
|
238
|
+
[ops.literal, "foo/"],
|
|
239
|
+
[ops.literal, "bar/"],
|
|
240
|
+
]);
|
|
241
|
+
// Consecutive slahes in a path are removed
|
|
242
|
+
assertParse("callExpression", "path//key", [
|
|
243
|
+
markers.reference,
|
|
244
|
+
[ops.literal, "path/"],
|
|
245
|
+
[ops.literal, "key"],
|
|
246
|
+
]);
|
|
247
|
+
assertParse("callExpression", "/foo/bar", [
|
|
248
|
+
[ops.rootDirectory],
|
|
249
|
+
[ops.literal, "foo/"],
|
|
250
|
+
[ops.literal, "bar"],
|
|
251
|
+
]);
|
|
252
|
+
assertParse("callExpression", "{ a: 1, b: 2}/b", [
|
|
253
|
+
[ops.object, ["a", [ops.literal, 1]], ["b", [ops.literal, 2]]],
|
|
254
|
+
[ops.literal, "b"],
|
|
255
|
+
]);
|
|
256
|
+
assertParse("callExpression", "files:foo/bar", [
|
|
257
|
+
[markers.global, "files:"],
|
|
258
|
+
[ops.literal, "foo/"],
|
|
259
|
+
[ops.literal, "bar"],
|
|
260
|
+
]);
|
|
261
|
+
});
|
|
262
|
+
test("path and parentheses chains", () => {
|
|
263
|
+
assertParse("callExpression", "foo.js()/key", [
|
|
264
|
+
[[markers.reference, [ops.literal, "foo.js"]], undefined],
|
|
265
|
+
[ops.literal, "key"],
|
|
266
|
+
]);
|
|
267
|
+
assertParse("callExpression", "tree/key()", [
|
|
268
|
+
[markers.reference, [ops.literal, "tree/"], [ops.literal, "key"]],
|
|
269
|
+
undefined,
|
|
270
|
+
]);
|
|
271
|
+
assertParse("callExpression", "(tree)/", [
|
|
272
|
+
ops.unpack,
|
|
273
|
+
[markers.reference, [ops.literal, "tree/"]],
|
|
274
|
+
]);
|
|
275
|
+
assertParse("callExpression", "fn()/key()", [
|
|
276
|
+
[
|
|
277
|
+
[[markers.global, "fn"], undefined],
|
|
278
|
+
[ops.literal, "key"],
|
|
279
|
+
],
|
|
280
|
+
undefined,
|
|
281
|
+
]);
|
|
282
|
+
assertParse("callExpression", "package:@weborigami/dropbox/auth(creds)", [
|
|
268
283
|
[
|
|
269
|
-
[
|
|
284
|
+
[markers.global, "package:"],
|
|
270
285
|
[ops.literal, "@weborigami/"],
|
|
286
|
+
[ops.literal, "dropbox/"],
|
|
287
|
+
[ops.literal, "auth"],
|
|
271
288
|
],
|
|
272
|
-
[ops.literal, "
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
289
|
+
[markers.reference, [ops.literal, "creds"]],
|
|
290
|
+
]);
|
|
291
|
+
});
|
|
292
|
+
test("tagged templates", () => {
|
|
293
|
+
assertParse("callExpression", "indent`hello`", [
|
|
294
|
+
[markers.global, "indent"],
|
|
295
|
+
[ops.literal, ["hello"]],
|
|
296
|
+
]);
|
|
297
|
+
assertParse("callExpression", "fn.js`Hello, world.`", [
|
|
298
|
+
[markers.reference, [ops.literal, "fn.js"]],
|
|
299
|
+
[ops.literal, ["Hello, world."]],
|
|
300
|
+
]);
|
|
301
|
+
});
|
|
302
|
+
test("protocols", () => {
|
|
303
|
+
assertParse("callExpression", "files:src/assets", [
|
|
304
|
+
[markers.global, "files:"],
|
|
305
|
+
[ops.literal, "src/"],
|
|
306
|
+
[ops.literal, "assets"],
|
|
307
|
+
]);
|
|
308
|
+
assertParse("callExpression", "new:(js:Date, '2025-01-01')", [
|
|
309
|
+
[markers.global, "new:"],
|
|
310
|
+
[
|
|
311
|
+
[markers.global, "js:"],
|
|
312
|
+
[ops.literal, "Date"],
|
|
313
|
+
],
|
|
314
|
+
[ops.literal, "2025-01-01"],
|
|
315
|
+
]);
|
|
316
|
+
});
|
|
277
317
|
});
|
|
278
318
|
|
|
279
319
|
test("callExpression using property acccess", () => {
|
|
280
320
|
assertParse("callExpression", "(foo).bar", [
|
|
281
|
-
|
|
282
|
-
[ops.
|
|
321
|
+
markers.reference,
|
|
322
|
+
[ops.literal, "foo/"],
|
|
283
323
|
[ops.literal, "bar"],
|
|
284
324
|
]);
|
|
285
325
|
assertParse("callExpression", "(foo).bar.baz", [
|
|
286
|
-
|
|
287
|
-
[ops.
|
|
326
|
+
markers.reference,
|
|
327
|
+
[ops.literal, "foo/"],
|
|
328
|
+
[ops.literal, "bar/"],
|
|
288
329
|
[ops.literal, "baz"],
|
|
289
330
|
]);
|
|
290
331
|
assertParse("callExpression", "foo[bar]", [
|
|
291
|
-
|
|
292
|
-
[ops.
|
|
293
|
-
[ops.
|
|
332
|
+
markers.reference,
|
|
333
|
+
[ops.literal, "foo/"],
|
|
334
|
+
[markers.reference, [ops.literal, "bar"]],
|
|
294
335
|
]);
|
|
336
|
+
assertParse(
|
|
337
|
+
"callExpression",
|
|
338
|
+
"Tree.map",
|
|
339
|
+
[markers.reference, [ops.literal, "Tree/"], [ops.literal, "map"]],
|
|
340
|
+
"jse"
|
|
341
|
+
);
|
|
295
342
|
});
|
|
296
343
|
|
|
297
344
|
test("commaExpression", () => {
|
|
298
345
|
assertParse("commaExpression", "1", [ops.literal, 1]);
|
|
299
346
|
assertParse("commaExpression", "a, b, c", [
|
|
300
347
|
ops.comma,
|
|
301
|
-
[ops.
|
|
302
|
-
[ops.
|
|
303
|
-
[ops.
|
|
348
|
+
[markers.reference, [ops.literal, "a"]],
|
|
349
|
+
[markers.reference, [ops.literal, "b"]],
|
|
350
|
+
[markers.reference, [ops.literal, "c"]],
|
|
304
351
|
]);
|
|
305
352
|
});
|
|
306
353
|
|
|
@@ -308,19 +355,19 @@ describe("Origami parser", () => {
|
|
|
308
355
|
assertParse("conditionalExpression", "1", [ops.literal, 1]);
|
|
309
356
|
assertParse("conditionalExpression", "true ? 1 : 0", [
|
|
310
357
|
ops.conditional,
|
|
311
|
-
[ops.
|
|
358
|
+
[markers.reference, [ops.literal, "true"]],
|
|
312
359
|
[ops.literal, 1],
|
|
313
360
|
[ops.literal, 0],
|
|
314
361
|
]);
|
|
315
362
|
assertParse("conditionalExpression", "false ? () => 1 : 0", [
|
|
316
363
|
ops.conditional,
|
|
317
|
-
[ops.
|
|
364
|
+
[markers.reference, [ops.literal, "false"]],
|
|
318
365
|
[ops.lambda, [], [ops.lambda, [], [ops.literal, 1]]],
|
|
319
366
|
[ops.literal, 0],
|
|
320
367
|
]);
|
|
321
368
|
assertParse("conditionalExpression", "false ? =1 : 0", [
|
|
322
369
|
ops.conditional,
|
|
323
|
-
[ops.
|
|
370
|
+
[markers.reference, [ops.literal, "false"]],
|
|
324
371
|
[ops.lambda, [], [ops.lambda, [[ops.literal, "_"]], [ops.literal, 1]]],
|
|
325
372
|
[ops.literal, 0],
|
|
326
373
|
]);
|
|
@@ -334,8 +381,12 @@ describe("Origami parser", () => {
|
|
|
334
381
|
]);
|
|
335
382
|
assertParse("equalityExpression", "a === b === c", [
|
|
336
383
|
ops.strictEqual,
|
|
337
|
-
[
|
|
338
|
-
|
|
384
|
+
[
|
|
385
|
+
ops.strictEqual,
|
|
386
|
+
[markers.reference, [ops.literal, "a"]],
|
|
387
|
+
[markers.reference, [ops.literal, "b"]],
|
|
388
|
+
],
|
|
389
|
+
[markers.reference, [ops.literal, "c"]],
|
|
339
390
|
]);
|
|
340
391
|
assertParse("equalityExpression", "1 !== 1", [
|
|
341
392
|
ops.notStrictEqual,
|
|
@@ -403,8 +454,8 @@ Body`,
|
|
|
403
454
|
[
|
|
404
455
|
ops.getter,
|
|
405
456
|
[
|
|
406
|
-
[ops.
|
|
407
|
-
[ops.
|
|
457
|
+
[markers.reference, [ops.literal, "index.ori"]],
|
|
458
|
+
[markers.reference, [ops.literal, "teamData.yaml"]],
|
|
408
459
|
],
|
|
409
460
|
],
|
|
410
461
|
],
|
|
@@ -413,9 +464,12 @@ Body`,
|
|
|
413
464
|
[
|
|
414
465
|
ops.getter,
|
|
415
466
|
[
|
|
416
|
-
[
|
|
417
|
-
[ops.
|
|
418
|
-
[
|
|
467
|
+
[markers.global, "map"],
|
|
468
|
+
[markers.reference, [ops.literal, "images"]],
|
|
469
|
+
[
|
|
470
|
+
ops.object,
|
|
471
|
+
["value", [markers.reference, [ops.literal, "thumbnail.js"]]],
|
|
472
|
+
],
|
|
419
473
|
],
|
|
420
474
|
],
|
|
421
475
|
],
|
|
@@ -423,58 +477,54 @@ Body`,
|
|
|
423
477
|
);
|
|
424
478
|
|
|
425
479
|
// Builtin on its own is the function itself, not a function call
|
|
426
|
-
assertParse("expression", "mdHtml:", [
|
|
427
|
-
|
|
428
|
-
// Consecutive slahes in a path are removed
|
|
429
|
-
assertParse("expression", "path//key", [
|
|
430
|
-
ops.traverse,
|
|
431
|
-
[ops.scope, "path/"],
|
|
432
|
-
[ops.literal, "key"],
|
|
433
|
-
]);
|
|
434
|
-
|
|
435
|
-
// Single slash at start of something = absolute file path
|
|
436
|
-
assertParse("expression", "/path", [
|
|
437
|
-
ops.rootDirectory,
|
|
438
|
-
[ops.literal, "path"],
|
|
439
|
-
]);
|
|
480
|
+
assertParse("expression", "mdHtml:", [markers.global, "mdHtml:"]);
|
|
440
481
|
|
|
441
482
|
// Consecutive slashes at start of something = comment
|
|
442
|
-
assertParse(
|
|
483
|
+
assertParse(
|
|
484
|
+
"expression",
|
|
485
|
+
"x //comment",
|
|
486
|
+
[markers.reference, [ops.literal, "x"]],
|
|
487
|
+
"jse",
|
|
488
|
+
false
|
|
489
|
+
);
|
|
443
490
|
|
|
444
491
|
assertParse("expression", "page.ori(mdHtml:(about.md))", [
|
|
445
|
-
[ops.
|
|
492
|
+
[markers.reference, [ops.literal, "page.ori"]],
|
|
446
493
|
[
|
|
447
|
-
[
|
|
448
|
-
[ops.
|
|
494
|
+
[markers.global, "mdHtml:"],
|
|
495
|
+
[markers.reference, [ops.literal, "about.md"]],
|
|
449
496
|
],
|
|
450
497
|
]);
|
|
451
498
|
|
|
452
499
|
// Slash on its own is the root folder
|
|
453
500
|
assertParse("expression", "keys /", [
|
|
454
|
-
[
|
|
501
|
+
[markers.global, "keys"],
|
|
455
502
|
[ops.rootDirectory],
|
|
456
503
|
]);
|
|
457
504
|
|
|
458
505
|
assertParse("expression", "'Hello' -> test.orit", [
|
|
459
|
-
[ops.
|
|
506
|
+
[markers.reference, [ops.literal, "test.orit"]],
|
|
460
507
|
[ops.literal, "Hello"],
|
|
461
508
|
]);
|
|
462
|
-
assertParse("expression", "obj.json", [
|
|
509
|
+
assertParse("expression", "obj.json", [
|
|
510
|
+
markers.reference,
|
|
511
|
+
[ops.literal, "obj.json"],
|
|
512
|
+
]);
|
|
463
513
|
assertParse("expression", "(fn a, b, c)", [
|
|
464
|
-
[
|
|
465
|
-
[
|
|
466
|
-
[
|
|
467
|
-
[
|
|
514
|
+
[markers.global, "fn"],
|
|
515
|
+
[markers.reference, [ops.literal, "a"]],
|
|
516
|
+
[markers.reference, [ops.literal, "b"]],
|
|
517
|
+
[markers.reference, [ops.literal, "c"]],
|
|
468
518
|
]);
|
|
469
519
|
assertParse("expression", "foo.bar('hello', 'world')", [
|
|
470
|
-
[ops.
|
|
520
|
+
[markers.reference, [ops.literal, "foo.bar"]],
|
|
471
521
|
[ops.literal, "hello"],
|
|
472
522
|
[ops.literal, "world"],
|
|
473
523
|
]);
|
|
474
|
-
assertParse("expression", "(key)('a')", [
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
]);
|
|
524
|
+
// assertParse("expression", "(key)('a')", [
|
|
525
|
+
// [markers.reference, [ops.literal, "key"]],
|
|
526
|
+
// [ops.literal, "a"],
|
|
527
|
+
// ]);
|
|
478
528
|
assertParse("expression", "1", [ops.literal, 1]);
|
|
479
529
|
assertParse("expression", "{ a: 1, b: 2 }", [
|
|
480
530
|
ops.object,
|
|
@@ -482,11 +532,11 @@ Body`,
|
|
|
482
532
|
["b", [ops.literal, 2]],
|
|
483
533
|
]);
|
|
484
534
|
assertParse("expression", "serve { index.html: 'hello' }", [
|
|
485
|
-
[
|
|
535
|
+
[markers.global, "serve"],
|
|
486
536
|
[ops.object, ["index.html", [ops.literal, "hello"]]],
|
|
487
537
|
]);
|
|
488
538
|
assertParse("expression", "fn =`x`", [
|
|
489
|
-
[
|
|
539
|
+
[markers.global, "fn"],
|
|
490
540
|
[
|
|
491
541
|
ops.lambda,
|
|
492
542
|
[[ops.literal, "_"]],
|
|
@@ -494,33 +544,37 @@ Body`,
|
|
|
494
544
|
],
|
|
495
545
|
]);
|
|
496
546
|
assertParse("expression", "copy app.js(formulas), files:snapshot", [
|
|
497
|
-
[
|
|
547
|
+
[markers.global, "copy"],
|
|
498
548
|
[
|
|
499
|
-
[ops.
|
|
500
|
-
[ops.
|
|
549
|
+
[markers.reference, [ops.literal, "app.js"]],
|
|
550
|
+
[markers.reference, [ops.literal, "formulas"]],
|
|
501
551
|
],
|
|
502
552
|
[
|
|
503
|
-
[
|
|
553
|
+
[markers.global, "files:"],
|
|
504
554
|
[ops.literal, "snapshot"],
|
|
505
555
|
],
|
|
506
556
|
]);
|
|
507
557
|
assertParse("expression", "map =`<li>${_}</li>`", [
|
|
508
|
-
[
|
|
558
|
+
[markers.global, "map"],
|
|
509
559
|
[
|
|
510
560
|
ops.lambda,
|
|
511
561
|
[[ops.literal, "_"]],
|
|
512
|
-
[
|
|
562
|
+
[
|
|
563
|
+
ops.templateTree,
|
|
564
|
+
[ops.literal, ["<li>", "</li>"]],
|
|
565
|
+
[markers.reference, [ops.literal, "_"]],
|
|
566
|
+
],
|
|
513
567
|
],
|
|
514
568
|
]);
|
|
515
569
|
assertParse("expression", `https://example.com/about/`, [
|
|
516
|
-
[
|
|
570
|
+
[markers.global, "https:"],
|
|
517
571
|
[ops.literal, "example.com/"],
|
|
518
572
|
[ops.literal, "about/"],
|
|
519
573
|
]);
|
|
520
574
|
assertParse("expression", "tag`Hello, ${name}!`", [
|
|
521
|
-
[
|
|
575
|
+
[markers.global, "tag"],
|
|
522
576
|
[ops.literal, ["Hello, ", "!"]],
|
|
523
|
-
[ops.concat, [ops.
|
|
577
|
+
[ops.concat, [markers.reference, [ops.literal, "name"]]],
|
|
524
578
|
]);
|
|
525
579
|
assertParse("expression", "(post, slug) => fn.js(post, slug)", [
|
|
526
580
|
ops.lambda,
|
|
@@ -529,42 +583,38 @@ Body`,
|
|
|
529
583
|
[ops.literal, "slug"],
|
|
530
584
|
],
|
|
531
585
|
[
|
|
532
|
-
[ops.
|
|
533
|
-
[ops.
|
|
534
|
-
[ops.
|
|
586
|
+
[markers.reference, [ops.literal, "fn.js"]],
|
|
587
|
+
[markers.reference, [ops.literal, "post"]],
|
|
588
|
+
[markers.reference, [ops.literal, "slug"]],
|
|
535
589
|
],
|
|
536
590
|
]);
|
|
537
591
|
assertParse("expression", "keys ~", [
|
|
538
|
-
[
|
|
592
|
+
[markers.global, "keys"],
|
|
539
593
|
[ops.homeDirectory],
|
|
540
594
|
]);
|
|
541
595
|
assertParse("expression", "keys /Users/alice", [
|
|
542
|
-
[
|
|
543
|
-
[
|
|
544
|
-
ops.traverse,
|
|
545
|
-
[ops.rootDirectory, [ops.literal, "Users/"]],
|
|
546
|
-
[ops.literal, "alice"],
|
|
547
|
-
],
|
|
596
|
+
[markers.global, "keys"],
|
|
597
|
+
[[ops.rootDirectory], [ops.literal, "Users/"], [ops.literal, "alice"]],
|
|
548
598
|
]);
|
|
549
599
|
|
|
550
600
|
// Verify parser treatment of identifiers containing operators
|
|
551
601
|
assertParse("expression", "a + b", [
|
|
552
602
|
ops.addition,
|
|
553
|
-
[
|
|
554
|
-
[
|
|
603
|
+
[markers.reference, [ops.literal, "a"]],
|
|
604
|
+
[markers.reference, [ops.literal, "b"]],
|
|
555
605
|
]);
|
|
556
|
-
assertParse("expression", "a+b", [ops.
|
|
606
|
+
assertParse("expression", "a+b", [markers.reference, [ops.literal, "a+b"]]);
|
|
557
607
|
assertParse("expression", "a - b", [
|
|
558
608
|
ops.subtraction,
|
|
559
|
-
[
|
|
560
|
-
[
|
|
609
|
+
[markers.reference, [ops.literal, "a"]],
|
|
610
|
+
[markers.reference, [ops.literal, "b"]],
|
|
561
611
|
]);
|
|
562
|
-
assertParse("expression", "a-b", [ops.
|
|
563
|
-
assertParse("expression", "a&b", [ops.
|
|
612
|
+
assertParse("expression", "a-b", [markers.reference, [ops.literal, "a-b"]]);
|
|
613
|
+
assertParse("expression", "a&b", [markers.reference, [ops.literal, "a&b"]]);
|
|
564
614
|
assertParse("expression", "a & b", [
|
|
565
615
|
ops.bitwiseAnd,
|
|
566
|
-
[
|
|
567
|
-
[
|
|
616
|
+
[markers.reference, [ops.literal, "a"]],
|
|
617
|
+
[markers.reference, [ops.literal, "b"]],
|
|
568
618
|
]);
|
|
569
619
|
});
|
|
570
620
|
|
|
@@ -578,7 +628,7 @@ Body`,
|
|
|
578
628
|
[
|
|
579
629
|
ops.lambda,
|
|
580
630
|
[[ops.literal, "name"]],
|
|
581
|
-
[[ops.
|
|
631
|
+
[[markers.reference, [ops.literal, "_template"]], undefined],
|
|
582
632
|
],
|
|
583
633
|
"jse",
|
|
584
634
|
false
|
|
@@ -586,12 +636,18 @@ Body`,
|
|
|
586
636
|
});
|
|
587
637
|
|
|
588
638
|
test("group", () => {
|
|
589
|
-
assertParse("group", "(hello)", [
|
|
590
|
-
|
|
591
|
-
|
|
639
|
+
assertParse("group", "(hello)", [
|
|
640
|
+
markers.reference,
|
|
641
|
+
[ops.literal, "hello"],
|
|
642
|
+
]);
|
|
643
|
+
assertParse("group", "(((nested)))", [
|
|
644
|
+
markers.reference,
|
|
645
|
+
[ops.literal, "nested"],
|
|
646
|
+
]);
|
|
647
|
+
assertParse("group", "(fn())", [[markers.global, "fn"], undefined]);
|
|
592
648
|
assertParse("group", "(a -> b)", [
|
|
593
|
-
[
|
|
594
|
-
[ops.
|
|
649
|
+
[markers.global, "b"],
|
|
650
|
+
[markers.reference, [ops.literal, "a"]],
|
|
595
651
|
]);
|
|
596
652
|
});
|
|
597
653
|
|
|
@@ -614,42 +670,42 @@ Body`,
|
|
|
614
670
|
|
|
615
671
|
test("implicitParenthesesCallExpression", () => {
|
|
616
672
|
assertParse("implicitParenthesesCallExpression", "fn arg", [
|
|
617
|
-
[
|
|
618
|
-
[
|
|
673
|
+
[markers.global, "fn"],
|
|
674
|
+
[markers.reference, [ops.literal, "arg"]],
|
|
619
675
|
]);
|
|
620
676
|
assertParse("implicitParenthesesCallExpression", "page.ori 'a', 'b'", [
|
|
621
|
-
[ops.
|
|
677
|
+
[markers.reference, [ops.literal, "page.ori"]],
|
|
622
678
|
[ops.literal, "a"],
|
|
623
679
|
[ops.literal, "b"],
|
|
624
680
|
]);
|
|
625
681
|
assertParse("implicitParenthesesCallExpression", "fn a(b), c", [
|
|
626
|
-
[
|
|
682
|
+
[markers.global, "fn"],
|
|
627
683
|
[
|
|
628
|
-
[
|
|
629
|
-
[ops.
|
|
684
|
+
[markers.global, "a"],
|
|
685
|
+
[markers.reference, [ops.literal, "b"]],
|
|
630
686
|
],
|
|
631
|
-
[
|
|
687
|
+
[markers.reference, [ops.literal, "c"]],
|
|
632
688
|
]);
|
|
633
689
|
assertParse("implicitParenthesesCallExpression", "(fn()) 'arg'", [
|
|
634
|
-
[[
|
|
690
|
+
[[markers.global, "fn"], undefined],
|
|
635
691
|
[ops.literal, "arg"],
|
|
636
692
|
]);
|
|
637
693
|
assertParse("implicitParenthesesCallExpression", "tree/key arg", [
|
|
638
|
-
[
|
|
639
|
-
[
|
|
694
|
+
[markers.reference, [ops.literal, "tree/"], [ops.literal, "key"]],
|
|
695
|
+
[markers.reference, [ops.literal, "arg"]],
|
|
640
696
|
]);
|
|
641
697
|
assertParse("implicitParenthesesCallExpression", "foo.js bar.ori 'arg'", [
|
|
642
|
-
[ops.
|
|
698
|
+
[markers.reference, [ops.literal, "foo.js"]],
|
|
643
699
|
[
|
|
644
|
-
[ops.
|
|
700
|
+
[markers.reference, [ops.literal, "bar.ori"]],
|
|
645
701
|
[ops.literal, "arg"],
|
|
646
702
|
],
|
|
647
703
|
]);
|
|
648
704
|
});
|
|
649
705
|
|
|
650
706
|
test("jsIdentifier", () => {
|
|
651
|
-
assertParse("jsIdentifier", "foo", "foo", "jse"
|
|
652
|
-
assertParse("jsIdentifier", "$Δelta", "$Δelta", "jse"
|
|
707
|
+
assertParse("jsIdentifier", "foo", [ops.literal, "foo"], "jse");
|
|
708
|
+
assertParse("jsIdentifier", "$Δelta", [ops.literal, "$Δelta"], "jse");
|
|
653
709
|
assertThrows(
|
|
654
710
|
"jsIdentifier",
|
|
655
711
|
"1stCharacterIsNumber",
|
|
@@ -689,7 +745,6 @@ Body`,
|
|
|
689
745
|
[ops.literal, 2],
|
|
690
746
|
[ops.literal, 3],
|
|
691
747
|
]);
|
|
692
|
-
assertThrows("list", "1\n2\n3", `but "\\n" found`, 0, "jse");
|
|
693
748
|
assertParse("list", "'a' , 'b' , 'c'", [
|
|
694
749
|
[ops.literal, "a"],
|
|
695
750
|
[ops.literal, "b"],
|
|
@@ -700,8 +755,8 @@ Body`,
|
|
|
700
755
|
test("logicalAndExpression", () => {
|
|
701
756
|
assertParse("logicalAndExpression", "true && false", [
|
|
702
757
|
ops.logicalAnd,
|
|
703
|
-
[ops.
|
|
704
|
-
[ops.lambda, [], [
|
|
758
|
+
[markers.reference, [ops.literal, "true"]],
|
|
759
|
+
[ops.lambda, [], [markers.reference, [ops.literal, "false"]]],
|
|
705
760
|
]);
|
|
706
761
|
});
|
|
707
762
|
|
|
@@ -713,9 +768,9 @@ Body`,
|
|
|
713
768
|
]);
|
|
714
769
|
assertParse("logicalOrExpression", "false || false || true", [
|
|
715
770
|
ops.logicalOr,
|
|
716
|
-
[ops.
|
|
717
|
-
[ops.lambda, [], [
|
|
718
|
-
[ops.lambda, [], [
|
|
771
|
+
[markers.reference, [ops.literal, "false"]],
|
|
772
|
+
[ops.lambda, [], [markers.reference, [ops.literal, "false"]]],
|
|
773
|
+
[ops.lambda, [], [markers.reference, [ops.literal, "true"]]],
|
|
719
774
|
]);
|
|
720
775
|
assertParse("logicalOrExpression", "1 || 2 && 0", [
|
|
721
776
|
ops.logicalOr,
|
|
@@ -753,27 +808,31 @@ Body`,
|
|
|
753
808
|
});
|
|
754
809
|
|
|
755
810
|
test("namespace", () => {
|
|
756
|
-
assertParse("namespace", "js:", [
|
|
811
|
+
assertParse("namespace", "js:", [markers.global, "js:"]);
|
|
757
812
|
});
|
|
758
813
|
|
|
759
814
|
test("newExpression", () => {
|
|
760
815
|
assertParse("newExpression", "new Foo()", [
|
|
761
816
|
ops.construct,
|
|
762
|
-
[ops.
|
|
817
|
+
[markers.reference, [ops.literal, "Foo"]],
|
|
818
|
+
]);
|
|
819
|
+
assertParse("newExpression", "new:Foo()", [
|
|
820
|
+
ops.construct,
|
|
821
|
+
[markers.reference, [ops.literal, "Foo"]],
|
|
763
822
|
]);
|
|
764
823
|
});
|
|
765
824
|
|
|
766
825
|
test("nullishCoalescingExpression", () => {
|
|
767
826
|
assertParse("nullishCoalescingExpression", "a ?? b", [
|
|
768
827
|
ops.nullishCoalescing,
|
|
769
|
-
[ops.
|
|
770
|
-
[ops.lambda, [], [
|
|
828
|
+
[markers.reference, [ops.literal, "a"]],
|
|
829
|
+
[ops.lambda, [], [markers.reference, [ops.literal, "b"]]],
|
|
771
830
|
]);
|
|
772
831
|
assertParse("nullishCoalescingExpression", "a ?? b ?? c", [
|
|
773
832
|
ops.nullishCoalescing,
|
|
774
|
-
[ops.
|
|
775
|
-
[ops.lambda, [], [
|
|
776
|
-
[ops.lambda, [], [
|
|
833
|
+
[markers.reference, [ops.literal, "a"]],
|
|
834
|
+
[ops.lambda, [], [markers.reference, [ops.literal, "b"]]],
|
|
835
|
+
[ops.lambda, [], [markers.reference, [ops.literal, "c"]]],
|
|
777
836
|
]);
|
|
778
837
|
});
|
|
779
838
|
|
|
@@ -788,7 +847,7 @@ Body`,
|
|
|
788
847
|
assertParse("objectLiteral", "{ a: 1, b }", [
|
|
789
848
|
ops.object,
|
|
790
849
|
["a", [ops.literal, 1]],
|
|
791
|
-
["b", [
|
|
850
|
+
["b", [markers.reference, "b"]],
|
|
792
851
|
]);
|
|
793
852
|
assertParse("objectLiteral", "{ sub: { a: 1 } }", [
|
|
794
853
|
ops.object,
|
|
@@ -805,7 +864,7 @@ Body`,
|
|
|
805
864
|
]);
|
|
806
865
|
assertParse("objectLiteral", "{ a = b, b = 2 }", [
|
|
807
866
|
ops.object,
|
|
808
|
-
["a", [ops.getter, [ops.
|
|
867
|
+
["a", [ops.getter, [markers.reference, [ops.literal, "b"]]]],
|
|
809
868
|
["b", [ops.literal, 2]],
|
|
810
869
|
]);
|
|
811
870
|
assertParse(
|
|
@@ -816,7 +875,7 @@ Body`,
|
|
|
816
875
|
}`,
|
|
817
876
|
[
|
|
818
877
|
ops.object,
|
|
819
|
-
["a", [ops.getter, [ops.
|
|
878
|
+
["a", [ops.getter, [markers.reference, [ops.literal, "b"]]]],
|
|
820
879
|
["b", [ops.literal, 2]],
|
|
821
880
|
]
|
|
822
881
|
);
|
|
@@ -832,7 +891,7 @@ Body`,
|
|
|
832
891
|
ops.object,
|
|
833
892
|
[
|
|
834
893
|
"a",
|
|
835
|
-
[ops.object, ["b", [ops.getter, [[
|
|
894
|
+
[ops.object, ["b", [ops.getter, [[markers.global, "fn"], undefined]]]],
|
|
836
895
|
],
|
|
837
896
|
]);
|
|
838
897
|
assertParse("objectLiteral", "{ x = fn.js('a') }", [
|
|
@@ -842,16 +901,28 @@ Body`,
|
|
|
842
901
|
[
|
|
843
902
|
ops.getter,
|
|
844
903
|
[
|
|
845
|
-
[ops.
|
|
904
|
+
[markers.reference, [ops.literal, "fn.js"]],
|
|
846
905
|
[ops.literal, "a"],
|
|
847
906
|
],
|
|
848
907
|
],
|
|
849
908
|
],
|
|
850
909
|
]);
|
|
851
|
-
assertParse("objectLiteral", "{ a: 1, ...
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
910
|
+
assertParse("objectLiteral", "{ a: 1, ...more, c: a }", [
|
|
911
|
+
[
|
|
912
|
+
ops.object,
|
|
913
|
+
["a", [ops.literal, 1]],
|
|
914
|
+
["c", [markers.reference, [ops.literal, "a"]]],
|
|
915
|
+
[
|
|
916
|
+
"_result",
|
|
917
|
+
[
|
|
918
|
+
ops.merge,
|
|
919
|
+
[ops.object, ["a", [ops.getter, [[ops.context, 1], "a"]]]],
|
|
920
|
+
[markers.reference, [ops.literal, "more"]],
|
|
921
|
+
[ops.object, ["c", [ops.getter, [[ops.context, 1], "c"]]]],
|
|
922
|
+
],
|
|
923
|
+
],
|
|
924
|
+
],
|
|
925
|
+
"_result",
|
|
855
926
|
]);
|
|
856
927
|
assertParse("objectLiteral", "{ a: 1, ...{ b: 2 } }", [
|
|
857
928
|
ops.object,
|
|
@@ -862,22 +933,63 @@ Body`,
|
|
|
862
933
|
ops.object,
|
|
863
934
|
["(a)", [ops.literal, 1]],
|
|
864
935
|
]);
|
|
936
|
+
assertParse(
|
|
937
|
+
"objectLiteral",
|
|
938
|
+
"{ <path/to/file.txt> }",
|
|
939
|
+
[
|
|
940
|
+
ops.object,
|
|
941
|
+
[
|
|
942
|
+
"file.txt",
|
|
943
|
+
[
|
|
944
|
+
[ops.scope],
|
|
945
|
+
[ops.literal, "path/"],
|
|
946
|
+
[ops.literal, "to/"],
|
|
947
|
+
[ops.literal, "file.txt"],
|
|
948
|
+
],
|
|
949
|
+
],
|
|
950
|
+
],
|
|
951
|
+
"jse"
|
|
952
|
+
);
|
|
865
953
|
});
|
|
866
954
|
|
|
867
955
|
test("objectEntry", () => {
|
|
868
|
-
assertParse("objectEntry", "foo", ["foo", [
|
|
869
|
-
assertParse("objectEntry", "x: y", [
|
|
870
|
-
|
|
956
|
+
assertParse("objectEntry", "foo", ["foo", [markers.reference, "foo"]]);
|
|
957
|
+
assertParse("objectEntry", "x: y", [
|
|
958
|
+
"x",
|
|
959
|
+
[markers.reference, [ops.literal, "y"]],
|
|
960
|
+
]);
|
|
961
|
+
assertParse("objectEntry", "a: a", [
|
|
962
|
+
"a",
|
|
963
|
+
[markers.reference, [ops.literal, "a"]],
|
|
964
|
+
]);
|
|
965
|
+
assertParse(
|
|
966
|
+
"objectEntry",
|
|
967
|
+
"<path/to/file.txt>",
|
|
968
|
+
[
|
|
969
|
+
"file.txt",
|
|
970
|
+
[
|
|
971
|
+
[ops.scope],
|
|
972
|
+
[ops.literal, "path/"],
|
|
973
|
+
[ops.literal, "to/"],
|
|
974
|
+
[ops.literal, "file.txt"],
|
|
975
|
+
],
|
|
976
|
+
],
|
|
977
|
+
"jse"
|
|
978
|
+
);
|
|
871
979
|
assertParse("objectEntry", "a: (a) => a", [
|
|
872
980
|
"a",
|
|
873
|
-
[
|
|
981
|
+
[
|
|
982
|
+
ops.lambda,
|
|
983
|
+
[[ops.literal, "a"]],
|
|
984
|
+
[markers.reference, [ops.literal, "a"]],
|
|
985
|
+
],
|
|
874
986
|
]);
|
|
875
987
|
assertParse("objectEntry", "posts/: map(posts, post.ori)", [
|
|
876
988
|
"posts/",
|
|
877
989
|
[
|
|
878
|
-
[
|
|
879
|
-
[ops.
|
|
880
|
-
[ops.
|
|
990
|
+
[markers.global, "map"],
|
|
991
|
+
[markers.reference, [ops.literal, "posts"]],
|
|
992
|
+
[markers.reference, [ops.literal, "post.ori"]],
|
|
881
993
|
],
|
|
882
994
|
]);
|
|
883
995
|
});
|
|
@@ -885,14 +997,14 @@ Body`,
|
|
|
885
997
|
test("objectGetter", () => {
|
|
886
998
|
assertParse("objectGetter", "data = obj.json", [
|
|
887
999
|
"data",
|
|
888
|
-
[ops.getter, [ops.
|
|
1000
|
+
[ops.getter, [markers.reference, [ops.literal, "obj.json"]]],
|
|
889
1001
|
]);
|
|
890
1002
|
assertParse("objectGetter", "foo = page.ori 'bar'", [
|
|
891
1003
|
"foo",
|
|
892
1004
|
[
|
|
893
1005
|
ops.getter,
|
|
894
1006
|
[
|
|
895
|
-
[ops.
|
|
1007
|
+
[markers.reference, [ops.literal, "page.ori"]],
|
|
896
1008
|
[ops.literal, "bar"],
|
|
897
1009
|
],
|
|
898
1010
|
],
|
|
@@ -908,7 +1020,7 @@ Body`,
|
|
|
908
1020
|
assertParse("objectProperty", "x: fn('a')", [
|
|
909
1021
|
"x",
|
|
910
1022
|
[
|
|
911
|
-
[
|
|
1023
|
+
[markers.global, "fn"],
|
|
912
1024
|
[ops.literal, "a"],
|
|
913
1025
|
],
|
|
914
1026
|
]);
|
|
@@ -930,9 +1042,9 @@ Body`,
|
|
|
930
1042
|
test("parenthesesArguments", () => {
|
|
931
1043
|
assertParse("parenthesesArguments", "()", [undefined]);
|
|
932
1044
|
assertParse("parenthesesArguments", "(a, b, c)", [
|
|
933
|
-
[ops.
|
|
934
|
-
[ops.
|
|
935
|
-
[ops.
|
|
1045
|
+
[markers.reference, [ops.literal, "a"]],
|
|
1046
|
+
[markers.reference, [ops.literal, "b"]],
|
|
1047
|
+
[markers.reference, [ops.literal, "c"]],
|
|
936
1048
|
]);
|
|
937
1049
|
});
|
|
938
1050
|
|
|
@@ -954,41 +1066,47 @@ Body`,
|
|
|
954
1066
|
});
|
|
955
1067
|
|
|
956
1068
|
test("pathArguments", () => {
|
|
957
|
-
assertParse("pathArguments", "/", [
|
|
1069
|
+
assertParse("pathArguments", "/", [markers.traverse]);
|
|
958
1070
|
assertParse("pathArguments", "/tree", [
|
|
959
|
-
|
|
1071
|
+
markers.traverse,
|
|
960
1072
|
[ops.literal, "tree"],
|
|
961
1073
|
]);
|
|
962
1074
|
assertParse("pathArguments", "/tree/", [
|
|
963
|
-
|
|
1075
|
+
markers.traverse,
|
|
964
1076
|
[ops.literal, "tree/"],
|
|
965
1077
|
]);
|
|
966
1078
|
});
|
|
967
1079
|
|
|
968
1080
|
test("pipelineExpression", () => {
|
|
969
|
-
assertParse("pipelineExpression", "foo", [
|
|
1081
|
+
assertParse("pipelineExpression", "foo", [
|
|
1082
|
+
markers.reference,
|
|
1083
|
+
[ops.literal, "foo"],
|
|
1084
|
+
]);
|
|
970
1085
|
assertParse("pipelineExpression", "a -> b", [
|
|
971
|
-
[
|
|
972
|
-
[ops.
|
|
1086
|
+
[markers.global, "b"],
|
|
1087
|
+
[markers.reference, [ops.literal, "a"]],
|
|
973
1088
|
]);
|
|
974
1089
|
assertParse("pipelineExpression", "input → one.js → two.js", [
|
|
975
|
-
[ops.
|
|
1090
|
+
[markers.reference, [ops.literal, "two.js"]],
|
|
976
1091
|
[
|
|
977
|
-
[ops.
|
|
978
|
-
[ops.
|
|
1092
|
+
[markers.reference, [ops.literal, "one.js"]],
|
|
1093
|
+
[markers.reference, [ops.literal, "input"]],
|
|
979
1094
|
],
|
|
980
1095
|
]);
|
|
981
1096
|
assertParse("pipelineExpression", "fn a -> b", [
|
|
982
|
-
[
|
|
1097
|
+
[markers.global, "b"],
|
|
983
1098
|
[
|
|
984
|
-
[
|
|
985
|
-
[
|
|
1099
|
+
[markers.global, "fn"],
|
|
1100
|
+
[markers.reference, [ops.literal, "a"]],
|
|
986
1101
|
],
|
|
987
1102
|
]);
|
|
988
1103
|
});
|
|
989
1104
|
|
|
990
1105
|
test("primary", () => {
|
|
991
|
-
assertParse("primary", "foo.js", [
|
|
1106
|
+
assertParse("primary", "foo.js", [
|
|
1107
|
+
markers.reference,
|
|
1108
|
+
[ops.literal, "foo.js"],
|
|
1109
|
+
]);
|
|
992
1110
|
assertParse("primary", "[1, 2]", [
|
|
993
1111
|
ops.array,
|
|
994
1112
|
[ops.literal, 1],
|
|
@@ -998,7 +1116,7 @@ Body`,
|
|
|
998
1116
|
assertParse(
|
|
999
1117
|
"primary",
|
|
1000
1118
|
"<index.html>",
|
|
1001
|
-
[ops.scope, "index.html"],
|
|
1119
|
+
[[ops.scope], [ops.literal, "index.html"]],
|
|
1002
1120
|
"jse",
|
|
1003
1121
|
false
|
|
1004
1122
|
);
|
|
@@ -1018,32 +1136,33 @@ Body`,
|
|
|
1018
1136
|
});
|
|
1019
1137
|
|
|
1020
1138
|
test("protocolExpression", () => {
|
|
1021
|
-
assertParse("protocolExpression", "foo://bar", [
|
|
1022
|
-
[
|
|
1023
|
-
[ops.literal, "bar"],
|
|
1139
|
+
assertParse("protocolExpression", "foo://bar/baz", [
|
|
1140
|
+
[markers.global, "foo:"],
|
|
1141
|
+
[ops.literal, "bar/"],
|
|
1142
|
+
[ops.literal, "baz"],
|
|
1024
1143
|
]);
|
|
1025
1144
|
assertParse("protocolExpression", "http://example.com", [
|
|
1026
|
-
[
|
|
1145
|
+
[markers.global, "http:"],
|
|
1027
1146
|
[ops.literal, "example.com"],
|
|
1028
1147
|
]);
|
|
1029
1148
|
assertParse("protocolExpression", "https://example.com/about/", [
|
|
1030
|
-
[
|
|
1149
|
+
[markers.global, "https:"],
|
|
1031
1150
|
[ops.literal, "example.com/"],
|
|
1032
1151
|
[ops.literal, "about/"],
|
|
1033
1152
|
]);
|
|
1034
1153
|
assertParse("protocolExpression", "https://example.com/about/index.html", [
|
|
1035
|
-
[
|
|
1154
|
+
[markers.global, "https:"],
|
|
1036
1155
|
[ops.literal, "example.com/"],
|
|
1037
1156
|
[ops.literal, "about/"],
|
|
1038
1157
|
[ops.literal, "index.html"],
|
|
1039
1158
|
]);
|
|
1040
1159
|
assertParse("protocolExpression", "http://localhost:5000/foo", [
|
|
1041
|
-
[
|
|
1160
|
+
[markers.global, "http:"],
|
|
1042
1161
|
[ops.literal, "localhost:5000/"],
|
|
1043
1162
|
[ops.literal, "foo"],
|
|
1044
1163
|
]);
|
|
1045
1164
|
assertParse("protocolExpression", "files:///foo/bar.txt", [
|
|
1046
|
-
[
|
|
1165
|
+
[markers.global, "files:"],
|
|
1047
1166
|
[ops.literal, "/"],
|
|
1048
1167
|
[ops.literal, "foo/"],
|
|
1049
1168
|
[ops.literal, "bar.txt"],
|
|
@@ -1052,7 +1171,7 @@ Body`,
|
|
|
1052
1171
|
|
|
1053
1172
|
test("qualifiedReference", () => {
|
|
1054
1173
|
assertParse("qualifiedReference", "js:Date", [
|
|
1055
|
-
[
|
|
1174
|
+
[markers.global, "js:"],
|
|
1056
1175
|
[ops.literal, "Date"],
|
|
1057
1176
|
]);
|
|
1058
1177
|
});
|
|
@@ -1084,15 +1203,15 @@ Body`,
|
|
|
1084
1203
|
]);
|
|
1085
1204
|
});
|
|
1086
1205
|
|
|
1087
|
-
test("rootDirectory", () => {
|
|
1088
|
-
assertParse("rootDirectory", "/", [ops.rootDirectory]);
|
|
1089
|
-
});
|
|
1090
|
-
|
|
1091
1206
|
test("scopeReference", () => {
|
|
1092
|
-
assertParse("scopeReference", "keys", [
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1207
|
+
assertParse("scopeReference", "keys", [
|
|
1208
|
+
markers.reference,
|
|
1209
|
+
[ops.literal, "keys"],
|
|
1210
|
+
]);
|
|
1211
|
+
assertParse("scopeReference", "greet.js", [
|
|
1212
|
+
markers.reference,
|
|
1213
|
+
[ops.literal, "greet.js"],
|
|
1214
|
+
]);
|
|
1096
1215
|
});
|
|
1097
1216
|
|
|
1098
1217
|
test("shiftExpression", () => {
|
|
@@ -1117,18 +1236,22 @@ Body`,
|
|
|
1117
1236
|
assertParse("shorthandFunction", "=message", [
|
|
1118
1237
|
ops.lambda,
|
|
1119
1238
|
[[ops.literal, "_"]],
|
|
1120
|
-
[
|
|
1239
|
+
[markers.reference, [ops.literal, "message"]],
|
|
1121
1240
|
]);
|
|
1122
1241
|
assertParse("shorthandFunction", "=`Hello, ${name}.`", [
|
|
1123
1242
|
ops.lambda,
|
|
1124
1243
|
[[ops.literal, "_"]],
|
|
1125
|
-
[
|
|
1244
|
+
[
|
|
1245
|
+
ops.templateTree,
|
|
1246
|
+
[ops.literal, ["Hello, ", "."]],
|
|
1247
|
+
[markers.reference, [ops.literal, "name"]],
|
|
1248
|
+
],
|
|
1126
1249
|
]);
|
|
1127
1250
|
assertParse("shorthandFunction", "=indent`hello`", [
|
|
1128
1251
|
ops.lambda,
|
|
1129
1252
|
[[ops.literal, "_"]],
|
|
1130
1253
|
[
|
|
1131
|
-
[
|
|
1254
|
+
[markers.global, "indent"],
|
|
1132
1255
|
[ops.literal, ["hello"]],
|
|
1133
1256
|
],
|
|
1134
1257
|
]);
|
|
@@ -1139,8 +1262,14 @@ Body`,
|
|
|
1139
1262
|
});
|
|
1140
1263
|
|
|
1141
1264
|
test("spreadElement", () => {
|
|
1142
|
-
assertParse("spreadElement", "...a", [
|
|
1143
|
-
|
|
1265
|
+
assertParse("spreadElement", "...a", [
|
|
1266
|
+
ops.spread,
|
|
1267
|
+
[markers.reference, [ops.literal, "a"]],
|
|
1268
|
+
]);
|
|
1269
|
+
assertParse("spreadElement", "…a", [
|
|
1270
|
+
ops.spread,
|
|
1271
|
+
[markers.reference, [ops.literal, "a"]],
|
|
1272
|
+
]);
|
|
1144
1273
|
});
|
|
1145
1274
|
|
|
1146
1275
|
test("stringLiteral", () => {
|
|
@@ -1159,21 +1288,13 @@ Body`,
|
|
|
1159
1288
|
|
|
1160
1289
|
test("templateBody", () => {
|
|
1161
1290
|
assertParse("templateBody", "hello${foo}world", [
|
|
1162
|
-
ops.
|
|
1163
|
-
[
|
|
1164
|
-
[
|
|
1165
|
-
ops.templateIndent,
|
|
1166
|
-
[ops.literal, ["hello", "world"]],
|
|
1167
|
-
[ops.scope, "foo"],
|
|
1168
|
-
],
|
|
1291
|
+
ops.templateIndent,
|
|
1292
|
+
[ops.literal, ["hello", "world"]],
|
|
1293
|
+
[markers.reference, [ops.literal, "foo"]],
|
|
1169
1294
|
]);
|
|
1170
1295
|
assertParse("templateBody", "Documents can contain ` backticks", [
|
|
1171
|
-
ops.
|
|
1172
|
-
[
|
|
1173
|
-
[
|
|
1174
|
-
ops.templateIndent,
|
|
1175
|
-
[ops.literal, ["Documents can contain ` backticks"]],
|
|
1176
|
-
],
|
|
1296
|
+
ops.templateIndent,
|
|
1297
|
+
[ops.literal, ["Documents can contain ` backticks"]],
|
|
1177
1298
|
]);
|
|
1178
1299
|
});
|
|
1179
1300
|
|
|
@@ -1193,13 +1314,9 @@ title: Title goes here
|
|
|
1193
1314
|
---
|
|
1194
1315
|
Body text`,
|
|
1195
1316
|
[
|
|
1196
|
-
ops.
|
|
1197
|
-
[ops.literal,
|
|
1198
|
-
[
|
|
1199
|
-
ops.lambda,
|
|
1200
|
-
[[ops.literal, "_"]],
|
|
1201
|
-
[ops.templateIndent, [ops.literal, ["Body text"]]],
|
|
1202
|
-
],
|
|
1317
|
+
ops.object,
|
|
1318
|
+
["title", [ops.literal, "Title goes here"]],
|
|
1319
|
+
["@text", [ops.templateIndent, [ops.literal, ["Body text"]]]],
|
|
1203
1320
|
]
|
|
1204
1321
|
);
|
|
1205
1322
|
});
|
|
@@ -1221,16 +1338,9 @@ Body text`,
|
|
|
1221
1338
|
[
|
|
1222
1339
|
"@text",
|
|
1223
1340
|
[
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
[
|
|
1228
|
-
ops.templateIndent,
|
|
1229
|
-
[ops.literal, ["<h1>", "</h1>\n"]],
|
|
1230
|
-
[ops.scope, "title"],
|
|
1231
|
-
],
|
|
1232
|
-
],
|
|
1233
|
-
undefined,
|
|
1341
|
+
ops.templateIndent,
|
|
1342
|
+
[ops.literal, ["<h1>", "</h1>\n"]],
|
|
1343
|
+
[markers.reference, [ops.literal, "title"]],
|
|
1234
1344
|
],
|
|
1235
1345
|
],
|
|
1236
1346
|
]
|
|
@@ -1251,7 +1361,7 @@ Body text`,
|
|
|
1251
1361
|
assertParse("templateLiteral", "`foo ${x} bar`", [
|
|
1252
1362
|
ops.templateTree,
|
|
1253
1363
|
[ops.literal, ["foo ", " bar"]],
|
|
1254
|
-
[ops.
|
|
1364
|
+
[markers.reference, [ops.literal, "x"]],
|
|
1255
1365
|
]);
|
|
1256
1366
|
assertParse("templateLiteral", "`${`nested`}`", [
|
|
1257
1367
|
ops.templateTree,
|
|
@@ -1262,12 +1372,16 @@ Body text`,
|
|
|
1262
1372
|
ops.templateTree,
|
|
1263
1373
|
[ops.literal, ["", ""]],
|
|
1264
1374
|
[
|
|
1265
|
-
[
|
|
1266
|
-
[ops.
|
|
1375
|
+
[markers.global, "map:"],
|
|
1376
|
+
[markers.reference, [ops.literal, "people"]],
|
|
1267
1377
|
[
|
|
1268
1378
|
ops.lambda,
|
|
1269
1379
|
[[ops.literal, "_"]],
|
|
1270
|
-
[
|
|
1380
|
+
[
|
|
1381
|
+
ops.templateTree,
|
|
1382
|
+
[ops.literal, ["", ""]],
|
|
1383
|
+
[markers.reference, [ops.literal, "name"]],
|
|
1384
|
+
],
|
|
1271
1385
|
],
|
|
1272
1386
|
],
|
|
1273
1387
|
]);
|
|
@@ -1277,7 +1391,7 @@ Body text`,
|
|
|
1277
1391
|
assertParse(
|
|
1278
1392
|
"templateSubstitution",
|
|
1279
1393
|
"${foo}",
|
|
1280
|
-
[ops.
|
|
1394
|
+
[markers.reference, [ops.literal, "foo"]],
|
|
1281
1395
|
"shell",
|
|
1282
1396
|
false
|
|
1283
1397
|
);
|
|
@@ -1299,7 +1413,7 @@ Body text`,
|
|
|
1299
1413
|
test("unaryExpression", () => {
|
|
1300
1414
|
assertParse("unaryExpression", "!true", [
|
|
1301
1415
|
ops.logicalNot,
|
|
1302
|
-
[
|
|
1416
|
+
[markers.reference, [ops.literal, "true"]],
|
|
1303
1417
|
]);
|
|
1304
1418
|
assertParse("unaryExpression", "+1", [ops.unaryPlus, [ops.literal, 1]]);
|
|
1305
1419
|
assertParse("unaryExpression", "-2", [ops.unaryMinus, [ops.literal, 2]]);
|