@weborigami/language 0.6.3 → 0.6.5

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.
@@ -117,49 +117,231 @@ describe("Origami parser", () => {
117
117
  );
118
118
  });
119
119
 
120
- test("arrowFunction", () => {
121
- assertParse("arrowFunction", "() => foo", [
122
- ops.lambda,
123
- [],
124
- [markers.traverse, [markers.reference, "foo"]],
125
- ]);
126
- assertParse("arrowFunction", "x => y", [
127
- ops.lambda,
128
- [[ops.literal, "x"]],
129
- [markers.traverse, [markers.reference, "y"]],
130
- ]);
131
- assertParse("arrowFunction", "(a, b, c) ⇒ fn(a, b, c)", [
132
- ops.lambda,
133
- [
134
- [ops.literal, "a"],
135
- [ops.literal, "b"],
136
- [ops.literal, "c"],
137
- ],
138
- [
139
- [markers.traverse, [markers.reference, "fn"]],
140
- [markers.traverse, [markers.reference, "a"]],
141
- [markers.traverse, [markers.reference, "b"]],
142
- [markers.traverse, [markers.reference, "c"]],
143
- ],
144
- ]);
145
- assertParse("arrowFunction", "a => b => fn(a, b)", [
146
- ops.lambda,
147
- [[ops.literal, "a"]],
148
- [
120
+ describe("arrowFunction", () => {
121
+ test("basic arrow functions", () => {
122
+ assertParse("arrowFunction", "() => foo", [
149
123
  ops.lambda,
150
- [[ops.literal, "b"]],
124
+ 0,
125
+ [],
126
+ [markers.traverse, [markers.reference, "foo"]],
127
+ ]);
128
+ assertParse("arrowFunction", "x => y", [
129
+ ops.lambda,
130
+ 1,
131
+ [["x", [[ops.params, 0], 0]]],
132
+ [markers.traverse, [markers.reference, "y"]],
133
+ ]);
134
+ assertParse("arrowFunction", "(a, b, c) ⇒ fn(a, b, c)", [
135
+ ops.lambda,
136
+ 3,
137
+ [
138
+ ["a", [[ops.params, 0], 0]],
139
+ ["b", [[ops.params, 0], 1]],
140
+ ["c", [[ops.params, 0], 2]],
141
+ ],
151
142
  [
152
143
  [markers.traverse, [markers.reference, "fn"]],
153
144
  [markers.traverse, [markers.reference, "a"]],
154
145
  [markers.traverse, [markers.reference, "b"]],
146
+ [markers.traverse, [markers.reference, "c"]],
155
147
  ],
156
- ],
157
- ]);
158
- assertParse("arrowFunction", "async (x) => x", [
159
- ops.lambda,
160
- [[ops.literal, "x"]],
161
- [markers.traverse, [markers.reference, "x"]],
162
- ]);
148
+ ]);
149
+ // `async` keyword is effectively ignored
150
+ assertParse("arrowFunction", "async (x) => x", [
151
+ ops.lambda,
152
+ 1,
153
+ [["x", [[ops.params, 0], 0]]],
154
+ [markers.traverse, [markers.reference, "x"]],
155
+ ]);
156
+ // Can't omit a parameter like you can in an array
157
+ assertThrows("arrowFunction", "(, b) => b", "Expected an expression");
158
+ });
159
+
160
+ test("arrow function with default parameters", () => {
161
+ assertParse("arrowFunction", "(a = 1, b = fn()) => a + b", [
162
+ ops.lambda,
163
+ 0,
164
+ [
165
+ ["a", [ops.defaultValue, [[ops.params, 0], 0], [ops.literal, 1]]],
166
+ [
167
+ "__temp0__",
168
+ [
169
+ ops.defaultValue,
170
+ [[ops.params, 0], 1],
171
+ [
172
+ ops.lambda,
173
+ 0,
174
+ [],
175
+ [[markers.traverse, [markers.reference, "fn"]], undefined],
176
+ ],
177
+ ],
178
+ ],
179
+ ["b", [[ops.inherited, 0], "__temp0__"]],
180
+ ],
181
+ [
182
+ ops.addition,
183
+ [markers.traverse, [markers.reference, "a"]],
184
+ [markers.traverse, [markers.reference, "b"]],
185
+ ],
186
+ ]);
187
+ });
188
+
189
+ test("arrow function with rest parameter", () => {
190
+ assertParse("arrowFunction", "(head, ...tail) => tail", [
191
+ ops.lambda,
192
+ 1,
193
+ [
194
+ ["head", [[ops.params, 0], 0]],
195
+ ["tail", [[[ops.params, 0], "slice"], 1]],
196
+ ],
197
+ [markers.traverse, [markers.reference, "tail"]],
198
+ ]);
199
+ });
200
+
201
+ test("array parameter destructuring", () => {
202
+ assertParse("arrowFunction", "([a, b, c]) => a + b + c", [
203
+ ops.lambda,
204
+ 1,
205
+ [
206
+ ["a", [[[ops.params, 0], 0], 0]],
207
+ ["b", [[[ops.params, 0], 0], 1]],
208
+ ["c", [[[ops.params, 0], 0], 2]],
209
+ ],
210
+ [
211
+ ops.addition,
212
+ [
213
+ ops.addition,
214
+ [markers.traverse, [markers.reference, "a"]],
215
+ [markers.traverse, [markers.reference, "b"]],
216
+ ],
217
+ [markers.traverse, [markers.reference, "c"]],
218
+ ],
219
+ ]);
220
+ assertParse("arrowFunction", "([a, , b]) => a * b", [
221
+ ops.lambda,
222
+ 1,
223
+ [
224
+ ["a", [[[ops.params, 0], 0], 0]],
225
+ ["b", [[[ops.params, 0], 0], 2]],
226
+ ],
227
+ [
228
+ ops.multiplication,
229
+ [markers.traverse, [markers.reference, "a"]],
230
+ [markers.traverse, [markers.reference, "b"]],
231
+ ],
232
+ ]);
233
+ assertParse("arrowFunction", "([a = 1, b = 2]) => a + b", [
234
+ ops.lambda,
235
+ 1,
236
+ [
237
+ [
238
+ "a",
239
+ [ops.defaultValue, [[[ops.params, 0], 0], 0], [ops.literal, 1]],
240
+ ],
241
+ [
242
+ "b",
243
+ [ops.defaultValue, [[[ops.params, 0], 0], 1], [ops.literal, 2]],
244
+ ],
245
+ ],
246
+ [
247
+ ops.addition,
248
+ [markers.traverse, [markers.reference, "a"]],
249
+ [markers.traverse, [markers.reference, "b"]],
250
+ ],
251
+ ]);
252
+ assertParse("arrowFunction", "([head, ...tail]) => tail", [
253
+ ops.lambda,
254
+ 1,
255
+ [
256
+ ["head", [[[ops.params, 0], 0], 0]],
257
+ ["tail", [[[[ops.params, 0], 0], "slice"], 1]],
258
+ ],
259
+ [markers.traverse, [markers.reference, "tail"]],
260
+ ]);
261
+ assertParse("arrowFunction", "(head, ...{ length }) => length", [
262
+ ops.lambda,
263
+ 1,
264
+ [
265
+ ["head", [[ops.params, 0], 0]],
266
+ ["length", [[[[ops.params, 0], "slice"], 1], "length"]],
267
+ ],
268
+ [markers.traverse, [markers.reference, "length"]],
269
+ ]);
270
+ assertThrows(
271
+ "arrowFunction",
272
+ "([a, a]) => a",
273
+ `Duplicate parameter name "a"`
274
+ );
275
+ });
276
+
277
+ test("object parameter destructuring", () => {
278
+ assertParse("arrowFunction", "({ a, b: c }) => a + c", [
279
+ ops.lambda,
280
+ 1,
281
+ [
282
+ ["a", [[[ops.params, 0], 0], "a"]],
283
+ ["c", [[[ops.params, 0], 0], "b"]],
284
+ ],
285
+ [
286
+ ops.addition,
287
+ [markers.traverse, [markers.reference, "a"]],
288
+ [markers.traverse, [markers.reference, "c"]],
289
+ ],
290
+ ]);
291
+ assertParse("arrowFunction", "({ a: { b: { c }}}) => c", [
292
+ ops.lambda,
293
+ 1,
294
+ [["c", [[[[[ops.params, 0], 0], "a"], "b"], "c"]]],
295
+ [markers.traverse, [markers.reference, "c"]],
296
+ ]);
297
+ assertParse("arrowFunction", "({ a = 1 }) => a", [
298
+ ops.lambda,
299
+ 1,
300
+ [
301
+ [
302
+ "a",
303
+ [ops.defaultValue, [[[ops.params, 0], 0], "a"], [ops.literal, 1]],
304
+ ],
305
+ ],
306
+ [markers.traverse, [markers.reference, "a"]],
307
+ ]);
308
+ assertParse("arrowFunction", "({ a, b, ...rest }) => rest", [
309
+ ops.lambda,
310
+ 1,
311
+ [
312
+ ["a", [[[ops.params, 0], 0], "a"]],
313
+ ["b", [[[ops.params, 0], 0], "b"]],
314
+ [
315
+ "rest",
316
+ [ops.objectRest, [[ops.params, 0], 0], [ops.array, "a", "b"]],
317
+ ],
318
+ ],
319
+ [markers.traverse, [markers.reference, "rest"]],
320
+ ]);
321
+ assertThrows(
322
+ "arrowFunction",
323
+ "({ a: c, b: c }) => c",
324
+ `Duplicate parameter name "c"`
325
+ );
326
+ });
327
+
328
+ test("functional arrow functions", () => {
329
+ assertParse("arrowFunction", "a => b => fn(a, b)", [
330
+ ops.lambda,
331
+ 1,
332
+ [["a", [[ops.params, 0], 0]]],
333
+ [
334
+ ops.lambda,
335
+ 1,
336
+ [["b", [[ops.params, 0], 0]]],
337
+ [
338
+ [markers.traverse, [markers.reference, "fn"]],
339
+ [markers.traverse, [markers.reference, "a"]],
340
+ [markers.traverse, [markers.reference, "b"]],
341
+ ],
342
+ ],
343
+ ]);
344
+ });
163
345
  });
164
346
 
165
347
  test("bitwiseAndExpression", () => {
@@ -187,7 +369,181 @@ describe("Origami parser", () => {
187
369
  });
188
370
 
189
371
  describe("callExpression", () => {
190
- test("with parentheses arguments", () => {
372
+ test("call chains", () => {
373
+ assertParse("callExpression", "(foo.js())('arg')", [
374
+ [[markers.traverse, [markers.reference, "foo.js"]], undefined],
375
+ [ops.literal, "arg"],
376
+ ]);
377
+ assertParse("callExpression", "fn('a')('b')", [
378
+ [
379
+ [markers.traverse, [markers.reference, "fn"]],
380
+ [ops.literal, "a"],
381
+ ],
382
+ [ops.literal, "b"],
383
+ ]);
384
+ assertParse("callExpression", "(foo.js())(a, b)", [
385
+ [[markers.traverse, [markers.reference, "foo.js"]], undefined],
386
+ [markers.traverse, [markers.reference, "a"]],
387
+ [markers.traverse, [markers.reference, "b"]],
388
+ ]);
389
+ assertParse("callExpression", "fn (x) (y) (z)", [
390
+ [
391
+ [
392
+ [markers.traverse, [markers.reference, "fn"]],
393
+ [markers.traverse, [markers.reference, "x"]],
394
+ ],
395
+ [markers.traverse, [markers.reference, "y"]],
396
+ ],
397
+ [markers.traverse, [markers.reference, "z"]],
398
+ ]);
399
+ });
400
+
401
+ test("optional property access", () => {
402
+ assertParse("callExpression", "a?.b.c", [
403
+ ops.optional,
404
+ [markers.traverse, [markers.reference, "a"]],
405
+ [
406
+ ops.lambda,
407
+ 1,
408
+ [["__optional__", [[ops.params, 0], 0]]],
409
+ [
410
+ ops.property,
411
+ [
412
+ ops.property,
413
+ [markers.traverse, [markers.reference, "__optional__"]],
414
+ [ops.literal, "b"],
415
+ ],
416
+ [ops.literal, "c"],
417
+ ],
418
+ ],
419
+ ]);
420
+ assertParse("callExpression", "a?.b?.c", [
421
+ ops.optional,
422
+ [markers.traverse, [markers.reference, "a"]],
423
+ [
424
+ ops.lambda,
425
+ 1,
426
+ [["__optional__", [[ops.params, 0], 0]]],
427
+ [
428
+ ops.optional,
429
+ [
430
+ ops.property,
431
+ [markers.traverse, [markers.reference, "__optional__"]],
432
+ [ops.literal, "b"],
433
+ ],
434
+ [
435
+ ops.lambda,
436
+ 1,
437
+ [["__optional__", [[ops.params, 0], 0]]],
438
+ [
439
+ ops.property,
440
+ [markers.traverse, [markers.reference, "__optional__"]],
441
+ [ops.literal, "c"],
442
+ ],
443
+ ],
444
+ ],
445
+ ],
446
+ ]);
447
+ });
448
+
449
+ test("optional computed property access", () => {
450
+ assertParse("callExpression", "a?.[key]", [
451
+ ops.optional,
452
+ [markers.traverse, [markers.reference, "a"]],
453
+ [
454
+ ops.lambda,
455
+ 1,
456
+ [["__optional__", [[ops.params, 0], 0]]],
457
+ [
458
+ ops.property,
459
+ [markers.traverse, [markers.reference, "__optional__"]],
460
+ [markers.traverse, [markers.reference, "key"]],
461
+ ],
462
+ ],
463
+ ]);
464
+ });
465
+
466
+ test("optional parentheses call", () => {
467
+ assertParse("callExpression", "fn?.(0)", [
468
+ ops.optional,
469
+ [markers.traverse, [markers.reference, "fn"]],
470
+ [
471
+ ops.lambda,
472
+ 1,
473
+ [["__optional__", [[ops.params, 0], 0]]],
474
+ [
475
+ [markers.traverse, [markers.reference, "__optional__"]],
476
+ [ops.literal, 0],
477
+ ],
478
+ ],
479
+ ]);
480
+ });
481
+
482
+ test("paramArray", () => {
483
+ assertParse("paramArray", "[a, b, c]", [
484
+ markers.paramArray,
485
+ [markers.paramName, "a"],
486
+ [markers.paramName, "b"],
487
+ [markers.paramName, "c"],
488
+ ]);
489
+ assertParse("paramArray", "[a, , b]", [
490
+ markers.paramArray,
491
+ [markers.paramName, "a"],
492
+ undefined,
493
+ [markers.paramName, "b"],
494
+ ]);
495
+ assertParse("paramArray", "[head, ...tail]", [
496
+ markers.paramArray,
497
+ [markers.paramName, "head"],
498
+ [markers.paramRest, [markers.paramName, "tail"]],
499
+ ]);
500
+ });
501
+
502
+ test("paramArrayEntry", () => {
503
+ assertParse("paramArrayEntry", "a", [markers.paramName, "a"]);
504
+ assertParse("paramArrayEntry", "a = 1", [
505
+ markers.paramInitializer,
506
+ [markers.paramName, "a"],
507
+ [ops.literal, 1],
508
+ ]);
509
+ assertThrows("paramArrayEntry", "...rest", `but "." found`);
510
+ });
511
+
512
+ test("paramObject", () => {
513
+ assertParse("paramObject", "{}", [markers.paramObject]);
514
+ assertParse("paramObject", "{ a, b: c }", [
515
+ markers.paramObject,
516
+ ["a", [markers.paramName, "a"]],
517
+ ["b", [markers.paramName, "c"]],
518
+ ]);
519
+ assertParse("paramObject", "{ a, b: { c } }", [
520
+ markers.paramObject,
521
+ ["a", [markers.paramName, "a"]],
522
+ ["b", [markers.paramObject, ["c", [markers.paramName, "c"]]]],
523
+ ]);
524
+ });
525
+
526
+ test("paramObjectEntry", () => {
527
+ assertParse("paramObjectEntry", "a", ["a", [markers.paramName, "a"]]);
528
+ assertParse("paramObjectEntry", "a: b", ["a", [markers.paramName, "b"]]);
529
+ assertParse("paramObjectEntry", "[key]: param", [
530
+ [markers.traverse, [markers.reference, "key"]],
531
+ [markers.paramName, "param"],
532
+ ]);
533
+ assertParse("paramObjectEntry", "a = 1", [
534
+ "a",
535
+ [markers.paramInitializer, [markers.paramName, "a"], [ops.literal, 1]],
536
+ ]);
537
+ });
538
+
539
+ test("paramRest", () => {
540
+ assertParse("paramRest", "...rest", [
541
+ markers.paramRest,
542
+ [markers.paramName, "rest"],
543
+ ]);
544
+ });
545
+
546
+ test("parentheses arguments", () => {
191
547
  assertParse("callExpression", "fn()", [
192
548
  [markers.traverse, [markers.reference, "fn"]],
193
549
  undefined,
@@ -212,26 +568,20 @@ describe("Origami parser", () => {
212
568
  ]);
213
569
  });
214
570
 
215
- test("call chains", () => {
216
- assertParse("callExpression", "(foo.js())('arg')", [
217
- [[markers.traverse, [markers.reference, "foo.js"]], undefined],
218
- [ops.literal, "arg"],
219
- ]);
220
- assertParse("callExpression", "fn('a')('b')", [
571
+ test("parentheses arguments with spreads", () => {
572
+ assertParse("callExpression", "fn(a, ...b, ...c)", [
573
+ [ops.property, [markers.traverse, [markers.reference, "fn"]], "apply"],
574
+ null,
221
575
  [
222
- [markers.traverse, [markers.reference, "fn"]],
223
- [ops.literal, "a"],
576
+ ops.flat,
577
+ [ops.array, [markers.traverse, [markers.reference, "a"]]],
578
+ [markers.traverse, [markers.reference, "b"]],
579
+ [markers.traverse, [markers.reference, "c"]],
224
580
  ],
225
- [ops.literal, "b"],
226
- ]);
227
- assertParse("callExpression", "(foo.js())(a, b)", [
228
- [[markers.traverse, [markers.reference, "foo.js"]], undefined],
229
- [markers.traverse, [markers.reference, "a"]],
230
- [markers.traverse, [markers.reference, "b"]],
231
581
  ]);
232
582
  });
233
583
 
234
- test("with paths", () => {
584
+ test("paths", () => {
235
585
  assertParse("callExpression", "tree/", [
236
586
  markers.traverse,
237
587
  [markers.reference, "tree/"],
@@ -292,17 +642,6 @@ describe("Origami parser", () => {
292
642
  ]);
293
643
  });
294
644
 
295
- test("tagged templates", () => {
296
- assertParse("callExpression", "indent`hello`", [
297
- [markers.traverse, [markers.reference, "indent"]],
298
- [ops.literal, ["hello"]],
299
- ]);
300
- assertParse("callExpression", "fn.js`Hello, world.`", [
301
- [markers.traverse, [markers.reference, "fn.js"]],
302
- [ops.literal, ["Hello, world."]],
303
- ]);
304
- });
305
-
306
645
  test("protocols", () => {
307
646
  assertParse("callExpression", "files:src/assets", [
308
647
  [markers.global, "files:"],
@@ -318,6 +657,17 @@ describe("Origami parser", () => {
318
657
  [ops.literal, "env"],
319
658
  ]);
320
659
  });
660
+
661
+ test("tagged templates", () => {
662
+ assertParse("callExpression", "indent`hello`", [
663
+ [markers.traverse, [markers.reference, "indent"]],
664
+ [ops.literal, ["hello"]],
665
+ ]);
666
+ assertParse("callExpression", "fn.js`Hello, world.`", [
667
+ [markers.traverse, [markers.reference, "fn.js"]],
668
+ [ops.literal, ["Hello, world."]],
669
+ ]);
670
+ });
321
671
  });
322
672
 
323
673
  test("commaExpression", () => {
@@ -341,13 +691,13 @@ describe("Origami parser", () => {
341
691
  assertParse("conditionalExpression", "false ? () => 1 : 0", [
342
692
  ops.conditional,
343
693
  [markers.traverse, [markers.reference, "false"]],
344
- [ops.lambda, [], [ops.lambda, [], [ops.literal, 1]]],
694
+ [ops.lambda, 0, [], [ops.lambda, 0, [], [ops.literal, 1]]],
345
695
  [ops.literal, 0],
346
696
  ]);
347
697
  assertParse("conditionalExpression", "false ? () => 1 : 0", [
348
698
  ops.conditional,
349
699
  [markers.traverse, [markers.reference, "false"]],
350
- [ops.lambda, [], [ops.lambda, [], [ops.literal, 1]]],
700
+ [ops.lambda, 0, [], [ops.lambda, 0, [], [ops.literal, 1]]],
351
701
  [ops.literal, 0],
352
702
  ]);
353
703
  });
@@ -380,6 +730,7 @@ describe("Origami parser", () => {
380
730
  assertThrows("callExpression", "fn(a", "Expected right parenthesis");
381
731
  assertThrows("doubleQuoteString", '"foo', "Expected closing quote");
382
732
  assertThrows("guillemetString", "«foo", "Expected closing guillemet");
733
+ assertThrows("guillemetString", "»foo", "Expected closing guillemet");
383
734
  assertThrows("objectGetter", "a =", "Expected an expression");
384
735
  assertThrows("objectProperty", "a:", "Expected an expression");
385
736
  assertThrows("singleQuoteString", "'foo", "Expected closing quote");
@@ -558,7 +909,8 @@ Body`,
558
909
  [markers.traverse, [markers.reference, "fn"]],
559
910
  [
560
911
  ops.lambda,
561
- [[ops.literal, "_"]],
912
+ 1,
913
+ [["_", [[ops.params, 0], 0]]],
562
914
  [ops.templateText, [ops.literal, ["x"]]],
563
915
  ],
564
916
  ]);
@@ -577,7 +929,8 @@ Body`,
577
929
  [markers.traverse, [markers.reference, "map"]],
578
930
  [
579
931
  ops.lambda,
580
- [[ops.literal, "_"]],
932
+ 1,
933
+ [["_", [[ops.params, 0], 0]]],
581
934
  [
582
935
  ops.templateText,
583
936
  [ops.literal, ["<li>", "</li>"]],
@@ -597,7 +950,8 @@ Body`,
597
950
  ]);
598
951
  assertParse("expression", "=tag`Hello, ${_}!`", [
599
952
  ops.lambda,
600
- [[ops.literal, "_"]],
953
+ 1,
954
+ [["_", [[ops.params, 0], 0]]],
601
955
  [
602
956
  [markers.traverse, [markers.reference, "tag"]],
603
957
  [ops.literal, ["Hello, ", "!"]],
@@ -606,9 +960,10 @@ Body`,
606
960
  ]);
607
961
  assertParse("expression", "(post, slug) => fn.js(post, slug)", [
608
962
  ops.lambda,
963
+ 2,
609
964
  [
610
- [ops.literal, "post"],
611
- [ops.literal, "slug"],
965
+ ["post", [[ops.params, 0], 0]],
966
+ ["slug", [[ops.params, 0], 1]],
612
967
  ],
613
968
  [
614
969
  [markers.traverse, [markers.reference, "fn.js"]],
@@ -678,7 +1033,8 @@ Body`,
678
1033
  `,
679
1034
  [
680
1035
  ops.lambda,
681
- [[ops.literal, "name"]],
1036
+ 1,
1037
+ [["name", [[ops.params, 0], 0]]],
682
1038
  [[markers.traverse, [markers.reference, "_template"]], undefined],
683
1039
  ],
684
1040
  "program",
@@ -768,6 +1124,24 @@ Body`,
768
1124
  [ops.literal, "arg"],
769
1125
  ],
770
1126
  ]);
1127
+ assertParse(
1128
+ "implicitParenthesesCallExpression",
1129
+ "concat a.json, ...b.json, c.json",
1130
+ [
1131
+ [
1132
+ ops.property,
1133
+ [markers.traverse, [markers.reference, "concat"]],
1134
+ "apply",
1135
+ ],
1136
+ null,
1137
+ [
1138
+ ops.flat,
1139
+ [ops.array, [markers.traverse, [markers.reference, "a.json"]]],
1140
+ [markers.traverse, [markers.reference, "b.json"]],
1141
+ [ops.array, [markers.traverse, [markers.reference, "c.json"]]],
1142
+ ],
1143
+ ]
1144
+ );
771
1145
  });
772
1146
 
773
1147
  test("key", () => {
@@ -780,42 +1154,14 @@ Body`,
780
1154
  assertParse("key", "a~b", "a~b");
781
1155
  assertParse("key", "foo-bar", "foo-bar");
782
1156
  assertParse("key", "package-lock.json", "package-lock.json");
783
- });
784
-
785
- test("list", () => {
786
- assertParse("list", "1", [[ops.literal, 1]]);
787
- assertParse("list", "1,2,3", [
788
- [ops.literal, 1],
789
- [ops.literal, 2],
790
- [ops.literal, 3],
791
- ]);
792
- assertParse("list", "1, 2, 3,", [
793
- [ops.literal, 1],
794
- [ops.literal, 2],
795
- [ops.literal, 3],
796
- ]);
797
- assertParse("list", "1 , 2 , 3", [
798
- [ops.literal, 1],
799
- [ops.literal, 2],
800
- [ops.literal, 3],
801
- ]);
802
- assertParse("list", "1\n2\n3", [
803
- [ops.literal, 1],
804
- [ops.literal, 2],
805
- [ops.literal, 3],
806
- ]);
807
- assertParse("list", "'a' , 'b' , 'c'", [
808
- [ops.literal, "a"],
809
- [ops.literal, "b"],
810
- [ops.literal, "c"],
811
- ]);
1157
+ assertThrows("key", "...rest", `but "." found`);
812
1158
  });
813
1159
 
814
1160
  test("logicalAndExpression", () => {
815
1161
  assertParse("logicalAndExpression", "true && false", [
816
1162
  ops.logicalAnd,
817
1163
  [markers.traverse, [markers.reference, "true"]],
818
- [ops.lambda, [], [markers.traverse, [markers.reference, "false"]]],
1164
+ [ops.lambda, 0, [], [markers.traverse, [markers.reference, "false"]]],
819
1165
  ]);
820
1166
  });
821
1167
 
@@ -828,13 +1174,13 @@ Body`,
828
1174
  assertParse("logicalOrExpression", "false || false || true", [
829
1175
  ops.logicalOr,
830
1176
  [markers.traverse, [markers.reference, "false"]],
831
- [ops.lambda, [], [markers.traverse, [markers.reference, "false"]]],
832
- [ops.lambda, [], [markers.traverse, [markers.reference, "true"]]],
1177
+ [ops.lambda, 0, [], [markers.traverse, [markers.reference, "false"]]],
1178
+ [ops.lambda, 0, [], [markers.traverse, [markers.reference, "true"]]],
833
1179
  ]);
834
1180
  assertParse("logicalOrExpression", "1 || 2 && 0", [
835
1181
  ops.logicalOr,
836
1182
  [ops.literal, 1],
837
- [ops.lambda, [], [ops.logicalAnd, [ops.literal, 2], [ops.literal, 0]]],
1183
+ [ops.lambda, 0, [], [ops.logicalAnd, [ops.literal, 2], [ops.literal, 0]]],
838
1184
  ]);
839
1185
  });
840
1186
 
@@ -881,24 +1227,38 @@ Body`,
881
1227
  assertParse("nullishCoalescingExpression", "a ?? b", [
882
1228
  ops.nullishCoalescing,
883
1229
  [markers.traverse, [markers.reference, "a"]],
884
- [ops.lambda, [], [markers.traverse, [markers.reference, "b"]]],
1230
+ [ops.lambda, 0, [], [markers.traverse, [markers.reference, "b"]]],
885
1231
  ]);
886
1232
  assertParse("nullishCoalescingExpression", "a ?? b ?? c", [
887
1233
  ops.nullishCoalescing,
888
1234
  [markers.traverse, [markers.reference, "a"]],
889
- [ops.lambda, [], [markers.traverse, [markers.reference, "b"]]],
890
- [ops.lambda, [], [markers.traverse, [markers.reference, "c"]]],
1235
+ [ops.lambda, 0, [], [markers.traverse, [markers.reference, "b"]]],
1236
+ [ops.lambda, 0, [], [markers.traverse, [markers.reference, "c"]]],
891
1237
  ]);
892
1238
  });
893
1239
 
894
- test("numericLiteral", () => {
895
- assertParse("numericLiteral", "123", [ops.literal, 123]);
896
- assertParse("numericLiteral", ".5", [ops.literal, 0.5]);
897
- assertParse("numericLiteral", "123.45", [ops.literal, 123.45]);
1240
+ test("numberLiteral", () => {
1241
+ assertParse("numberLiteral", "123", [ops.literal, 123]);
1242
+ });
1243
+
1244
+ test("number", () => {
1245
+ assertParse("number", "123", 123, undefined, false);
1246
+ assertParse("number", ".5", 0.5, undefined, false);
1247
+ assertParse("number", "123.45", 123.45, undefined, false);
1248
+ assertParse("number", "123_456", 123456, undefined, false);
1249
+ assertParse("number", "0e-5", 0e-5, undefined, false);
1250
+ assertParse("number", "175e-2", 175e-2, undefined, false);
1251
+ assertParse("number", "1e-3", 1e-3, undefined, false);
1252
+ assertParse("number", "123n", 123n, undefined, false);
1253
+ assertParse("number", "0b1010", 0b1010, undefined, false);
1254
+ assertParse("number", "0b100_100", 0b100100, undefined, false);
1255
+ assertParse("number", "0o755", 0o755, undefined, false);
1256
+ assertParse("number", "0x1A3F", 0x1a3f, undefined, false);
1257
+ assertParse("number", "0x1a_3f", 0x1a3f, undefined, false);
898
1258
  });
899
1259
 
900
1260
  describe("objectLiteral", () => {
901
- describe("basic objects", () => {
1261
+ test("basic objects", () => {
902
1262
  assertParse("objectLiteral", "{}", [ops.object]);
903
1263
  assertParse("objectLiteral", "{ a: 1, b }", [
904
1264
  ops.object,
@@ -991,7 +1351,7 @@ Body`,
991
1351
  ]);
992
1352
  });
993
1353
 
994
- describe("spreads", () => {
1354
+ test("spreads", () => {
995
1355
  assertParse("objectLiteral", "{ ...x }", [
996
1356
  ops.unpack,
997
1357
  [markers.traverse, [markers.reference, "x"]],
@@ -1019,6 +1379,16 @@ Body`,
1019
1379
  ["b", [ops.literal, 2]],
1020
1380
  ]);
1021
1381
  });
1382
+
1383
+ test("computed property keys", () => {
1384
+ assertParse("objectLiteral", "{ [key]: value }", [
1385
+ ops.object,
1386
+ [
1387
+ [markers.traverse, [markers.reference, "key"]],
1388
+ [markers.traverse, [markers.reference, "value"]],
1389
+ ],
1390
+ ]);
1391
+ });
1022
1392
  });
1023
1393
 
1024
1394
  describe("objectEntry", () => {
@@ -1068,7 +1438,8 @@ Body`,
1068
1438
  "a",
1069
1439
  [
1070
1440
  ops.lambda,
1071
- [[ops.literal, "a"]],
1441
+ 1,
1442
+ [["a", [[ops.params, 0], 0]]],
1072
1443
  [markers.traverse, [markers.reference, "a"]],
1073
1444
  ],
1074
1445
  ]);
@@ -1122,12 +1493,17 @@ Body`,
1122
1493
  assertParse("objectPublicKey", `"foo bar"`, "foo bar", "shell", false);
1123
1494
  });
1124
1495
 
1125
- // test.skip("optionalChaining", () => {
1126
- // assertParse("optionalChaining", "?.key", [
1127
- // ops.optionalTraverse,
1128
- // [ops.literal, "key"],
1129
- // ]);
1130
- // });
1496
+ test("optional", () => {
1497
+ assertParse("optional", "?.key", [
1498
+ ops.optional,
1499
+ [markers.property, [ops.literal, "key"]],
1500
+ ]);
1501
+ assertParse("optional", "?.[index]", [
1502
+ ops.optional,
1503
+ [markers.property, [markers.traverse, [markers.reference, "index"]]],
1504
+ ]);
1505
+ assertParse("optional", "?.(0)", [ops.optional, [[ops.literal, 0]]]);
1506
+ });
1131
1507
 
1132
1508
  test("parenthesesArguments", () => {
1133
1509
  assertParse("parenthesesArguments", "()", [undefined]);
@@ -1138,6 +1514,40 @@ Body`,
1138
1514
  ]);
1139
1515
  });
1140
1516
 
1517
+ test("parenthesesArgumentList", () => {
1518
+ assertParse("parenthesesArgumentList", "1", [[ops.literal, 1]]);
1519
+ assertParse("parenthesesArgumentList", "1,2,3", [
1520
+ [ops.literal, 1],
1521
+ [ops.literal, 2],
1522
+ [ops.literal, 3],
1523
+ ]);
1524
+ assertParse("parenthesesArgumentList", "1, 2, 3,", [
1525
+ [ops.literal, 1],
1526
+ [ops.literal, 2],
1527
+ [ops.literal, 3],
1528
+ ]);
1529
+ assertParse("parenthesesArgumentList", "1 , 2 , 3", [
1530
+ [ops.literal, 1],
1531
+ [ops.literal, 2],
1532
+ [ops.literal, 3],
1533
+ ]);
1534
+ assertParse("parenthesesArgumentList", "1\n2\n3", [
1535
+ [ops.literal, 1],
1536
+ [ops.literal, 2],
1537
+ [ops.literal, 3],
1538
+ ]);
1539
+ assertParse("parenthesesArgumentList", "'a' , 'b' , 'c'", [
1540
+ [ops.literal, "a"],
1541
+ [ops.literal, "b"],
1542
+ [ops.literal, "c"],
1543
+ ]);
1544
+ assertParse("parenthesesArgumentList", "a, ...b, c", [
1545
+ [markers.traverse, [markers.reference, "a"]],
1546
+ [markers.spread, [markers.traverse, [markers.reference, "b"]]],
1547
+ [markers.traverse, [markers.reference, "c"]],
1548
+ ]);
1549
+ });
1550
+
1141
1551
  test("pathKeys", () => {
1142
1552
  assertParse(
1143
1553
  "pathKeys",
@@ -1326,12 +1736,14 @@ Body`,
1326
1736
  test("shorthandFunction", () => {
1327
1737
  assertParse("shorthandFunction", "=message", [
1328
1738
  ops.lambda,
1329
- [[ops.literal, "_"]],
1739
+ 1,
1740
+ [["_", [[ops.params, 0], 0]]],
1330
1741
  [markers.traverse, [markers.reference, "message"]],
1331
1742
  ]);
1332
1743
  assertParse("shorthandFunction", "=`Hello, ${name}.`", [
1333
1744
  ops.lambda,
1334
- [[ops.literal, "_"]],
1745
+ 1,
1746
+ [["_", [[ops.params, 0], 0]]],
1335
1747
  [
1336
1748
  ops.templateText,
1337
1749
  [ops.literal, ["Hello, ", "."]],
@@ -1340,7 +1752,8 @@ Body`,
1340
1752
  ]);
1341
1753
  assertParse("shorthandFunction", "=indent`hello`", [
1342
1754
  ops.lambda,
1343
- [[ops.literal, "_"]],
1755
+ 1,
1756
+ [["_", [[ops.params, 0], 0]]],
1344
1757
  [
1345
1758
  [markers.traverse, [markers.reference, "indent"]],
1346
1759
  [ops.literal, ["hello"]],
@@ -1360,7 +1773,7 @@ Body`,
1360
1773
 
1361
1774
  test("spreadElement", () => {
1362
1775
  assertParse("spreadElement", "...a", [
1363
- ops.spread,
1776
+ markers.spread,
1364
1777
  [markers.traverse, [markers.reference, "a"]],
1365
1778
  ]);
1366
1779
  });
@@ -1373,6 +1786,7 @@ Body`,
1373
1786
  assertParse("stringLiteral", `"foo\\"s bar"`, [ops.literal, `foo"s bar`]);
1374
1787
  assertParse("stringLiteral", `'bar\\'s baz'`, [ops.literal, `bar's baz`]);
1375
1788
  assertParse("stringLiteral", `«string»`, [ops.literal, "string"]);
1789
+ assertParse("stringLiteral", `»string«`, [ops.literal, "string"]);
1376
1790
  assertParse("stringLiteral", `"\\0\\b\\f\\n\\r\\t\\v"`, [
1377
1791
  ops.literal,
1378
1792
  "\0\b\f\n\r\t\v",
@@ -1394,7 +1808,8 @@ Body`,
1394
1808
  test("templateDocument with no front matter", () => {
1395
1809
  assertParse("templateDocument", "Hello, world!", [
1396
1810
  ops.lambda,
1397
- [[ops.literal, "_"]],
1811
+ 1,
1812
+ [["_", [[ops.params, 0], 0]]],
1398
1813
  [ops.templateIndent, [ops.literal, ["Hello, world!"]]],
1399
1814
  ]);
1400
1815
  });
@@ -1441,32 +1856,6 @@ Body text`,
1441
1856
  );
1442
1857
  });
1443
1858
 
1444
- test.skip("templateDocument with Origami front matter", () => {
1445
- assertParse(
1446
- "templateDocument",
1447
- `---
1448
- {
1449
- title: "Title"
1450
- _body: _template()
1451
- }
1452
- ---
1453
- <h1>\${ title }</h1>
1454
- `,
1455
- [
1456
- ops.object,
1457
- ["title", [ops.literal, "Title"]],
1458
- [
1459
- "_body",
1460
- [
1461
- ops.templateIndent,
1462
- [ops.literal, ["<h1>", "</h1>\n"]],
1463
- [markers.traverse, [markers.reference, "title"]],
1464
- ],
1465
- ],
1466
- ]
1467
- );
1468
- });
1469
-
1470
1859
  test("templateLiteral", () => {
1471
1860
  assertParse("templateLiteral", "`Hello, world.`", [
1472
1861
  ops.templateText,
@@ -1494,7 +1883,8 @@ Body text`,
1494
1883
  [markers.traverse, [markers.reference, "people"]],
1495
1884
  [
1496
1885
  ops.lambda,
1497
- [[ops.literal, "_"]],
1886
+ 1,
1887
+ [["_", [[ops.params, 0], 0]]],
1498
1888
  [
1499
1889
  ops.templateText,
1500
1890
  [ops.literal, ["", ""]],