@danielx/civet 0.7.0 → 0.7.1

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.
Files changed (4) hide show
  1. package/dist/browser.js +2028 -1982
  2. package/dist/main.js +2028 -1982
  3. package/dist/main.mjs +2028 -1982
  4. package/package.json +1 -1
package/dist/browser.js CHANGED
@@ -41,1061 +41,629 @@ var Civet = (() => {
41
41
  ));
42
42
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
43
43
 
44
- // source/parser/op.civet
45
- function getPrecedence(op) {
46
- if (typeof op === "string") {
47
- return precedenceMap.get(op) ?? (() => {
48
- throw new Error(`Unknown operator: ${op}`);
49
- })();
50
- } else if (typeof op.prec === "number") {
51
- return op.prec;
52
- } else {
53
- return precedenceMap.get(op.prec ?? op.token) ?? (op.relational ? precedenceRelational : precedenceCustomDefault);
54
- }
55
- }
56
- function processBinaryOpExpression($0) {
57
- return recurse(expandChainedComparisons($0));
58
- function recurse(expandedOps) {
59
- let i = 2;
60
- while (i < expandedOps.length) {
61
- let op = expandedOps[i];
62
- if (op.special) {
63
- let advanceLeft2 = function(allowEqual) {
64
- while (start >= 4) {
65
- const prevPrec = getPrecedence(expandedOps[start - 2]);
66
- if (!(prevPrec > prec || allowEqual && prevPrec === prec)) {
67
- return prevPrec === prec;
68
- }
69
- start -= 4;
70
- }
71
- return false;
72
- }, advanceRight2 = function(allowEqual) {
73
- while (end + 4 < expandedOps.length) {
74
- const nextPrec = getPrecedence(expandedOps[end + 2]);
75
- if (!(nextPrec > prec || allowEqual && nextPrec === prec)) {
76
- return nextPrec === prec;
77
- }
78
- end += 4;
79
- }
80
- return false;
81
- };
82
- var advanceLeft = advanceLeft2, advanceRight = advanceRight2;
83
- let start = i - 2, end = i + 2;
84
- const prec = getPrecedence(op);
85
- let error;
86
- switch (op.assoc) {
87
- case "left":
88
- case void 0: {
89
- advanceLeft2(true);
90
- advanceRight2(false);
91
- break;
92
- }
93
- case "right": {
94
- advanceLeft2(false);
95
- advanceRight2(true);
96
- break;
97
- }
98
- case "non": {
99
- if (advanceLeft2(false) || advanceRight2(false)) {
100
- error = {
101
- type: "Error",
102
- message: `non-associative operator ${op.token} used at same precedence level without parenthesization`
103
- };
104
- }
105
- ;
106
- break;
107
- }
108
- case "arguments": {
109
- if (advanceLeft2(false)) {
110
- error = {
111
- type: "Error",
112
- message: `arguments operator ${op.token} used at same precedence level as ${expandedOps[start - 2].token} to the left`
113
- };
114
- }
115
- advanceRight2(true);
116
- break;
117
- }
118
- default: {
119
- throw new Error(`Unsupported associativity: ${op.assoc}`);
120
- }
121
- }
122
- let a = start === i - 2 ? expandedOps[start] : expandedOps.slice(start, i - 1);
123
- let wsOp = expandedOps[i - 1];
124
- let wsB = expandedOps[i + 1];
125
- let b = end === i + 2 ? expandedOps[i + 2] : expandedOps.slice(i + 2, end + 1);
126
- if (op.assoc === "arguments") {
127
- let i2 = 2;
128
- while (i2 < b.length) {
129
- if (prec === getPrecedence(b[i2])) {
130
- if (!(b[i2].token === op.token)) {
131
- error ??= {
132
- type: "Error",
133
- message: `arguments operator ${op.token} used at same precedence level as ${b[i2].token} to the right`
134
- };
135
- }
136
- b[i2] = ",";
137
- }
138
- i2 += 4;
139
- }
140
- } else {
141
- b = recurse(b);
142
- }
143
- if (op.token === "instanceof" && b.type === "Literal" && b.children?.[0]?.type === "StringLiteral") {
144
- a = ["typeof ", makeLeftHandSideExpression(a)];
145
- if (op.negated) {
146
- op = { ...op, token: "!==", negated: false };
147
- } else {
148
- op = { ...op, token: "===" };
149
- }
150
- }
151
- if (op.asConst) {
152
- a = makeAsConst(a);
153
- b = makeAsConst(b);
154
- }
155
- let children;
156
- if (op.call) {
157
- wsOp = insertTrimmingSpace(wsOp, "");
158
- if (op.reversed) {
159
- wsB = insertTrimmingSpace(wsB, "");
160
- children = [wsOp, op.call, "(", wsB, b, ", ", a, ")", op.suffix];
161
- } else {
162
- children = [wsOp, op.call, "(", a, ",", wsB, b, ")", op.suffix];
163
- }
164
- } else if (op.method) {
165
- wsOp = insertTrimmingSpace(wsOp, "");
166
- wsB = insertTrimmingSpace(wsB, "");
167
- if (op.reversed) {
168
- if (end !== i + 2)
169
- b = makeLeftHandSideExpression(b);
170
- b = dotNumericLiteral(b);
171
- children = [wsB, b, wsOp, ".", op.method, "(", a, ")"];
172
- } else {
173
- if (start !== i - 2 || a.type === "NumericLiteral") {
174
- a = makeLeftHandSideExpression(a);
175
- }
176
- a = dotNumericLiteral(a);
177
- children = [a, wsOp, ".", op.method, "(", wsB, b, ")"];
178
- }
179
- } else if (op.token) {
180
- children = [a, wsOp, op, wsB, b];
181
- if (op.negated)
182
- children = ["(", ...children, ")"];
183
- } else {
184
- throw new Error("Unknown operator: " + JSON.stringify(op));
185
- }
186
- if (op.negated)
187
- children.unshift("!");
188
- if (error != null) {
189
- children.push(error);
190
- }
191
- expandedOps.splice(start, end - start + 1, {
192
- children
193
- });
194
- i = start + 2;
195
- } else {
196
- i += 4;
197
- }
198
- }
199
- return expandedOps;
200
- }
201
- ;
202
- return recurse;
203
- }
204
- function dotNumericLiteral(literal) {
205
- if (literal?.type === "Literal" && /^[+-]?(?:0|[1-9](?:_[0-9]|[0-9])*)$/.test(literal.raw)) {
206
- literal.children.push(".");
207
- literal.raw += ".";
208
- }
209
- return literal;
210
- }
211
- function makeAsConst(node) {
212
- if (Array.isArray(node) && node.length === 1) {
213
- node = node[0];
214
- }
215
- if (node.type === "Literal" && node.raw !== "null" || node.type === "ArrayExpression" || node.type === "ObjectExpression") {
216
- return { ...node, children: [...node.children, asConst] };
217
- } else {
218
- return node;
219
- }
220
- }
221
- function isExistence(exp) {
222
- if (exp?.type === "ParenthesizedExpression" && exp.implicit) {
223
- exp = exp.expression;
224
- }
225
- if (exp?.type === "Existence") {
226
- return exp;
227
- }
228
- ;
229
- return;
230
- }
231
- function isRelationalOp(op) {
232
- return op.relational || getPrecedence(op) === precedenceRelational;
233
- }
234
- function expandChainedComparisons([first, binops]) {
235
- if (!binops.length) {
236
- return [first];
237
- }
238
- const results = [];
239
- let start = 0;
240
- const chains = [];
241
- var i = 0;
242
- for (let i3 = 0, len2 = binops.length; i3 < len2; i3++) {
243
- var i = i3;
244
- var [, op] = binops[i3];
245
- if (isRelationalOp(op)) {
246
- chains.push(i);
247
- } else if (getPrecedence(op) < precedenceRelational) {
248
- processChains();
249
- first = results.pop();
250
- }
251
- }
252
- processChains();
253
- return results;
254
- function processChains() {
255
- if (chains.length > 0) {
256
- first = expandExistence(first);
257
- for (let i4 = 0, len3 = chains.length; i4 < len3; i4++) {
258
- const k = i4;
259
- const index = chains[i4];
260
- if (k > 0) {
261
- results.push(" ", "&&", " ");
262
- }
263
- const binop = binops[index];
264
- const exp = binop[3] = expandExistence(binop[3]);
265
- results.push(first);
266
- const endIndex = chains[k + 1] ?? i + 1;
267
- results.push(...binops.slice(start, endIndex).flat());
268
- first = [exp].concat(binops.slice(index + 1, endIndex));
269
- start = endIndex;
270
- }
271
- } else {
272
- results.push(first);
273
- results.push(...binops.slice(start, i + 1).flat());
274
- start = i + 1;
275
- }
276
- chains.length = 0;
277
- }
278
- function expandExistence(exp) {
279
- let ref;
280
- if (ref = isExistence(exp)) {
281
- const existence = ref;
282
- results.push(existence, " ", "&&", " ");
283
- return existence.expression;
284
- } else {
285
- return exp;
286
- }
287
- }
288
- ;
289
- }
290
- var precedenceOrder, precedenceMap, precedenceStep, precedenceRelational, precedenceCustomDefault, asConst;
291
- var init_op = __esm({
292
- "source/parser/op.civet"() {
293
- "use strict";
294
- init_util();
295
- precedenceOrder = [
296
- ["||", "??"],
297
- ["^^"],
298
- ["&&"],
299
- ["|"],
300
- ["^"],
301
- ["&"],
302
- // NOTE: Equality and inequality merged because of relational chaining
303
- [
304
- "==",
305
- "!=",
306
- "===",
307
- "!==",
308
- "<",
309
- "<=",
310
- ">",
311
- ">=",
312
- "in",
313
- "instanceof"
314
- ],
315
- // NOTE: Extra in-between level for default custom operators
316
- ["custom"],
317
- ["<<", ">>", ">>>"],
318
- ["+", "-"],
319
- ["*", "/", "%"],
320
- ["**"]
321
- ];
322
- precedenceMap = /* @__PURE__ */ new Map();
323
- for (let i1 = 0, len = precedenceOrder.length; i1 < len; i1++) {
324
- const prec = i1;
325
- const ops = precedenceOrder[i1];
326
- for (let i2 = 0, len1 = ops.length; i2 < len1; i2++) {
327
- const op = ops[i2];
328
- precedenceMap.set(op, prec);
329
- }
330
- }
331
- precedenceStep = 1 / 64;
332
- precedenceRelational = precedenceMap.get("==");
333
- precedenceCustomDefault = precedenceMap.get("custom");
334
- asConst = {
335
- ts: true,
336
- children: [" as const"]
337
- };
338
- }
339
- });
340
-
341
- // source/parser/unary.civet
342
- function processUnaryExpression(pre, exp, post) {
343
- if (!(pre.length || post))
344
- return exp;
345
- if (post?.token === "?") {
346
- post = {
347
- $loc: post.$loc,
348
- token: " != null"
349
- };
350
- if (pre.length) {
351
- const lastPre = pre.at(-1);
352
- if (lastPre.token === "!") {
353
- post.token = " == null";
354
- pre = pre.slice(0, -1);
355
- } else if (lastPre.length === 2 && lastPre[0].token === "!") {
356
- post.token = " == null";
357
- pre = pre.slice(0, -1);
358
- }
359
- }
360
- const existence = {
361
- type: "Existence",
362
- expression: exp,
363
- children: [exp, post],
364
- parent: void 0
365
- };
366
- exp = makeLeftHandSideExpression(existence);
367
- if (pre.length) {
368
- return {
369
- type: "UnaryExpression",
370
- children: [...pre, exp]
371
- };
372
- }
373
- return exp;
374
- }
375
- if (exp.type === "Literal") {
376
- if (pre.length === 1) {
377
- const { token } = pre[0];
378
- if (token === "-" || token === "+") {
379
- const children = [pre[0], ...exp.children];
380
- const literal = {
381
- type: "Literal",
382
- children,
383
- raw: `${token}${exp.raw}`
384
- };
385
- if (post) {
386
- return {
387
- type: "UnaryExpression",
388
- children: [literal, post]
389
- };
390
- }
391
- return literal;
392
- }
393
- }
394
- }
395
- let ref;
396
- while (ref = pre.length) {
397
- const l = ref;
398
- const last = pre[l - 1];
399
- if (last.type === "Await") {
400
- if (last.op) {
401
- if (exp.type !== "ParenthesizedExpression") {
402
- exp = ["(", exp, ")"];
403
- }
404
- exp = {
405
- type: "CallExpression",
406
- children: [...last.children, "Promise", last.op, exp]
407
- };
408
- pre = pre.slice(0, -1);
409
- } else {
410
- exp = {
411
- type: "AwaitExpression",
412
- children: [...last.children, exp]
413
- };
414
- pre = pre.slice(0, -1);
415
- }
416
- } else {
417
- break;
418
- }
419
- }
420
- return {
421
- type: "UnaryExpression",
422
- children: [...pre, exp, post]
423
- };
424
- }
425
- var init_unary = __esm({
426
- "source/parser/unary.civet"() {
427
- "use strict";
428
- init_util();
429
- }
430
- });
431
-
432
- // source/parser/util.civet
433
- function addParentPointers(node, parent) {
434
- if (node == null)
435
- return;
436
- if (typeof node !== "object")
437
- return;
438
- if (Array.isArray(node)) {
439
- for (const child of node) {
440
- addParentPointers(child, parent);
441
- }
442
- return;
443
- }
444
- node = node;
445
- node.parent = parent;
446
- if (node.children) {
447
- for (const child of node.children) {
448
- addParentPointers(child, node);
449
- }
450
- }
451
- }
452
- function clone(node) {
453
- removeParentPointers(node);
454
- return deepCopy(node);
455
- }
456
- function removeParentPointers(node) {
457
- if (node == null)
458
- return;
459
- if (typeof node !== "object")
460
- return;
461
- if (Array.isArray(node)) {
462
- for (const child of node) {
463
- removeParentPointers(child);
464
- }
465
- return;
466
- }
467
- node.parent = null;
468
- if (node.children) {
469
- for (const child of node.children) {
470
- removeParentPointers(child);
471
- }
472
- }
473
- }
474
- function maybeWrap(node, parent) {
475
- if (!isASTNodeObject(node)) {
476
- updateParentPointers(node = {
477
- type: "Wrapper",
478
- children: [node],
479
- parent
480
- });
481
- }
482
- return node;
483
- }
484
- function maybeUnwrap(node) {
485
- if (node?.type === "Wrapper") {
486
- return node.children[0];
487
- } else {
488
- return node;
489
- }
490
- }
491
- function isASTNodeObject(node) {
492
- return typeof node === "object" && node != null && !Array.isArray(node);
493
- }
494
- function isParent(node) {
495
- return node != null && node.children != null;
496
- }
497
- function isToken(node) {
498
- return node != null && node.token != null;
499
- }
500
- function isEmptyBareBlock(node) {
501
- if (node?.type !== "BlockStatement")
502
- return false;
503
- const { bare, expressions } = node;
504
- return bare && (expressions.length === 0 || expressions.length === 1 && expressions[0][1]?.type === "EmptyStatement");
505
- }
506
- function isFunction(node) {
507
- const { type } = node;
508
- return type === "FunctionExpression" || type === "ArrowFunction" || type === "MethodDefinition" || !!node.async;
509
- }
510
- function isWhitespaceOrEmpty(node) {
511
- if (!node)
512
- return true;
513
- if (node.type === "Ref")
514
- return false;
515
- if (node.token)
516
- return node.token.match(/^\s*$/);
517
- if (node.children)
518
- node = node.children;
519
- if (!node.length)
520
- return true;
521
- if (typeof node === "string")
522
- return node.match(/^\s*$/);
523
- if (Array.isArray(node))
524
- return node.every(isWhitespaceOrEmpty);
525
- return;
526
- }
527
- function isExit(node) {
528
- if (!(node != null)) {
529
- return false;
530
- }
531
- switch (node.type) {
532
- case "ReturnStatement":
533
- case "ThrowStatement":
534
- case "BreakStatement":
535
- case "ContinueStatement": {
536
- return true;
537
- }
538
- case "IfStatement": {
539
- return isExit(node.then) && isExit(node.else?.at(-1));
540
- }
541
- case "BlockStatement": {
542
- return isExit(node.expressions.at(-1)?.[1]);
543
- }
544
- case "IterationStatement": {
545
- return node.condition?.type === "ParenthesizedExpression" && node.condition.expression?.type === "Literal" && node.condition.expression?.raw === "true" && gatherRecursiveWithinFunction(
546
- node.block,
547
- ({ type }) => type === "BreakStatement"
548
- ).length === 0;
44
+ // source/parser/binding.civet
45
+ function adjustAtBindings(statements, asThis = false) {
46
+ gatherRecursiveAll(statements, (n) => n.type === "AtBindingProperty").forEach((binding) => {
47
+ const { ref } = binding;
48
+ if (asThis) {
49
+ const atBinding = binding.binding;
50
+ atBinding.children.pop();
51
+ atBinding.type = void 0;
52
+ binding.children.unshift(ref.id, ": this.", ref.base);
53
+ binding.type = "Property";
54
+ binding.ref = void 0;
55
+ return;
549
56
  }
550
- default: {
551
- return false;
57
+ if (ref.names[0] !== ref.base) {
58
+ return binding.children.unshift(ref.base, ": ");
552
59
  }
553
- }
554
- }
555
- function isComma(node) {
556
- if (node?.token === ",") {
557
- return node;
558
- } else if (Array.isArray(node) && node.at(-1)?.token === ",") {
559
- return node.at(-1);
560
- }
561
- ;
562
- return;
60
+ ;
61
+ return;
62
+ });
563
63
  }
564
- function insertTrimmingSpace(target, c) {
565
- if (!(target != null)) {
566
- return target;
567
- }
568
- if (Array.isArray(target)) {
569
- if (target.length === 0) {
570
- return c;
64
+ function adjustBindingElements(elements) {
65
+ const names = elements.flatMap((p) => p.names || []), { length } = elements;
66
+ let blockPrefix, restIndex = -1, restCount = 0;
67
+ elements.forEach(({ type }, i) => {
68
+ if (type === "BindingRestElement") {
69
+ if (restIndex < 0)
70
+ restIndex = i;
71
+ return restCount++;
571
72
  }
572
- return target.map((e, i) => {
573
- if (i === 0) {
574
- return insertTrimmingSpace(e, c);
575
- } else {
576
- return e;
577
- }
578
- });
579
- } else if (isParent(target)) {
580
- return {
581
- ...target,
582
- children: insertTrimmingSpace(target.children, c)
583
- };
584
- } else if (isToken(target)) {
73
+ ;
74
+ return;
75
+ });
76
+ if (restCount === 0) {
585
77
  return {
586
- ...target,
587
- token: target.token.replace(/^ ?/, c)
78
+ children: elements,
79
+ names,
80
+ blockPrefix,
81
+ length
588
82
  };
589
- } else {
590
- return target;
591
- }
592
- }
593
- function inplaceInsertTrimmingSpace(target, c) {
594
- if (!(target != null)) {
595
- return target;
596
- }
597
- if (Array.isArray(target)) {
598
- inplaceInsertTrimmingSpace(target[0], c);
599
- } else if (isParent(target)) {
600
- inplaceInsertTrimmingSpace(target.children, c);
601
- } else if (isToken(target)) {
602
- target.token = target.token.replace(/^ ?/, c);
603
- }
604
- }
605
- function getTrimmingSpace(target) {
606
- if (!(target != null)) {
607
- return;
608
- }
609
- if (Array.isArray(target)) {
610
- return getTrimmingSpace(target[0]);
611
- } else if (isParent(target)) {
612
- return getTrimmingSpace(target.children[0]);
613
- } else if (isToken(target)) {
614
- return target.token.match(/^ ?/)[0];
615
- }
616
- ;
617
- return;
618
- }
619
- function prepend(prefix, node) {
620
- if (!(prefix && prefix.length)) {
621
- return node;
622
- }
623
- if (Array.isArray(node)) {
624
- return [prefix, ...node];
625
- } else if (isParent(node)) {
83
+ } else if (restCount === 1) {
84
+ const rest = elements[restIndex];
85
+ const after = elements.slice(restIndex + 1);
86
+ const restIdentifier = rest.binding.ref || rest.binding;
87
+ names.push(...rest.names || []);
88
+ let l = after.length;
89
+ if (l) {
90
+ if (arrayElementHasTrailingComma(after[l - 1]))
91
+ l++;
92
+ blockPrefix = {
93
+ type: "PostRestBindingElements",
94
+ children: ["[", insertTrimmingSpace(after, ""), "] = ", restIdentifier, ".splice(-", l.toString(), ")"],
95
+ names: after.flatMap((p) => p.names)
96
+ };
97
+ }
626
98
  return {
627
- ...node,
628
- children: [prefix, ...node.children]
99
+ names,
100
+ children: [...elements.slice(0, restIndex), {
101
+ ...rest,
102
+ children: rest.children.slice(0, -1)
103
+ // remove trailing comma
104
+ }],
105
+ blockPrefix,
106
+ length
629
107
  };
630
- } else {
631
- return [prefix, node];
632
- }
633
- }
634
- function inplacePrepend(prefix, node) {
635
- if (!prefix) {
636
- return;
637
- }
638
- if (Array.isArray(prefix) && !prefix.length) {
639
- return;
640
- }
641
- if (Array.isArray(node)) {
642
- node.unshift(prefix);
643
- } else if (isParent(node)) {
644
- node.children.unshift(prefix);
645
- } else {
646
- throw new Error("Can't prepend to a leaf node");
647
108
  }
109
+ const err = {
110
+ type: "Error",
111
+ children: ["Multiple rest elements in array pattern"]
112
+ };
113
+ return {
114
+ names,
115
+ children: [...elements, err],
116
+ blockPrefix,
117
+ length
118
+ };
648
119
  }
649
- function literalValue(literal) {
650
- let { raw } = literal;
651
- switch (raw) {
652
- case "null":
653
- return null;
654
- case "true":
655
- return true;
656
- case "false":
657
- return false;
658
- }
659
- if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'")) {
660
- return raw.slice(1, -1);
661
- }
662
- const numeric = literal.children.find(
663
- (child) => child.type === "NumericLiteral"
664
- );
665
- if (numeric) {
666
- raw = raw.replace(/_/g, "");
667
- const { token } = numeric;
668
- if (token.endsWith("n")) {
669
- return BigInt(raw.slice(0, -1));
670
- } else if (token.match(/[\.eE]/)) {
671
- return parseFloat(raw);
672
- } else if (token.startsWith("0")) {
673
- switch (token.charAt(1).toLowerCase()) {
674
- case "x":
675
- return parseInt(raw.replace(/0[xX]/, ""), 16);
676
- case "b":
677
- return parseInt(raw.replace(/0[bB]/, ""), 2);
678
- case "o":
679
- return parseInt(raw.replace(/0[oO]/, ""), 8);
120
+ function gatherBindingCode(statements, opts) {
121
+ const thisAssignments = [];
122
+ const splices = [];
123
+ function insertRestSplices(s, p, thisAssignments2) {
124
+ gatherRecursiveAll(s, (n) => n.blockPrefix || opts?.injectParamProps && n.accessModifier || n.type === "AtBinding").forEach((n) => {
125
+ if (n.type === "AtBinding") {
126
+ const { ref } = n;
127
+ const { id } = ref;
128
+ thisAssignments2.push([`this.${id} = `, ref]);
129
+ return;
680
130
  }
681
- }
682
- return parseInt(raw, 10);
683
- }
684
- throw new Error("Unrecognized literal " + JSON.stringify(literal));
685
- }
686
- function startsWith(target, value) {
687
- if (!target)
688
- return;
689
- if (Array.isArray(target)) {
690
- let i = 0;
691
- let l = target.length;
692
- while (i < l) {
693
- const t = target[i];
694
- if (t && (t.length || t.token || t.children)) {
695
- break;
131
+ if (opts?.injectParamProps && n.type === "Parameter" && n.accessModifier) {
132
+ n.names.forEach((id) => ({
133
+ push: thisAssignments2.push({
134
+ type: "AssignmentExpression",
135
+ children: [`this.${id} = `, id],
136
+ js: true
137
+ })
138
+ }));
139
+ return;
696
140
  }
697
- i++;
698
- }
699
- if (i < l) {
700
- return startsWith(target[i], value);
701
- }
141
+ const { blockPrefix } = n;
142
+ p.push(blockPrefix);
143
+ return insertRestSplices(blockPrefix, p, thisAssignments2);
144
+ });
702
145
  }
703
- if (typeof target === "string")
704
- return value.test(target);
705
- if (target.children)
706
- return startsWith(target.children, value);
707
- if (target.token)
708
- return value.test(target.token);
709
- return;
146
+ insertRestSplices(statements, splices, thisAssignments);
147
+ return [splices, thisAssignments];
710
148
  }
711
- function hasAwait(exp) {
712
- return gatherRecursiveWithinFunction(exp, ({ type }) => type === "Await").length > 0;
149
+ function arrayElementHasTrailingComma(elementNode) {
150
+ const lastChild = elementNode.children.at(-1);
151
+ return lastChild && lastChild[lastChild.length - 1]?.token === ",";
713
152
  }
714
- function hasYield(exp) {
715
- return gatherRecursiveWithinFunction(exp, ({ type }) => type === "Yield").length > 0;
153
+ var init_binding = __esm({
154
+ "source/parser/binding.civet"() {
155
+ "use strict";
156
+ init_traversal();
157
+ init_util();
158
+ }
159
+ });
160
+
161
+ // source/parser/function.civet
162
+ function isVoidType(t) {
163
+ return t?.type === "LiteralType" && t.t.type === "VoidType";
716
164
  }
717
- function hasImportDeclaration(exp) {
718
- return gatherRecursiveWithinFunction(exp, ({ type }) => type === "ImportDeclaration").length > 0;
165
+ function isPromiseVoidType(t) {
166
+ return t?.type === "IdentifierType" && t.raw === "Promise" && t.args?.types?.length === 1 && isVoidType(t.args.types[0]);
167
+ }
168
+ function isGeneratorVoidType(t) {
169
+ return t?.type === "IdentifierType" && (t.raw === "Iterator" || t.raw === "Generator") && t.args?.types?.length >= 2 && isVoidType(t.args.types[1]);
719
170
  }
720
- function deepCopy(node) {
721
- if (node == null)
722
- return node;
723
- if (typeof node !== "object")
724
- return node;
725
- if (Array.isArray(node)) {
726
- return node.map(deepCopy);
727
- }
728
- if (node?.type === "Ref")
729
- return node;
730
- return Object.fromEntries(
731
- Object.entries(node).map(([key, value]) => {
732
- return [key, deepCopy(value)];
733
- })
734
- );
171
+ function isAsyncGeneratorVoidType(t) {
172
+ return t?.type === "IdentifierType" && (t.raw === "AsyncIterator" || t.raw === "AsyncGenerator") && t.args?.types?.length >= 2 && isVoidType(t.args.types[1]);
735
173
  }
736
- function removeHoistDecs(node) {
737
- if (node == null)
174
+ function implicitFunctionBlock(f) {
175
+ if (f.abstract || f.block || f.signature?.optional)
738
176
  return;
739
- if (typeof node !== "object")
177
+ const { name, parent } = f;
178
+ if (parent?.type === "ExportDeclaration")
740
179
  return;
741
- if ("hoistDec" in node) {
742
- node.hoistDec = void 0;
180
+ const expressions = parent?.expressions ?? parent?.elements;
181
+ const currentIndex = expressions?.findIndex(([, def]) => def === f);
182
+ const following = currentIndex >= 0 && expressions[currentIndex + 1]?.[1];
183
+ if (f.type === following?.type && name && name === following.name) {
184
+ f.ts = true;
185
+ } else {
186
+ const block = makeEmptyBlock();
187
+ block.parent = f;
188
+ f.block = block;
189
+ f.children.push(block);
190
+ f.ts = false;
743
191
  }
744
- if (Array.isArray(node)) {
745
- for (const child of node) {
746
- removeHoistDecs(child);
747
- }
748
- return;
192
+ }
193
+ function processReturn(f, implicitReturns) {
194
+ let { returnType } = f.signature;
195
+ if (returnType && returnType.optional) {
196
+ convertOptionalType(returnType);
749
197
  }
750
- if (node.children) {
751
- for (const child of node.children) {
752
- removeHoistDecs(child);
198
+ if (!processReturnValue(f) && implicitReturns) {
199
+ const { signature, block } = f;
200
+ const { modifier, name, returnType: returnType2 } = signature;
201
+ const { async, generator, set } = modifier;
202
+ const isMethod = f.type === "MethodDefinition";
203
+ const isConstructor = isMethod && name === "constructor";
204
+ const isVoid = isVoidType(returnType2?.t) || async && (isPromiseVoidType(returnType2?.t) || generator && isAsyncGeneratorVoidType(returnType2?.t)) || !async && generator && isGeneratorVoidType(returnType2?.t);
205
+ if (block?.type === "BlockStatement") {
206
+ if (isVoid || set || isConstructor) {
207
+ if (block.bare && block.implicitlyReturned) {
208
+ braceBlock(block);
209
+ }
210
+ } else {
211
+ if (!block.implicitlyReturned) {
212
+ insertReturn(block);
213
+ }
214
+ }
753
215
  }
754
216
  }
755
217
  }
756
- function makeAmpersandFunction(rhs) {
757
- let { ref, typeSuffix, body } = rhs;
758
- if (!(ref != null)) {
759
- ref = makeRef("$");
760
- inplacePrepend(ref, body);
761
- }
762
- if (body?.type === "ObjectExpression") {
763
- body = makeLeftHandSideExpression(body);
218
+ function processReturnValue(func) {
219
+ const { block } = func;
220
+ const values = gatherRecursiveWithinFunction(
221
+ block,
222
+ ({ type }) => type === "ReturnValue"
223
+ );
224
+ if (!values.length) {
225
+ return false;
764
226
  }
765
- const parameters = makeNode({
766
- type: "Parameters",
767
- children: typeSuffix ? ["(", ref, typeSuffix, ")"] : [ref],
768
- names: []
769
- });
770
- const expressions = [body];
771
- const block = makeNode({
772
- bare: true,
773
- expressions,
774
- children: [expressions]
227
+ const ref = makeRef("ret");
228
+ let declaration;
229
+ values.forEach((value) => {
230
+ value.children = [ref];
231
+ const { ancestor, child } = findAncestor(
232
+ value,
233
+ ({ type }) => type === "Declaration",
234
+ isFunction
235
+ );
236
+ if (ancestor) {
237
+ return declaration ??= child;
238
+ }
239
+ ;
240
+ return;
775
241
  });
776
- const children = [parameters, " => ", block];
777
- const async = hasAwait(body);
778
- if (async) {
779
- children.unshift("async ");
242
+ let returnType = func.returnType ?? func.signature?.returnType;
243
+ if (returnType) {
244
+ const { t } = returnType;
245
+ let m;
246
+ if (m = t.type, m === "TypePredicate") {
247
+ returnType = ": boolean";
248
+ } else if (m === "AssertsType") {
249
+ returnType = void 0;
250
+ }
780
251
  }
781
- return makeNode({
782
- type: "ArrowFunction",
783
- signature: {
784
- modifier: {
785
- async
786
- }
787
- },
788
- children,
789
- ref,
790
- body,
791
- ampersandBlock: true,
252
+ if (declaration) {
253
+ if (!(declaration.suffix != null)) {
254
+ declaration.children[1] = declaration.suffix = returnType;
255
+ }
256
+ } else {
257
+ block.expressions.unshift([
258
+ getIndent(block.expressions[0]),
259
+ {
260
+ type: "Declaration",
261
+ children: ["let ", ref, returnType],
262
+ names: []
263
+ },
264
+ ";"
265
+ ]);
266
+ }
267
+ gatherRecursiveWithinFunction(
792
268
  block,
793
- parameters
269
+ (r) => r.type === "ReturnStatement" && !r.expression
270
+ ).forEach((r) => {
271
+ r.expression = ref;
272
+ return r.children.splice(-1, 1, " ", ref);
794
273
  });
795
- }
796
- function makeLeftHandSideExpression(expression) {
797
- if (expression.parenthesized) {
798
- return expression;
274
+ if (!(block.children.at(-2)?.type === "ReturnStatement")) {
275
+ const indent = getIndent(block.expressions.at(-1)) || ";";
276
+ block.expressions.push([
277
+ [indent],
278
+ {
279
+ type: "ReturnStatement",
280
+ expression: ref,
281
+ children: ["return ", ref]
282
+ }
283
+ ]);
799
284
  }
800
- switch (expression.type) {
801
- case "AmpersandRef":
802
- case "CallExpression":
285
+ return true;
286
+ }
287
+ function patternAsValue(pattern) {
288
+ switch (pattern.type) {
289
+ case "ArrayBindingPattern": {
290
+ const children = [...pattern.children];
291
+ const index = children.indexOf(pattern.elements);
292
+ if (index < 0)
293
+ throw new Error("failed to find elements in ArrayBindingPattern");
294
+ children[index] = pattern.elements.map((el) => {
295
+ const [ws, e, delim] = el.children;
296
+ return { ...el, children: [ws, patternAsValue(e), delim] };
297
+ });
298
+ return { ...pattern, children };
299
+ }
300
+ case "ObjectBindingPattern": {
301
+ const children = [...pattern.children];
302
+ const index = children.indexOf(pattern.properties);
303
+ if (index < 0)
304
+ throw new Error("failed to find properties in ArrayBindingPattern");
305
+ children[index] = pattern.properties.map(patternAsValue);
306
+ return { ...pattern, children };
307
+ }
803
308
  case "Identifier":
804
- case "JSXElement":
805
- case "JSXFragment":
806
- case "Literal":
807
- case "MemberExpression":
808
- case "NewExpression":
809
- case "ParenthesizedExpression":
810
- case "Ref":
811
- case "Placeholder":
812
- case "StatementExpression":
813
- return expression;
309
+ case "BindingProperty": {
310
+ const children = [
311
+ // { name: value } = ... declares value, not name
312
+ pattern.value ?? pattern.name,
313
+ pattern.delim
314
+ ];
315
+ if (isWhitespaceOrEmpty(pattern.children[0])) {
316
+ children.unshift(pattern.children[0]);
317
+ }
318
+ return { ...pattern, children };
319
+ }
320
+ default:
321
+ return pattern;
814
322
  }
815
- return makeNode({
816
- type: "ParenthesizedExpression",
817
- children: ["(", expression, ")"],
818
- expression,
819
- implicit: true,
820
- parent: void 0
821
- });
822
323
  }
823
- function updateParentPointers(node, parent, depth = 1) {
824
- if (!(node != null)) {
324
+ function assignResults(node, collect) {
325
+ if (!node)
326
+ return;
327
+ switch (node.type) {
328
+ case "BlockStatement":
329
+ if (node.expressions.length) {
330
+ assignResults(node.expressions.at(-1), collect);
331
+ } else {
332
+ node.expressions.push(["", collect("void 0"), ";"]);
333
+ }
334
+ return;
335
+ case "CaseBlock":
336
+ node.clauses.forEach((clause) => {
337
+ return assignResults(clause, collect);
338
+ });
339
+ return;
340
+ case "WhenClause":
341
+ case "DefaultClause":
342
+ case "PatternClause": {
343
+ assignResults(node.block, collect);
344
+ return;
345
+ }
346
+ }
347
+ if (!Array.isArray(node)) {
825
348
  return;
826
349
  }
827
- if (!(typeof node === "object")) {
350
+ let [, exp, semi] = node;
351
+ if (semi?.type === "SemicolonDelimiter") {
828
352
  return;
829
353
  }
830
- if (Array.isArray(node)) {
831
- for (const child of node) {
832
- updateParentPointers(child, parent, depth);
833
- }
354
+ if (!exp) {
355
+ return;
356
+ }
357
+ if (isExit(exp)) {
834
358
  return;
835
359
  }
836
- node = node;
837
- if (parent != null) {
838
- node.parent = parent;
839
- }
840
- if (depth && isParent(node)) {
841
- for (const child of node.children) {
842
- updateParentPointers(child, node, depth - 1);
843
- }
360
+ const outer = exp;
361
+ let { type } = exp;
362
+ if (type === "LabelledStatement") {
363
+ exp = exp.statement;
364
+ ({ type } = exp);
844
365
  }
845
- }
846
- function makeNode(node) {
847
- updateParentPointers(node);
848
- return node;
849
- }
850
- function makeRef(base = "ref", id = base) {
851
- return {
852
- type: "Ref",
853
- base,
854
- id
855
- };
856
- }
857
- function needsRef(expression, base = "ref") {
858
- switch (expression.type) {
859
- case "Ref":
860
- case "Identifier":
861
- case "Literal":
366
+ switch (exp.type) {
367
+ case "BreakStatement":
368
+ case "ContinueStatement":
369
+ case "DebuggerStatement":
370
+ case "EmptyStatement":
371
+ case "ReturnStatement":
372
+ case "ThrowStatement":
373
+ return;
374
+ case "Declaration":
375
+ exp.children.push([
376
+ "",
377
+ [";", collect(patternAsValue(exp.bindings.at(-1).pattern))]
378
+ ]);
379
+ return;
380
+ case "ForStatement":
381
+ case "IterationStatement":
382
+ case "DoStatement":
383
+ wrapIterationReturningResults(exp, outer, collect);
384
+ return;
385
+ case "BlockStatement":
386
+ assignResults(exp.expressions[exp.expressions.length - 1], collect);
387
+ return;
388
+ case "IfStatement":
389
+ assignResults(exp.then, collect);
390
+ if (exp.then.bare && !exp.then.semicolon) {
391
+ exp.then.children.push(exp.then.semicolon = ";");
392
+ }
393
+ if (exp.else) {
394
+ assignResults(exp.else[2], collect);
395
+ } else {
396
+ exp.children.push([" else {", collect("undefined"), "}"]);
397
+ }
398
+ return;
399
+ case "PatternMatchingStatement":
400
+ assignResults(exp.children[0][0], collect);
401
+ return;
402
+ case "SwitchStatement":
403
+ assignResults(exp.children[2], collect);
404
+ return;
405
+ case "TryStatement":
406
+ exp.blocks.forEach((block) => assignResults(block, collect));
862
407
  return;
863
408
  }
864
- return makeRef(base);
865
- }
866
- function maybeRef(exp, base = "ref") {
867
- if (!needsRef(exp))
868
- return exp;
869
- return makeRef(base);
870
- }
871
- function skipIfOnlyWS(target) {
872
- if (!target)
873
- return target;
874
- if (Array.isArray(target)) {
875
- if (target.length === 1) {
876
- return skipIfOnlyWS(target[0]);
877
- } else if (target.every((e) => skipIfOnlyWS(e) === void 0)) {
878
- return void 0;
879
- }
880
- return target;
881
- }
882
- if (target.token != null && target.token.trim() === "") {
883
- return void 0;
409
+ if (node.at(-1)?.type === "SemicolonDelimiter") {
410
+ return;
884
411
  }
885
- return target;
412
+ node[1] = collect(node[1]);
886
413
  }
887
- function spliceChild(node, child, del, ...replacements) {
888
- const children = node?.children ?? node;
889
- if (!Array.isArray(children)) {
890
- throw new Error("spliceChild: non-array node has no children field");
414
+ function insertReturn(node, outerNode = node) {
415
+ if (!node)
416
+ return;
417
+ switch (node.type) {
418
+ case "BlockStatement":
419
+ if (node.expressions.length) {
420
+ const last = node.expressions[node.expressions.length - 1];
421
+ insertReturn(last);
422
+ } else {
423
+ if (node.parent.type === "CatchClause") {
424
+ node.expressions.push(["return"]);
425
+ }
426
+ }
427
+ return;
428
+ case "WhenClause":
429
+ if (node.break) {
430
+ node.children.splice(node.children.indexOf(node.break), 1);
431
+ }
432
+ if (node.block.expressions.length) {
433
+ insertReturn(node.block);
434
+ } else {
435
+ node.block.expressions.push(wrapWithReturn());
436
+ }
437
+ return;
438
+ case "DefaultClause":
439
+ insertReturn(node.block);
440
+ return;
891
441
  }
892
- const index = children.indexOf(child);
893
- if (index < 0) {
894
- throw new Error("spliceChild: child not found");
442
+ if (!Array.isArray(node))
443
+ return;
444
+ let [, exp, semi] = node;
445
+ if (semi?.type === "SemicolonDelimiter") {
446
+ return;
895
447
  }
896
- return children.splice(index, del, ...replacements);
897
- }
898
- function convertOptionalType(suffix) {
899
- if (suffix.t.type === "AssertsType") {
900
- spliceChild(suffix, suffix.optional, 1, suffix.optional = {
901
- type: "Error",
902
- message: "Can't use optional ?: syntax with asserts type"
903
- });
448
+ if (!exp) {
904
449
  return;
905
450
  }
906
- spliceChild(suffix, suffix.optional, 1, suffix.optional = void 0);
907
- const wrap = suffix.type === "ReturnTypeAnnotation";
908
- spliceChild(suffix, suffix.t, 1, suffix.t = [
909
- getTrimmingSpace(suffix.t),
910
- wrap && "(",
911
- // TODO: avoid parens if unnecessary
912
- "undefined | ",
913
- parenthesizeType(insertTrimmingSpace(suffix.t, "")),
914
- wrap && ")"
915
- ]);
916
- }
917
- function parenthesizeType(type) {
918
- if (typeNeedsNoParens.has(type.type)) {
919
- return type;
451
+ if (isExit(exp)) {
452
+ return;
920
453
  }
921
- return ["(", type, ")"];
922
- }
923
- function wrapIIFE(expressions, asyncFlag) {
924
- let prefix;
925
- let async;
926
- if (asyncFlag) {
927
- async = "async ";
928
- } else if (hasAwait(expressions)) {
929
- async = "async ";
930
- prefix = {
931
- type: "Await",
932
- children: ["await "]
933
- };
454
+ const outer = exp;
455
+ let { type } = exp;
456
+ if (type === "LabelledStatement") {
457
+ exp = exp.statement;
458
+ ({ type } = exp);
934
459
  }
935
- const block = makeNode({
936
- type: "BlockStatement",
937
- expressions,
938
- children: ["{", expressions, "}"],
939
- bare: false,
940
- root: false,
941
- parent: void 0
942
- });
943
- const parameters = {
944
- type: "Parameters",
945
- children: ["()"],
946
- names: []
947
- };
948
- const signature = {
949
- modifier: {
950
- async: !!async
951
- },
952
- returnType: void 0
953
- };
954
- const fn = makeNode({
955
- type: "ArrowFunction",
956
- signature,
957
- parameters,
958
- returnType: void 0,
959
- ts: false,
960
- async,
961
- block,
962
- children: [async, parameters, "=>", block]
963
- });
964
- const exp = makeNode({
965
- type: "CallExpression",
966
- children: [makeLeftHandSideExpression(fn), "()"]
967
- });
968
- if (prefix) {
969
- return [makeLeftHandSideExpression([prefix, exp])];
460
+ switch (type) {
461
+ case "BreakStatement":
462
+ case "ContinueStatement":
463
+ case "DebuggerStatement":
464
+ case "EmptyStatement":
465
+ case "ReturnStatement":
466
+ case "ThrowStatement":
467
+ return;
468
+ case "Declaration":
469
+ exp.children.push(["", {
470
+ type: "ReturnStatement",
471
+ children: [";return ", patternAsValue(exp.bindings.at(-1).pattern)],
472
+ parent: exp
473
+ }]);
474
+ return;
475
+ case "FunctionExpression":
476
+ if (exp.id) {
477
+ exp.children.push([
478
+ "",
479
+ {
480
+ type: "ReturnStatement",
481
+ children: [";return ", exp.id],
482
+ parent: exp
483
+ }
484
+ ]);
485
+ return;
486
+ }
487
+ break;
488
+ case "ForStatement":
489
+ case "IterationStatement":
490
+ case "DoStatement":
491
+ wrapIterationReturningResults(exp, outer);
492
+ return;
493
+ case "BlockStatement":
494
+ insertReturn(exp.expressions[exp.expressions.length - 1]);
495
+ return;
496
+ case "IfStatement":
497
+ insertReturn(exp.then);
498
+ if (exp.else && exp.else.length !== 0)
499
+ insertReturn(exp.else[2]);
500
+ else
501
+ exp.children.push(["", {
502
+ type: "ReturnStatement",
503
+ // NOTE: add a prefixed semi-colon because the if block may not be braced
504
+ children: [";return"],
505
+ parent: exp
506
+ }]);
507
+ return;
508
+ case "PatternMatchingStatement":
509
+ insertReturn(exp.children[0][0]);
510
+ return;
511
+ case "SwitchStatement":
512
+ insertSwitchReturns(exp);
513
+ return;
514
+ case "TryStatement":
515
+ exp.blocks.forEach((block) => insertReturn(block));
516
+ return;
970
517
  }
971
- return [exp];
518
+ if (node[node.length - 1]?.type === "SemicolonDelimiter")
519
+ return;
520
+ const returnStatement = wrapWithReturn(node[1]);
521
+ node.splice(1, 1, returnStatement);
972
522
  }
973
- function wrapWithReturn(expression) {
974
- const children = expression ? ["return ", expression] : ["return"];
975
- return makeNode({
976
- type: "ReturnStatement",
977
- children,
978
- expression,
979
- parent: expression?.parent
523
+ function insertSwitchReturns(exp) {
524
+ exp.caseBlock.clauses.forEach((clause) => {
525
+ return insertReturn(clause);
980
526
  });
981
527
  }
982
- var assert, typeNeedsNoParens;
983
- var init_util = __esm({
984
- "source/parser/util.civet"() {
985
- "use strict";
986
- init_traversal();
987
- init_op();
988
- init_unary();
989
- assert = {
990
- equal(a, b, msg) {
991
- if (a !== b) {
992
- throw new Error(`Assertion failed [${msg}]: ${a} !== ${b}`);
993
- }
994
- }
995
- };
996
- typeNeedsNoParens = /* @__PURE__ */ new Set([
997
- "IdentifierType",
998
- "ImportType",
999
- "LiteralType",
1000
- "TupleType",
1001
- "ParenthesizedType",
1002
- "UnaryType"
1003
- ]);
528
+ function wrapIterationReturningResults(statement, outer, collect) {
529
+ if (statement.type === "DoStatement") {
530
+ if (collect) {
531
+ assignResults(statement.block, collect);
532
+ } else {
533
+ insertReturn(statement.block, outer);
534
+ }
535
+ return;
1004
536
  }
1005
- });
1006
-
1007
- // source/parser/traversal.civet
1008
- function gatherRecursiveWithinFunction(node, predicate) {
1009
- return gatherRecursive(node, predicate, isFunction);
1010
- }
1011
- function findChildIndex(parent, child) {
1012
- if (!(parent != null)) {
1013
- return -1;
537
+ assert.equal(
538
+ statement.resultsRef,
539
+ void 0,
540
+ "wrapIterationReturningResults should not be called twice on the same statement"
541
+ );
542
+ const resultsRef = statement.resultsRef = makeRef("results");
543
+ const declaration = {
544
+ type: "Declaration",
545
+ children: ["const ", resultsRef, "=[]"]
546
+ };
547
+ outer.children.unshift(["", declaration, ";"]);
548
+ assignResults(statement.block, (node) => {
549
+ return [resultsRef, ".push(", node, ")"];
550
+ });
551
+ if (collect) {
552
+ statement.children.push(collect(resultsRef));
553
+ } else {
554
+ statement.children.push(";return ", resultsRef, ";");
1014
555
  }
1015
- const children = Array.isArray(parent) ? parent : parent.children;
1016
- if (!(children != null)) {
1017
- return -1;
556
+ }
557
+ function processParams(f) {
558
+ const { type, parameters, block } = f;
559
+ const isConstructor = f.name === "constructor";
560
+ if (type === "ArrowFunction" && parameters && parameters.tp && parameters.tp.parameters.length === 1) {
561
+ parameters.tp.parameters.push(",");
1018
562
  }
1019
- for (let i1 = 0, len = children.length; i1 < len; i1++) {
1020
- const i = i1;
1021
- const c = children[i1];
1022
- if (c === child || Array.isArray(c) && arrayRecurse(c)) {
1023
- return i;
1024
- }
563
+ if (!block)
564
+ return;
565
+ const { expressions } = block;
566
+ if (!expressions)
567
+ return;
568
+ const { blockPrefix } = parameters;
569
+ let indent;
570
+ if (!expressions.length) {
571
+ indent = "";
572
+ } else {
573
+ indent = expressions[0][0];
1025
574
  }
1026
- function arrayRecurse(array) {
1027
- for (let i2 = 0, len1 = array.length; i2 < len1; i2++) {
1028
- const c = array[i2];
1029
- if (c === child || Array.isArray(c) && arrayRecurse(c)) {
1030
- return true;
575
+ const [splices, thisAssignments] = gatherBindingCode(parameters, {
576
+ injectParamProps: isConstructor
577
+ });
578
+ const delimiter = {
579
+ type: "SemicolonDelimiter",
580
+ children: [";"]
581
+ };
582
+ const prefix = splices.map((s) => ["let ", s]).concat(thisAssignments).map(
583
+ (s) => s.type ? {
584
+ // TODO: figure out how to get JS only statement tuples
585
+ ...s,
586
+ children: [indent, ...s.children, delimiter]
587
+ } : [indent, s, delimiter]
588
+ );
589
+ if (!prefix.length)
590
+ return;
591
+ if (isConstructor) {
592
+ const superCalls = gatherNodes(expressions, (exp) => {
593
+ return exp.type === "CallExpression" && exp.children[0]?.token === "super";
594
+ });
595
+ if (superCalls.length) {
596
+ const { child } = findAncestor(
597
+ superCalls[0],
598
+ (ancestor) => ancestor === block
599
+ );
600
+ const index = findChildIndex(expressions, child);
601
+ if (index < 0) {
602
+ throw new Error("Could not find super call within top-level expressions");
1031
603
  }
604
+ expressions.splice(index + 1, 0, ...prefix);
605
+ return;
1032
606
  }
1033
- return false;
1034
- }
1035
- return -1;
1036
- }
1037
- function findAncestor(node, predicate, stopPredicate) {
1038
- let { parent } = node;
1039
- while (parent && !stopPredicate?.(parent, node)) {
1040
- if (predicate(parent, node)) {
1041
- return { ancestor: parent, child: node };
1042
- }
1043
- node = parent;
1044
- ({ parent } = node);
1045
607
  }
1046
- return { ancestor: void 0, child: node };
608
+ expressions.unshift(...prefix);
1047
609
  }
1048
- function gatherNodes(node, predicate) {
1049
- if (node == null)
1050
- return [];
1051
- if (Array.isArray(node)) {
1052
- return node.flatMap((n) => gatherNodes(n, predicate));
1053
- }
1054
- if (predicate(node)) {
1055
- return [node];
1056
- }
1057
- switch (node.type) {
1058
- case "BlockStatement":
1059
- return [];
1060
- case "ForStatement":
1061
- const isDec = node.declaration?.type === "Declaration";
1062
- return node.children.flatMap((n) => {
1063
- if (isDec && n === node.declaration)
1064
- return [];
1065
- return gatherNodes(n, predicate);
1066
- });
1067
- default:
1068
- return gatherNodes(node.children, predicate);
1069
- }
610
+ function processFunctions(statements, config) {
611
+ gatherRecursiveAll(statements, ({ type }) => type === "FunctionExpression" || type === "ArrowFunction").forEach((f) => {
612
+ if (f.type === "FunctionExpression")
613
+ implicitFunctionBlock(f);
614
+ processParams(f);
615
+ return processReturn(f, config.implicitReturns);
616
+ });
617
+ gatherRecursiveAll(statements, ({ type }) => type === "MethodDefinition").forEach((f) => {
618
+ implicitFunctionBlock(f);
619
+ processParams(f);
620
+ return processReturn(f, config.implicitReturns);
621
+ });
1070
622
  }
1071
- function gatherRecursive(node, predicate, skipPredicate) {
1072
- if (node == null)
1073
- return [];
1074
- if (Array.isArray(node)) {
1075
- return node.flatMap((n) => gatherRecursive(n, predicate, skipPredicate));
623
+ function expressionizeIteration(exp) {
624
+ const { async, subtype, block, children, statement } = exp;
625
+ const i = children.indexOf(statement);
626
+ if (i < 0) {
627
+ throw new Error("Could not find iteration statement in iteration expression");
1076
628
  }
1077
- if (skipPredicate?.(node))
1078
- return [];
1079
- if (predicate(node)) {
1080
- return [node];
629
+ if (subtype === "DoStatement") {
630
+ children.splice(i, 1, ...wrapIIFE([["", statement, void 0]], async));
631
+ updateParentPointers(exp);
632
+ return;
1081
633
  }
1082
- return gatherRecursive(node.children, predicate, skipPredicate);
634
+ exp.resultsRef ??= makeRef("results");
635
+ const { resultsRef } = exp;
636
+ assignResults(block, (node) => {
637
+ return [resultsRef, ".push(", node, ")"];
638
+ });
639
+ braceBlock(block);
640
+ children.splice(
641
+ i,
642
+ 1,
643
+ ...wrapIIFE([
644
+ ["", ["const ", resultsRef, "=[]"], ";"],
645
+ ...children.map((c) => ["", c, void 0]),
646
+ ["", wrapWithReturn(resultsRef)]
647
+ ], async)
648
+ );
649
+ updateParentPointers(exp);
1083
650
  }
1084
- function gatherRecursiveAll(node, predicate) {
1085
- if (node == null)
1086
- return [];
1087
- if (Array.isArray(node)) {
1088
- return node.flatMap((n) => gatherRecursiveAll(n, predicate));
1089
- }
1090
- const nodes = gatherRecursiveAll(node.children, predicate);
1091
- if (predicate(node)) {
1092
- nodes.push(node);
651
+ function skipImplicitArguments(args) {
652
+ if (args.length === 1) {
653
+ let arg0 = args[0];
654
+ if (arg0.type === "StatementExpression") {
655
+ arg0 = arg0.statement;
656
+ }
657
+ return arg0.type === "IterationExpression" && arg0.subtype !== "DoStatement" && !arg0.async && isEmptyBareBlock(arg0.block);
1093
658
  }
1094
- return nodes;
659
+ return false;
1095
660
  }
1096
- var init_traversal = __esm({
1097
- "source/parser/traversal.civet"() {
661
+ var init_function = __esm({
662
+ "source/parser/function.civet"() {
1098
663
  "use strict";
664
+ init_block();
665
+ init_binding();
666
+ init_traversal();
1099
667
  init_util();
1100
668
  }
1101
669
  });
@@ -1128,7 +696,13 @@ var Civet = (() => {
1128
696
  }
1129
697
  block.children.unshift(" {");
1130
698
  block.children.push("}");
1131
- return block.bare = false;
699
+ const { implicitlyReturned } = block;
700
+ block.bare = block.implicitlyReturned = false;
701
+ if (implicitlyReturned) {
702
+ return processReturn(block.parent, true);
703
+ }
704
+ ;
705
+ return;
1132
706
  }
1133
707
  ;
1134
708
  return;
@@ -1302,1010 +876,1379 @@ var Civet = (() => {
1302
876
  "use strict";
1303
877
  init_util();
1304
878
  init_traversal();
879
+ init_function();
1305
880
  }
1306
881
  });
1307
882
 
1308
- // source/parser/binding.civet
1309
- function adjustAtBindings(statements, asThis = false) {
1310
- gatherRecursiveAll(statements, (n) => n.type === "AtBindingProperty").forEach((binding) => {
1311
- const { ref } = binding;
1312
- if (asThis) {
1313
- const atBinding = binding.binding;
1314
- atBinding.children.pop();
1315
- atBinding.type = void 0;
1316
- binding.children.unshift(ref.id, ": this.", ref.base);
1317
- binding.type = "Property";
1318
- binding.ref = void 0;
1319
- return;
1320
- }
1321
- if (ref.names[0] !== ref.base) {
1322
- return binding.children.unshift(ref.base, ": ");
883
+ // source/parser/util.civet
884
+ function addParentPointers(node, parent) {
885
+ if (node == null)
886
+ return;
887
+ if (typeof node !== "object")
888
+ return;
889
+ if (Array.isArray(node)) {
890
+ for (const child of node) {
891
+ addParentPointers(child, parent);
1323
892
  }
1324
- ;
1325
893
  return;
1326
- });
894
+ }
895
+ node = node;
896
+ node.parent = parent;
897
+ if (node.children) {
898
+ for (const child of node.children) {
899
+ addParentPointers(child, node);
900
+ }
901
+ }
1327
902
  }
1328
- function adjustBindingElements(elements) {
1329
- const names = elements.flatMap((p) => p.names || []), { length } = elements;
1330
- let blockPrefix, restIndex = -1, restCount = 0;
1331
- elements.forEach(({ type }, i) => {
1332
- if (type === "BindingRestElement") {
1333
- if (restIndex < 0)
1334
- restIndex = i;
1335
- return restCount++;
903
+ function clone(node) {
904
+ removeParentPointers(node);
905
+ return deepCopy(node);
906
+ }
907
+ function removeParentPointers(node) {
908
+ if (node == null)
909
+ return;
910
+ if (typeof node !== "object")
911
+ return;
912
+ if (Array.isArray(node)) {
913
+ for (const child of node) {
914
+ removeParentPointers(child);
1336
915
  }
1337
- ;
1338
916
  return;
1339
- });
1340
- if (restCount === 0) {
917
+ }
918
+ node.parent = null;
919
+ if (node.children) {
920
+ for (const child of node.children) {
921
+ removeParentPointers(child);
922
+ }
923
+ }
924
+ }
925
+ function maybeWrap(node, parent) {
926
+ if (!isASTNodeObject(node)) {
927
+ updateParentPointers(node = {
928
+ type: "Wrapper",
929
+ children: [node],
930
+ parent
931
+ });
932
+ }
933
+ return node;
934
+ }
935
+ function maybeUnwrap(node) {
936
+ if (node?.type === "Wrapper") {
937
+ return node.children[0];
938
+ } else {
939
+ return node;
940
+ }
941
+ }
942
+ function isASTNodeObject(node) {
943
+ return typeof node === "object" && node != null && !Array.isArray(node);
944
+ }
945
+ function isParent(node) {
946
+ return node != null && node.children != null;
947
+ }
948
+ function isToken(node) {
949
+ return node != null && node.token != null;
950
+ }
951
+ function isEmptyBareBlock(node) {
952
+ if (node?.type !== "BlockStatement")
953
+ return false;
954
+ const { bare, expressions } = node;
955
+ return bare && (expressions.length === 0 || expressions.length === 1 && expressions[0][1]?.type === "EmptyStatement");
956
+ }
957
+ function isFunction(node) {
958
+ const { type } = node;
959
+ return type === "FunctionExpression" || type === "ArrowFunction" || type === "MethodDefinition" || !!node.async;
960
+ }
961
+ function isStatement(node) {
962
+ return isASTNodeObject(node) && node.type != null && // forbid leaf
963
+ statementTypes.has(node.type);
964
+ }
965
+ function isWhitespaceOrEmpty(node) {
966
+ if (!node)
967
+ return true;
968
+ if (node.type === "Ref")
969
+ return false;
970
+ if (node.token)
971
+ return node.token.match(/^\s*$/);
972
+ if (node.children)
973
+ node = node.children;
974
+ if (!node.length)
975
+ return true;
976
+ if (typeof node === "string")
977
+ return node.match(/^\s*$/);
978
+ if (Array.isArray(node))
979
+ return node.every(isWhitespaceOrEmpty);
980
+ return;
981
+ }
982
+ function isExit(node) {
983
+ if (!(node != null)) {
984
+ return false;
985
+ }
986
+ switch (node.type) {
987
+ case "ReturnStatement":
988
+ case "ThrowStatement":
989
+ case "BreakStatement":
990
+ case "ContinueStatement": {
991
+ return true;
992
+ }
993
+ case "IfStatement": {
994
+ return isExit(node.then) && isExit(node.else?.at(-1));
995
+ }
996
+ case "BlockStatement": {
997
+ return isExit(node.expressions.at(-1)?.[1]);
998
+ }
999
+ case "IterationStatement": {
1000
+ return node.condition?.type === "ParenthesizedExpression" && node.condition.expression?.type === "Literal" && node.condition.expression?.raw === "true" && gatherRecursiveWithinFunction(
1001
+ node.block,
1002
+ ({ type }) => type === "BreakStatement"
1003
+ ).length === 0;
1004
+ }
1005
+ default: {
1006
+ return false;
1007
+ }
1008
+ }
1009
+ }
1010
+ function isComma(node) {
1011
+ if (node?.token === ",") {
1012
+ return node;
1013
+ } else if (Array.isArray(node) && node.at(-1)?.token === ",") {
1014
+ return node.at(-1);
1015
+ }
1016
+ ;
1017
+ return;
1018
+ }
1019
+ function insertTrimmingSpace(target, c) {
1020
+ if (!(target != null)) {
1021
+ return target;
1022
+ }
1023
+ if (Array.isArray(target)) {
1024
+ if (target.length === 0) {
1025
+ return c;
1026
+ }
1027
+ return target.map((e, i) => {
1028
+ if (i === 0) {
1029
+ return insertTrimmingSpace(e, c);
1030
+ } else {
1031
+ return e;
1032
+ }
1033
+ });
1034
+ } else if (isParent(target)) {
1341
1035
  return {
1342
- children: elements,
1343
- names,
1344
- blockPrefix,
1345
- length
1036
+ ...target,
1037
+ children: insertTrimmingSpace(target.children, c)
1346
1038
  };
1347
- } else if (restCount === 1) {
1348
- const rest = elements[restIndex];
1349
- const after = elements.slice(restIndex + 1);
1350
- const restIdentifier = rest.binding.ref || rest.binding;
1351
- names.push(...rest.names || []);
1352
- let l = after.length;
1353
- if (l) {
1354
- if (arrayElementHasTrailingComma(after[l - 1]))
1355
- l++;
1356
- blockPrefix = {
1357
- type: "PostRestBindingElements",
1358
- children: ["[", insertTrimmingSpace(after, ""), "] = ", restIdentifier, ".splice(-", l.toString(), ")"],
1359
- names: after.flatMap((p) => p.names)
1360
- };
1361
- }
1039
+ } else if (isToken(target)) {
1362
1040
  return {
1363
- names,
1364
- children: [...elements.slice(0, restIndex), {
1365
- ...rest,
1366
- children: rest.children.slice(0, -1)
1367
- // remove trailing comma
1368
- }],
1369
- blockPrefix,
1370
- length
1041
+ ...target,
1042
+ token: target.token.replace(/^ ?/, c)
1371
1043
  };
1044
+ } else {
1045
+ return target;
1372
1046
  }
1373
- const err = {
1374
- type: "Error",
1375
- children: ["Multiple rest elements in array pattern"]
1376
- };
1377
- return {
1378
- names,
1379
- children: [...elements, err],
1380
- blockPrefix,
1381
- length
1382
- };
1383
1047
  }
1384
- function gatherBindingCode(statements, opts) {
1385
- const thisAssignments = [];
1386
- const splices = [];
1387
- function insertRestSplices(s, p, thisAssignments2) {
1388
- gatherRecursiveAll(s, (n) => n.blockPrefix || opts?.injectParamProps && n.accessModifier || n.type === "AtBinding").forEach((n) => {
1389
- if (n.type === "AtBinding") {
1390
- const { ref } = n;
1391
- const { id } = ref;
1392
- thisAssignments2.push([`this.${id} = `, ref]);
1393
- return;
1394
- }
1395
- if (opts?.injectParamProps && n.type === "Parameter" && n.accessModifier) {
1396
- n.names.forEach((id) => ({
1397
- push: thisAssignments2.push({
1398
- type: "AssignmentExpression",
1399
- children: [`this.${id} = `, id],
1400
- js: true
1401
- })
1402
- }));
1403
- return;
1404
- }
1405
- const { blockPrefix } = n;
1406
- p.push(blockPrefix);
1407
- return insertRestSplices(blockPrefix, p, thisAssignments2);
1408
- });
1048
+ function inplaceInsertTrimmingSpace(target, c) {
1049
+ if (!(target != null)) {
1050
+ return target;
1051
+ }
1052
+ if (Array.isArray(target)) {
1053
+ inplaceInsertTrimmingSpace(target[0], c);
1054
+ } else if (isParent(target)) {
1055
+ inplaceInsertTrimmingSpace(target.children, c);
1056
+ } else if (isToken(target)) {
1057
+ target.token = target.token.replace(/^ ?/, c);
1058
+ }
1059
+ }
1060
+ function getTrimmingSpace(target) {
1061
+ if (!(target != null)) {
1062
+ return;
1409
1063
  }
1410
- insertRestSplices(statements, splices, thisAssignments);
1411
- return [splices, thisAssignments];
1064
+ if (Array.isArray(target)) {
1065
+ return getTrimmingSpace(target[0]);
1066
+ } else if (isParent(target)) {
1067
+ return getTrimmingSpace(target.children[0]);
1068
+ } else if (isToken(target)) {
1069
+ return target.token.match(/^ ?/)[0];
1070
+ }
1071
+ ;
1072
+ return;
1412
1073
  }
1413
- function arrayElementHasTrailingComma(elementNode) {
1414
- const lastChild = elementNode.children.at(-1);
1415
- return lastChild && lastChild[lastChild.length - 1]?.token === ",";
1074
+ function prepend(prefix, node) {
1075
+ if (!(prefix && prefix.length)) {
1076
+ return node;
1077
+ }
1078
+ if (Array.isArray(node)) {
1079
+ return [prefix, ...node];
1080
+ } else if (isParent(node)) {
1081
+ return {
1082
+ ...node,
1083
+ children: [prefix, ...node.children]
1084
+ };
1085
+ } else {
1086
+ return [prefix, node];
1087
+ }
1416
1088
  }
1417
- var init_binding = __esm({
1418
- "source/parser/binding.civet"() {
1419
- "use strict";
1420
- init_traversal();
1421
- init_util();
1089
+ function inplacePrepend(prefix, node) {
1090
+ if (!prefix) {
1091
+ return;
1422
1092
  }
1423
- });
1424
-
1425
- // source/parser/pattern-matching.civet
1426
- function processPatternMatching(statements, ReservedWord, getRef) {
1427
- gatherRecursiveAll(statements, ($) => $.type === "SwitchStatement").forEach((s) => {
1428
- const { caseBlock } = s;
1429
- const { clauses } = caseBlock;
1430
- for (const c of clauses) {
1431
- if (c.type === "WhenClause" && c.break) {
1432
- if (isExit(c.block)) {
1433
- c.children.splice(c.children.indexOf(c.break), 1);
1434
- c.break = void 0;
1435
- }
1093
+ if (Array.isArray(prefix) && !prefix.length) {
1094
+ return;
1095
+ }
1096
+ if (Array.isArray(node)) {
1097
+ node.unshift(prefix);
1098
+ } else if (isParent(node)) {
1099
+ node.children.unshift(prefix);
1100
+ } else {
1101
+ throw new Error("Can't prepend to a leaf node");
1102
+ }
1103
+ }
1104
+ function literalValue(literal) {
1105
+ let { raw } = literal;
1106
+ switch (raw) {
1107
+ case "null":
1108
+ return null;
1109
+ case "true":
1110
+ return true;
1111
+ case "false":
1112
+ return false;
1113
+ }
1114
+ if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'")) {
1115
+ return raw.slice(1, -1);
1116
+ }
1117
+ const numeric = literal.children.find(
1118
+ (child) => child.type === "NumericLiteral"
1119
+ );
1120
+ if (numeric) {
1121
+ raw = raw.replace(/_/g, "");
1122
+ const { token } = numeric;
1123
+ if (token.endsWith("n")) {
1124
+ return BigInt(raw.slice(0, -1));
1125
+ } else if (token.match(/[\.eE]/)) {
1126
+ return parseFloat(raw);
1127
+ } else if (token.startsWith("0")) {
1128
+ switch (token.charAt(1).toLowerCase()) {
1129
+ case "x":
1130
+ return parseInt(raw.replace(/0[xX]/, ""), 16);
1131
+ case "b":
1132
+ return parseInt(raw.replace(/0[bB]/, ""), 2);
1133
+ case "o":
1134
+ return parseInt(raw.replace(/0[oO]/, ""), 8);
1436
1135
  }
1437
1136
  }
1438
- let errors = false;
1439
- let isPattern = false;
1440
- if (clauses.some(($1) => $1.type === "PatternClause")) {
1441
- isPattern = true;
1442
- clauses.forEach((c) => {
1443
- if (!(c.type === "PatternClause" || c.type === "DefaultClause")) {
1444
- errors = true;
1445
- return c.children.push({
1446
- type: "Error",
1447
- message: "Can't mix pattern matching and non-pattern matching clauses"
1448
- });
1449
- }
1450
- ;
1451
- return;
1452
- });
1137
+ return parseInt(raw, 10);
1138
+ }
1139
+ throw new Error("Unrecognized literal " + JSON.stringify(literal));
1140
+ }
1141
+ function startsWith(target, value) {
1142
+ if (!target)
1143
+ return;
1144
+ if (Array.isArray(target)) {
1145
+ let i = 0;
1146
+ let l = target.length;
1147
+ while (i < l) {
1148
+ const t = target[i];
1149
+ if (t && (t.length || t.token || t.children)) {
1150
+ break;
1151
+ }
1152
+ i++;
1453
1153
  }
1454
- if (errors || !isPattern) {
1455
- return;
1154
+ if (i < l) {
1155
+ return startsWith(target[i], value);
1456
1156
  }
1457
- let { condition } = s;
1458
- if (condition.type === "ParenthesizedExpression") {
1459
- condition = condition.expression;
1157
+ }
1158
+ if (typeof target === "string")
1159
+ return value.test(target);
1160
+ if (target.children)
1161
+ return startsWith(target.children, value);
1162
+ if (target.token)
1163
+ return value.test(target.token);
1164
+ return;
1165
+ }
1166
+ function hasAwait(exp) {
1167
+ return gatherRecursiveWithinFunction(exp, ({ type }) => type === "Await").length > 0;
1168
+ }
1169
+ function hasYield(exp) {
1170
+ return gatherRecursiveWithinFunction(exp, ({ type }) => type === "Yield").length > 0;
1171
+ }
1172
+ function hasImportDeclaration(exp) {
1173
+ return gatherRecursiveWithinFunction(exp, ({ type }) => type === "ImportDeclaration").length > 0;
1174
+ }
1175
+ function deepCopy(node) {
1176
+ if (node == null)
1177
+ return node;
1178
+ if (typeof node !== "object")
1179
+ return node;
1180
+ if (Array.isArray(node)) {
1181
+ return node.map(deepCopy);
1182
+ }
1183
+ if (node?.type === "Ref")
1184
+ return node;
1185
+ return Object.fromEntries(
1186
+ Object.entries(node).map(([key, value]) => {
1187
+ return [key, deepCopy(value)];
1188
+ })
1189
+ );
1190
+ }
1191
+ function removeHoistDecs(node) {
1192
+ if (node == null)
1193
+ return;
1194
+ if (typeof node !== "object")
1195
+ return;
1196
+ if ("hoistDec" in node) {
1197
+ node.hoistDec = void 0;
1198
+ }
1199
+ if (Array.isArray(node)) {
1200
+ for (const child of node) {
1201
+ removeHoistDecs(child);
1460
1202
  }
1461
- let hoistDec, refAssignment = [], ref = maybeRef(condition, "m");
1462
- if (ref !== condition) {
1463
- hoistDec = {
1464
- type: "Declaration",
1465
- children: ["let ", ref],
1466
- names: []
1467
- };
1468
- refAssignment = [{
1469
- type: "AssignmentExpression",
1470
- children: [ref, " = ", condition]
1471
- }, ","];
1203
+ return;
1204
+ }
1205
+ if (node.children) {
1206
+ for (const child of node.children) {
1207
+ removeHoistDecs(child);
1472
1208
  }
1473
- let prev = [], root = prev;
1474
- const l = clauses.length;
1475
- clauses.forEach((c, i) => {
1476
- if (c.type === "DefaultClause") {
1477
- prev.push(c.block);
1478
- return;
1479
- }
1480
- let { patterns, block } = c;
1481
- let pattern = patterns[0];
1482
- const indent = block.expressions?.[0]?.[0] || "";
1483
- const alternativeConditions = patterns.map((pattern2, i2) => {
1484
- const conditions = [];
1485
- getPatternConditions(pattern2, ref, conditions, getRef);
1486
- return conditions;
1487
- });
1488
- const conditionExpression = alternativeConditions.map((conditions, i2) => {
1489
- const conditionArray = conditions.map((c2, i3) => {
1490
- if (i3 === 0)
1491
- return c2;
1492
- return [" && ", ...c2];
1493
- });
1494
- if (i2 === 0)
1495
- return conditionArray;
1496
- return [" || ", ...conditionArray];
1497
- });
1498
- const condition2 = {
1499
- type: "ParenthesizedExpression",
1500
- children: ["(", ...refAssignment, conditionExpression, ")"],
1501
- expression: conditionExpression
1502
- };
1503
- const prefix = [];
1504
- switch (pattern.type) {
1505
- case "ArrayBindingPattern":
1506
- if (pattern.length === 0)
1507
- break;
1508
- case "ObjectBindingPattern": {
1509
- if (pattern.properties?.length === 0)
1510
- break;
1511
- let [splices, thisAssignments] = gatherBindingCode(pattern);
1512
- const patternBindings = nonMatcherBindings(pattern);
1513
- splices = splices.map((s2) => [", ", nonMatcherBindings(s2)]);
1514
- thisAssignments = thisAssignments.map((a) => [indent, a, ";"]);
1515
- const duplicateDeclarations = aggregateDuplicateBindings([patternBindings, splices], ReservedWord);
1516
- prefix.push([indent, "const ", patternBindings, " = ", ref, splices, ";"]);
1517
- prefix.push(...thisAssignments);
1518
- prefix.push(...duplicateDeclarations.map((d) => [indent, d, ";"]));
1519
- break;
1520
- }
1209
+ }
1210
+ }
1211
+ function makeAmpersandFunction(rhs) {
1212
+ let { ref, typeSuffix, body } = rhs;
1213
+ if (!(ref != null)) {
1214
+ ref = makeRef("$");
1215
+ inplacePrepend(ref, body);
1216
+ }
1217
+ if (body?.type === "ObjectExpression") {
1218
+ body = makeLeftHandSideExpression(body);
1219
+ }
1220
+ const parameters = makeNode({
1221
+ type: "Parameters",
1222
+ children: typeSuffix ? ["(", ref, typeSuffix, ")"] : [ref],
1223
+ names: []
1224
+ });
1225
+ const expressions = [[" ", body]];
1226
+ const block = makeNode({
1227
+ type: "BlockStatement",
1228
+ bare: true,
1229
+ expressions,
1230
+ children: [expressions],
1231
+ implicitlyReturned: true
1232
+ });
1233
+ const children = [parameters, " =>", block];
1234
+ const async = hasAwait(body);
1235
+ if (async) {
1236
+ children.unshift("async ");
1237
+ }
1238
+ const fn = makeNode({
1239
+ type: "ArrowFunction",
1240
+ signature: {
1241
+ modifier: {
1242
+ async
1521
1243
  }
1522
- block.expressions.unshift(...prefix);
1523
- const next = [];
1524
- braceBlock(block);
1525
- if (i < l - 1)
1526
- next.push("\n", "else ");
1527
- prev.push(["", {
1528
- type: "IfStatement",
1529
- children: ["if", condition2, block, next],
1530
- then: block,
1531
- else: next,
1532
- hoistDec
1533
- }]);
1534
- hoistDec = void 0;
1535
- refAssignment = [];
1536
- return prev = next;
1537
- });
1538
- s.type = "PatternMatchingStatement";
1539
- s.children = [root];
1540
- return addParentPointers(s, s.parent);
1244
+ },
1245
+ children,
1246
+ ref,
1247
+ block,
1248
+ parameters,
1249
+ ampersandBlock: true,
1250
+ body
1541
1251
  });
1252
+ if (isStatement(body)) {
1253
+ braceBlock(block);
1254
+ fn.ampersandBlock = false;
1255
+ delete fn.body;
1256
+ }
1257
+ return fn;
1542
1258
  }
1543
- function getPatternConditions(pattern, ref, conditions, getRef) {
1544
- if (pattern.rest)
1259
+ function makeLeftHandSideExpression(expression) {
1260
+ if (expression.parenthesized) {
1261
+ return expression;
1262
+ }
1263
+ switch (expression.type) {
1264
+ case "AmpersandRef":
1265
+ case "CallExpression":
1266
+ case "Identifier":
1267
+ case "JSXElement":
1268
+ case "JSXFragment":
1269
+ case "Literal":
1270
+ case "MemberExpression":
1271
+ case "NewExpression":
1272
+ case "ParenthesizedExpression":
1273
+ case "Ref":
1274
+ case "Placeholder":
1275
+ case "StatementExpression":
1276
+ return expression;
1277
+ }
1278
+ return makeNode({
1279
+ type: "ParenthesizedExpression",
1280
+ children: ["(", expression, ")"],
1281
+ expression,
1282
+ implicit: true,
1283
+ parent: void 0
1284
+ });
1285
+ }
1286
+ function updateParentPointers(node, parent, depth = 1) {
1287
+ if (!(node != null)) {
1545
1288
  return;
1546
- switch (pattern.type) {
1547
- case "ArrayBindingPattern": {
1548
- const { elements, length } = pattern, hasRest = elements.some((e) => e.rest), l = (length - hasRest).toString(), lengthCheck = hasRest ? [ref, ".length >= ", l] : [getRef("len"), "(", ref, ", ", l, ")"];
1549
- conditions.push(
1550
- ["Array.isArray(", ref, ")"],
1551
- lengthCheck
1552
- );
1553
- elements.forEach(({ children: [, e] }, i) => {
1554
- const subRef = [ref, "[", i.toString(), "]"];
1555
- return getPatternConditions(e, subRef, conditions, getRef);
1556
- });
1557
- const { blockPrefix } = pattern;
1558
- if (blockPrefix) {
1559
- const postElements = blockPrefix.children[1], { length: postLength } = postElements;
1560
- postElements.forEach(({ children: [, e] }, i) => {
1561
- const subRef = [ref, "[", ref, ".length - ", (postLength + i).toString(), "]"];
1562
- return getPatternConditions(e, subRef, conditions, getRef);
1563
- });
1564
- }
1565
- break;
1566
- }
1567
- case "ObjectBindingPattern": {
1568
- conditions.push(
1569
- ["typeof ", ref, " === 'object'"],
1570
- [ref, " != null"]
1571
- );
1572
- pattern.properties.forEach((p) => {
1573
- switch (p.type) {
1574
- case "PinProperty":
1575
- case "BindingProperty": {
1576
- const { name, value } = p;
1577
- let subRef;
1578
- switch (name.type) {
1579
- case "ComputedPropertyName":
1580
- conditions.push([name.expression, " in ", ref]);
1581
- subRef = [ref, name];
1582
- break;
1583
- case "Literal":
1584
- case "StringLiteral":
1585
- case "NumericLiteral":
1586
- conditions.push([name, " in ", ref]);
1587
- subRef = [ref, "[", name, "]"];
1588
- break;
1589
- default:
1590
- conditions.push(["'", name, "' in ", ref]);
1591
- subRef = [ref, ".", name];
1592
- }
1593
- if (value) {
1594
- getPatternConditions(value, subRef, conditions, getRef);
1595
- }
1596
- break;
1597
- }
1598
- }
1599
- });
1600
- break;
1601
- }
1602
- case "ConditionFragment": {
1603
- let { children } = pattern;
1604
- if (children.length) {
1605
- let [first, ...rest] = children;
1606
- let [ws, ...op] = first;
1607
- ws = [" "].concat(ws);
1608
- first = [ws, ...op];
1609
- children = [first, ...rest];
1610
- }
1611
- conditions.push(
1612
- processBinaryOpExpression([ref, children])
1613
- );
1614
- break;
1289
+ }
1290
+ if (!(typeof node === "object")) {
1291
+ return;
1292
+ }
1293
+ if (Array.isArray(node)) {
1294
+ for (const child of node) {
1295
+ updateParentPointers(child, parent, depth);
1615
1296
  }
1616
- case "RegularExpressionLiteral": {
1617
- conditions.push(
1618
- ["typeof ", ref, " === 'string'"],
1619
- [pattern, ".test(", ref, ")"]
1620
- );
1621
- break;
1297
+ return;
1298
+ }
1299
+ node = node;
1300
+ if (parent != null) {
1301
+ node.parent = parent;
1302
+ }
1303
+ if (depth && isParent(node)) {
1304
+ for (const child of node.children) {
1305
+ updateParentPointers(child, node, depth - 1);
1622
1306
  }
1623
- case "PinPattern":
1624
- conditions.push([
1625
- ref,
1626
- " === ",
1627
- pattern.expression
1628
- ]);
1629
- break;
1307
+ }
1308
+ }
1309
+ function makeNode(node) {
1310
+ updateParentPointers(node);
1311
+ return node;
1312
+ }
1313
+ function makeRef(base = "ref", id = base) {
1314
+ return {
1315
+ type: "Ref",
1316
+ base,
1317
+ id
1318
+ };
1319
+ }
1320
+ function needsRef(expression, base = "ref") {
1321
+ switch (expression.type) {
1322
+ case "Ref":
1323
+ case "Identifier":
1630
1324
  case "Literal":
1631
- conditions.push([
1632
- ref,
1633
- " === ",
1634
- pattern
1635
- ]);
1636
- break;
1637
- default:
1638
- break;
1325
+ return;
1326
+ }
1327
+ return makeRef(base);
1328
+ }
1329
+ function maybeRef(exp, base = "ref") {
1330
+ if (!needsRef(exp))
1331
+ return exp;
1332
+ return makeRef(base);
1333
+ }
1334
+ function skipIfOnlyWS(target) {
1335
+ if (!target)
1336
+ return target;
1337
+ if (Array.isArray(target)) {
1338
+ if (target.length === 1) {
1339
+ return skipIfOnlyWS(target[0]);
1340
+ } else if (target.every((e) => skipIfOnlyWS(e) === void 0)) {
1341
+ return void 0;
1342
+ }
1343
+ return target;
1344
+ }
1345
+ if (target.token != null && target.token.trim() === "") {
1346
+ return void 0;
1347
+ }
1348
+ return target;
1349
+ }
1350
+ function spliceChild(node, child, del, ...replacements) {
1351
+ const children = node?.children ?? node;
1352
+ if (!Array.isArray(children)) {
1353
+ throw new Error("spliceChild: non-array node has no children field");
1354
+ }
1355
+ const index = children.indexOf(child);
1356
+ if (index < 0) {
1357
+ throw new Error("spliceChild: child not found");
1358
+ }
1359
+ return children.splice(index, del, ...replacements);
1360
+ }
1361
+ function convertOptionalType(suffix) {
1362
+ if (suffix.t.type === "AssertsType") {
1363
+ spliceChild(suffix, suffix.optional, 1, suffix.optional = {
1364
+ type: "Error",
1365
+ message: "Can't use optional ?: syntax with asserts type"
1366
+ });
1367
+ return;
1368
+ }
1369
+ spliceChild(suffix, suffix.optional, 1, suffix.optional = void 0);
1370
+ const wrap = suffix.type === "ReturnTypeAnnotation";
1371
+ spliceChild(suffix, suffix.t, 1, suffix.t = [
1372
+ getTrimmingSpace(suffix.t),
1373
+ wrap && "(",
1374
+ // TODO: avoid parens if unnecessary
1375
+ "undefined | ",
1376
+ parenthesizeType(insertTrimmingSpace(suffix.t, "")),
1377
+ wrap && ")"
1378
+ ]);
1379
+ }
1380
+ function parenthesizeType(type) {
1381
+ if (typeNeedsNoParens.has(type.type)) {
1382
+ return type;
1383
+ }
1384
+ return ["(", type, ")"];
1385
+ }
1386
+ function wrapIIFE(expressions, asyncFlag) {
1387
+ let prefix;
1388
+ let async;
1389
+ if (asyncFlag) {
1390
+ async = "async ";
1391
+ } else if (hasAwait(expressions)) {
1392
+ async = "async ";
1393
+ prefix = {
1394
+ type: "Await",
1395
+ children: ["await "]
1396
+ };
1397
+ }
1398
+ const block = makeNode({
1399
+ type: "BlockStatement",
1400
+ expressions,
1401
+ children: ["{", expressions, "}"],
1402
+ bare: false,
1403
+ root: false,
1404
+ parent: void 0
1405
+ });
1406
+ const parameters = {
1407
+ type: "Parameters",
1408
+ children: ["()"],
1409
+ names: []
1410
+ };
1411
+ const signature = {
1412
+ modifier: {
1413
+ async: !!async
1414
+ },
1415
+ returnType: void 0
1416
+ };
1417
+ const fn = makeNode({
1418
+ type: "ArrowFunction",
1419
+ signature,
1420
+ parameters,
1421
+ returnType: void 0,
1422
+ ts: false,
1423
+ async,
1424
+ block,
1425
+ children: [async, parameters, "=>", block]
1426
+ });
1427
+ const exp = makeNode({
1428
+ type: "CallExpression",
1429
+ children: [makeLeftHandSideExpression(fn), "()"]
1430
+ });
1431
+ if (prefix) {
1432
+ return [makeLeftHandSideExpression([prefix, exp])];
1639
1433
  }
1434
+ return [exp];
1640
1435
  }
1641
- function elideMatchersFromArrayBindings(elements) {
1642
- return elements.map((el) => {
1643
- if (el.type === "BindingRestElement") {
1644
- return ["", el, void 0];
1645
- }
1646
- const { children: [ws, e, delim] } = el;
1647
- switch (e.type) {
1648
- case "Literal":
1649
- case "RegularExpressionLiteral":
1650
- case "StringLiteral":
1651
- case "PinPattern":
1652
- return delim;
1653
- default:
1654
- return [ws, nonMatcherBindings(e), delim];
1655
- }
1436
+ function wrapWithReturn(expression) {
1437
+ const children = expression ? ["return ", expression] : ["return"];
1438
+ return makeNode({
1439
+ type: "ReturnStatement",
1440
+ children,
1441
+ expression,
1442
+ parent: expression?.parent
1656
1443
  });
1657
1444
  }
1658
- function elideMatchersFromPropertyBindings(properties) {
1659
- return properties.map((p) => {
1660
- switch (p.type) {
1661
- case "BindingProperty": {
1662
- const { children, name, value } = p;
1663
- const [ws] = children;
1664
- switch (value && value.type) {
1665
- case "ArrayBindingPattern":
1666
- case "ObjectBindingPattern":
1667
- return {
1668
- ...p,
1669
- children: [ws, name, ": ", nonMatcherBindings(value), p.delim]
1670
- };
1671
- case "Identifier":
1672
- return p;
1673
- case "Literal":
1674
- case "RegularExpressionLiteral":
1675
- case "StringLiteral":
1676
- default:
1677
- return {
1678
- ...p,
1679
- children: [ws, name, p.delim]
1680
- };
1445
+ var assert, statementTypes, typeNeedsNoParens;
1446
+ var init_util = __esm({
1447
+ "source/parser/util.civet"() {
1448
+ "use strict";
1449
+ init_block();
1450
+ init_traversal();
1451
+ init_function();
1452
+ assert = {
1453
+ equal(a, b, msg) {
1454
+ if (a !== b) {
1455
+ throw new Error(`Assertion failed [${msg}]: ${a} !== ${b}`);
1681
1456
  }
1682
1457
  }
1683
- case "PinProperty":
1684
- case "BindingRestProperty":
1685
- default:
1686
- return p;
1687
- }
1688
- });
1458
+ };
1459
+ statementTypes = /* @__PURE__ */ new Set([
1460
+ "BlockStatement",
1461
+ "BreakStatement",
1462
+ "ContinueStatement",
1463
+ "DebuggerStatement",
1464
+ "Declaration",
1465
+ "DoStatement",
1466
+ "ForStatement",
1467
+ "IfStatement",
1468
+ "IterationStatement",
1469
+ "LabeledStatement",
1470
+ "ReturnStatement",
1471
+ "SwitchStatement",
1472
+ "ThrowStatement",
1473
+ "TryStatement"
1474
+ ]);
1475
+ typeNeedsNoParens = /* @__PURE__ */ new Set([
1476
+ "IdentifierType",
1477
+ "ImportType",
1478
+ "LiteralType",
1479
+ "TupleType",
1480
+ "ParenthesizedType",
1481
+ "UnaryType"
1482
+ ]);
1483
+ }
1484
+ });
1485
+
1486
+ // source/parser/traversal.civet
1487
+ function gatherRecursiveWithinFunction(node, predicate) {
1488
+ return gatherRecursive(node, predicate, isFunction);
1689
1489
  }
1690
- function nonMatcherBindings(pattern) {
1691
- switch (pattern.type) {
1692
- case "ArrayBindingPattern": {
1693
- const elements = elideMatchersFromArrayBindings(pattern.elements);
1694
- const children = ["[", elements, "]"];
1695
- return {
1696
- ...pattern,
1697
- children,
1698
- elements
1699
- };
1700
- }
1701
- case "PostRestBindingElements": {
1702
- const els = elideMatchersFromArrayBindings(pattern.children[1]);
1703
- return {
1704
- ...pattern,
1705
- children: [
1706
- pattern.children[0],
1707
- els,
1708
- ...pattern.children.slice(2)
1709
- ]
1710
- };
1490
+ function findChildIndex(parent, child) {
1491
+ if (!(parent != null)) {
1492
+ return -1;
1493
+ }
1494
+ const children = Array.isArray(parent) ? parent : parent.children;
1495
+ if (!(children != null)) {
1496
+ return -1;
1497
+ }
1498
+ for (let i1 = 0, len = children.length; i1 < len; i1++) {
1499
+ const i = i1;
1500
+ const c = children[i1];
1501
+ if (c === child || Array.isArray(c) && arrayRecurse(c)) {
1502
+ return i;
1711
1503
  }
1712
- case "ObjectBindingPattern":
1713
- return ["{", elideMatchersFromPropertyBindings(pattern.properties), "}"];
1714
- default:
1715
- return pattern;
1716
1504
  }
1717
- }
1718
- function aggregateDuplicateBindings(bindings, ReservedWord) {
1719
- const props = gatherRecursiveAll(bindings, ($2) => $2.type === "BindingProperty");
1720
- const arrayBindings = gatherRecursiveAll(bindings, ($3) => $3.type === "ArrayBindingPattern");
1721
- arrayBindings.forEach((a) => {
1722
- const { elements } = a;
1723
- return elements.forEach((element) => {
1724
- if (Array.isArray(element)) {
1725
- const [, e] = element;
1726
- if (e.type === "Identifier") {
1727
- return props.push(e);
1728
- } else if (e.type === "BindingRestElement") {
1729
- return props.push(e);
1730
- }
1731
- ;
1732
- return;
1505
+ function arrayRecurse(array) {
1506
+ for (let i2 = 0, len1 = array.length; i2 < len1; i2++) {
1507
+ const c = array[i2];
1508
+ if (c === child || Array.isArray(c) && arrayRecurse(c)) {
1509
+ return true;
1733
1510
  }
1734
- ;
1735
- return;
1736
- });
1737
- });
1738
- const declarations = [];
1739
- const propsGroupedByName = /* @__PURE__ */ new Map();
1740
- for (const p of props) {
1741
- const { name, value } = p;
1742
- const key = value?.name || name?.name || name;
1743
- if (propsGroupedByName.has(key)) {
1744
- propsGroupedByName.get(key).push(p);
1745
- } else {
1746
- propsGroupedByName.set(key, [p]);
1747
1511
  }
1512
+ return false;
1748
1513
  }
1749
- propsGroupedByName.forEach((shared, key) => {
1750
- if (!key) {
1751
- return;
1514
+ return -1;
1515
+ }
1516
+ function findAncestor(node, predicate, stopPredicate) {
1517
+ let { parent } = node;
1518
+ while (parent && !stopPredicate?.(parent, node)) {
1519
+ if (predicate(parent, node)) {
1520
+ return { ancestor: parent, child: node };
1752
1521
  }
1753
- if (ReservedWord({ fail() {
1754
- } }, {
1755
- pos: 0,
1756
- input: key
1757
- })) {
1758
- shared.forEach((p) => {
1759
- return aliasBinding(p, makeRef(`_${key}`, key));
1522
+ node = parent;
1523
+ ({ parent } = node);
1524
+ }
1525
+ return { ancestor: void 0, child: node };
1526
+ }
1527
+ function gatherNodes(node, predicate) {
1528
+ if (node == null)
1529
+ return [];
1530
+ if (Array.isArray(node)) {
1531
+ return node.flatMap((n) => gatherNodes(n, predicate));
1532
+ }
1533
+ if (predicate(node)) {
1534
+ return [node];
1535
+ }
1536
+ switch (node.type) {
1537
+ case "BlockStatement":
1538
+ return [];
1539
+ case "ForStatement":
1540
+ const isDec = node.declaration?.type === "Declaration";
1541
+ return node.children.flatMap((n) => {
1542
+ if (isDec && n === node.declaration)
1543
+ return [];
1544
+ return gatherNodes(n, predicate);
1760
1545
  });
1761
- return;
1762
- }
1763
- if (shared.length === 1) {
1764
- return;
1765
- }
1766
- const refs = shared.map((p) => {
1767
- const ref = makeRef(key);
1768
- aliasBinding(p, ref);
1769
- return ref;
1770
- });
1771
- return declarations.push(["const ", key, " = [", ...refs.map((r, i) => {
1772
- return i === 0 ? r : [", ", r];
1773
- }), "]"]);
1774
- });
1775
- return declarations;
1546
+ default:
1547
+ return gatherNodes(node.children, predicate);
1548
+ }
1549
+ }
1550
+ function gatherRecursive(node, predicate, skipPredicate) {
1551
+ if (node == null)
1552
+ return [];
1553
+ if (Array.isArray(node)) {
1554
+ return node.flatMap((n) => gatherRecursive(n, predicate, skipPredicate));
1555
+ }
1556
+ if (skipPredicate?.(node))
1557
+ return [];
1558
+ if (predicate(node)) {
1559
+ return [node];
1560
+ }
1561
+ return gatherRecursive(node.children, predicate, skipPredicate);
1776
1562
  }
1777
- function aliasBinding(p, ref) {
1778
- if (p.type === "Identifier") {
1779
- p.children[0] = ref;
1780
- } else if (p.type === "BindingRestElement") {
1781
- aliasBinding(p.binding, ref);
1782
- } else if (p.value?.type === "Identifier") {
1783
- aliasBinding(p.value, ref);
1784
- } else {
1785
- p.value = ref;
1786
- const index = p.children.indexOf(p.name);
1787
- p.children.splice(index + 1, 0, ": ", ref);
1563
+ function gatherRecursiveAll(node, predicate) {
1564
+ if (node == null)
1565
+ return [];
1566
+ if (Array.isArray(node)) {
1567
+ return node.flatMap((n) => gatherRecursiveAll(n, predicate));
1568
+ }
1569
+ const nodes = gatherRecursiveAll(node.children, predicate);
1570
+ if (predicate(node)) {
1571
+ nodes.push(node);
1788
1572
  }
1573
+ return nodes;
1789
1574
  }
1790
- var init_pattern_matching = __esm({
1791
- "source/parser/pattern-matching.civet"() {
1575
+ var init_traversal = __esm({
1576
+ "source/parser/traversal.civet"() {
1792
1577
  "use strict";
1793
- init_traversal();
1794
1578
  init_util();
1795
- init_block();
1796
- init_binding();
1797
- init_op();
1798
1579
  }
1799
1580
  });
1800
1581
 
1801
- // source/parser/function.civet
1802
- function isVoidType(t) {
1803
- return t?.type === "LiteralType" && t.t.type === "VoidType";
1804
- }
1805
- function isPromiseVoidType(t) {
1806
- return t?.type === "IdentifierType" && t.raw === "Promise" && t.args?.types?.length === 1 && isVoidType(t.args.types[0]);
1807
- }
1808
- function isGeneratorVoidType(t) {
1809
- return t?.type === "IdentifierType" && (t.raw === "Iterator" || t.raw === "Generator") && t.args?.types?.length >= 2 && isVoidType(t.args.types[1]);
1810
- }
1811
- function isAsyncGeneratorVoidType(t) {
1812
- return t?.type === "IdentifierType" && (t.raw === "AsyncIterator" || t.raw === "AsyncGenerator") && t.args?.types?.length >= 2 && isVoidType(t.args.types[1]);
1813
- }
1814
- function implicitFunctionBlock(f) {
1815
- if (f.abstract || f.block || f.signature?.optional)
1816
- return;
1817
- const { name, parent } = f;
1818
- if (parent?.type === "ExportDeclaration")
1819
- return;
1820
- const expressions = parent?.expressions ?? parent?.elements;
1821
- const currentIndex = expressions?.findIndex(([, def]) => def === f);
1822
- const following = currentIndex >= 0 && expressions[currentIndex + 1]?.[1];
1823
- if (f.type === following?.type && name && name === following.name) {
1824
- f.ts = true;
1582
+ // source/parser/op.civet
1583
+ function getPrecedence(op) {
1584
+ if (typeof op === "string") {
1585
+ return precedenceMap.get(op) ?? (() => {
1586
+ throw new Error(`Unknown operator: ${op}`);
1587
+ })();
1588
+ } else if (typeof op.prec === "number") {
1589
+ return op.prec;
1825
1590
  } else {
1826
- const block = makeEmptyBlock();
1827
- block.parent = f;
1828
- f.block = block;
1829
- f.children.push(block);
1830
- f.ts = false;
1591
+ return precedenceMap.get(op.prec ?? op.token) ?? (op.relational ? precedenceRelational : precedenceCustomDefault);
1831
1592
  }
1832
1593
  }
1833
- function processReturn(f, implicitReturns) {
1834
- let { returnType } = f.signature;
1835
- if (returnType && returnType.optional) {
1836
- convertOptionalType(returnType);
1837
- }
1838
- if (!processReturnValue(f) && implicitReturns) {
1839
- const { signature, block } = f;
1840
- const { modifier, name, returnType: returnType2 } = signature;
1841
- const { async, generator, set } = modifier;
1842
- const isMethod = f.type === "MethodDefinition";
1843
- const isConstructor = isMethod && name === "constructor";
1844
- const isVoid = isVoidType(returnType2?.t) || async && (isPromiseVoidType(returnType2?.t) || generator && isAsyncGeneratorVoidType(returnType2?.t)) || !async && generator && isGeneratorVoidType(returnType2?.t);
1845
- if (block?.type === "BlockStatement") {
1846
- if (isVoid || set || isConstructor) {
1847
- if (block.bare && block.implicitlyReturned) {
1848
- block.children = [" {", ...block.children, " }"];
1849
- block.bare = block.implicitlyReturned = false;
1594
+ function processBinaryOpExpression($0) {
1595
+ return recurse(expandChainedComparisons($0));
1596
+ function recurse(expandedOps) {
1597
+ let i = 2;
1598
+ while (i < expandedOps.length) {
1599
+ let op = expandedOps[i];
1600
+ if (op.special) {
1601
+ let advanceLeft2 = function(allowEqual) {
1602
+ while (start >= 4) {
1603
+ const prevPrec = getPrecedence(expandedOps[start - 2]);
1604
+ if (!(prevPrec > prec || allowEqual && prevPrec === prec)) {
1605
+ return prevPrec === prec;
1606
+ }
1607
+ start -= 4;
1608
+ }
1609
+ return false;
1610
+ }, advanceRight2 = function(allowEqual) {
1611
+ while (end + 4 < expandedOps.length) {
1612
+ const nextPrec = getPrecedence(expandedOps[end + 2]);
1613
+ if (!(nextPrec > prec || allowEqual && nextPrec === prec)) {
1614
+ return nextPrec === prec;
1615
+ }
1616
+ end += 4;
1617
+ }
1618
+ return false;
1619
+ };
1620
+ var advanceLeft = advanceLeft2, advanceRight = advanceRight2;
1621
+ let start = i - 2, end = i + 2;
1622
+ const prec = getPrecedence(op);
1623
+ let error;
1624
+ switch (op.assoc) {
1625
+ case "left":
1626
+ case void 0: {
1627
+ advanceLeft2(true);
1628
+ advanceRight2(false);
1629
+ break;
1630
+ }
1631
+ case "right": {
1632
+ advanceLeft2(false);
1633
+ advanceRight2(true);
1634
+ break;
1635
+ }
1636
+ case "non": {
1637
+ if (advanceLeft2(false) || advanceRight2(false)) {
1638
+ error = {
1639
+ type: "Error",
1640
+ message: `non-associative operator ${op.token} used at same precedence level without parenthesization`
1641
+ };
1642
+ }
1643
+ ;
1644
+ break;
1645
+ }
1646
+ case "arguments": {
1647
+ if (advanceLeft2(false)) {
1648
+ error = {
1649
+ type: "Error",
1650
+ message: `arguments operator ${op.token} used at same precedence level as ${expandedOps[start - 2].token} to the left`
1651
+ };
1652
+ }
1653
+ advanceRight2(true);
1654
+ break;
1655
+ }
1656
+ default: {
1657
+ throw new Error(`Unsupported associativity: ${op.assoc}`);
1658
+ }
1850
1659
  }
1851
- } else {
1852
- if (!block.implicitlyReturned) {
1853
- insertReturn(block);
1660
+ let a = start === i - 2 ? expandedOps[start] : expandedOps.slice(start, i - 1);
1661
+ let wsOp = expandedOps[i - 1];
1662
+ let wsB = expandedOps[i + 1];
1663
+ let b = end === i + 2 ? expandedOps[i + 2] : expandedOps.slice(i + 2, end + 1);
1664
+ if (op.assoc === "arguments") {
1665
+ let i2 = 2;
1666
+ while (i2 < b.length) {
1667
+ if (prec === getPrecedence(b[i2])) {
1668
+ if (!(b[i2].token === op.token)) {
1669
+ error ??= {
1670
+ type: "Error",
1671
+ message: `arguments operator ${op.token} used at same precedence level as ${b[i2].token} to the right`
1672
+ };
1673
+ }
1674
+ b[i2] = ",";
1675
+ }
1676
+ i2 += 4;
1677
+ }
1678
+ } else {
1679
+ b = recurse(b);
1854
1680
  }
1681
+ if (op.token === "instanceof" && b.type === "Literal" && b.children?.[0]?.type === "StringLiteral") {
1682
+ a = ["typeof ", makeLeftHandSideExpression(a)];
1683
+ if (op.negated) {
1684
+ op = { ...op, token: "!==", negated: false };
1685
+ } else {
1686
+ op = { ...op, token: "===" };
1687
+ }
1688
+ }
1689
+ if (op.asConst) {
1690
+ a = makeAsConst(a);
1691
+ b = makeAsConst(b);
1692
+ }
1693
+ let children;
1694
+ if (op.call) {
1695
+ wsOp = insertTrimmingSpace(wsOp, "");
1696
+ if (op.reversed) {
1697
+ wsB = insertTrimmingSpace(wsB, "");
1698
+ children = [wsOp, op.call, "(", wsB, b, ", ", a, ")", op.suffix];
1699
+ } else {
1700
+ children = [wsOp, op.call, "(", a, ",", wsB, b, ")", op.suffix];
1701
+ }
1702
+ } else if (op.method) {
1703
+ wsOp = insertTrimmingSpace(wsOp, "");
1704
+ wsB = insertTrimmingSpace(wsB, "");
1705
+ if (op.reversed) {
1706
+ if (end !== i + 2)
1707
+ b = makeLeftHandSideExpression(b);
1708
+ b = dotNumericLiteral(b);
1709
+ children = [wsB, b, wsOp, ".", op.method, "(", a, ")"];
1710
+ } else {
1711
+ if (start !== i - 2 || a.type === "NumericLiteral") {
1712
+ a = makeLeftHandSideExpression(a);
1713
+ }
1714
+ a = dotNumericLiteral(a);
1715
+ children = [a, wsOp, ".", op.method, "(", wsB, b, ")"];
1716
+ }
1717
+ } else if (op.token) {
1718
+ children = [a, wsOp, op, wsB, b];
1719
+ if (op.negated)
1720
+ children = ["(", ...children, ")"];
1721
+ } else {
1722
+ throw new Error("Unknown operator: " + JSON.stringify(op));
1723
+ }
1724
+ if (op.negated)
1725
+ children.unshift("!");
1726
+ if (error != null) {
1727
+ children.push(error);
1728
+ }
1729
+ expandedOps.splice(start, end - start + 1, {
1730
+ children
1731
+ });
1732
+ i = start + 2;
1733
+ } else {
1734
+ i += 4;
1855
1735
  }
1856
- }
1857
- }
1858
- }
1859
- function processReturnValue(func) {
1860
- const { block } = func;
1861
- const values = gatherRecursiveWithinFunction(
1862
- block,
1863
- ({ type }) => type === "ReturnValue"
1864
- );
1865
- if (!values.length) {
1866
- return false;
1867
- }
1868
- const ref = makeRef("ret");
1869
- let declaration;
1870
- values.forEach((value) => {
1871
- value.children = [ref];
1872
- const { ancestor, child } = findAncestor(
1873
- value,
1874
- ({ type }) => type === "Declaration",
1875
- isFunction
1876
- );
1877
- if (ancestor) {
1878
- return declaration ??= child;
1879
- }
1880
- ;
1881
- return;
1882
- });
1883
- let returnType = func.returnType ?? func.signature?.returnType;
1884
- if (returnType) {
1885
- const { t } = returnType;
1886
- let m;
1887
- if (m = t.type, m === "TypePredicate") {
1888
- returnType = ": boolean";
1889
- } else if (m === "AssertsType") {
1890
- returnType = void 0;
1891
- }
1892
- }
1893
- if (declaration) {
1894
- if (!(declaration.suffix != null)) {
1895
- declaration.children[1] = declaration.suffix = returnType;
1896
- }
1897
- } else {
1898
- block.expressions.unshift([
1899
- getIndent(block.expressions[0]),
1900
- {
1901
- type: "Declaration",
1902
- children: ["let ", ref, returnType],
1903
- names: []
1904
- },
1905
- ";"
1906
- ]);
1907
- }
1908
- gatherRecursiveWithinFunction(
1909
- block,
1910
- (r) => r.type === "ReturnStatement" && !r.expression
1911
- ).forEach((r) => {
1912
- r.expression = ref;
1913
- return r.children.splice(-1, 1, " ", ref);
1914
- });
1915
- if (!(block.children.at(-2)?.type === "ReturnStatement")) {
1916
- const indent = getIndent(block.expressions.at(-1)) || ";";
1917
- block.expressions.push([
1918
- [indent],
1919
- {
1920
- type: "ReturnStatement",
1921
- expression: ref,
1922
- children: ["return ", ref]
1923
- }
1924
- ]);
1736
+ }
1737
+ return expandedOps;
1925
1738
  }
1926
- return true;
1739
+ ;
1740
+ return recurse;
1927
1741
  }
1928
- function patternAsValue(pattern) {
1929
- switch (pattern.type) {
1930
- case "ArrayBindingPattern": {
1931
- const children = [...pattern.children];
1932
- const index = children.indexOf(pattern.elements);
1933
- if (index < 0)
1934
- throw new Error("failed to find elements in ArrayBindingPattern");
1935
- children[index] = pattern.elements.map((el) => {
1936
- const [ws, e, delim] = el.children;
1937
- return { ...el, children: [ws, patternAsValue(e), delim] };
1938
- });
1939
- return { ...pattern, children };
1940
- }
1941
- case "ObjectBindingPattern": {
1942
- const children = [...pattern.children];
1943
- const index = children.indexOf(pattern.properties);
1944
- if (index < 0)
1945
- throw new Error("failed to find properties in ArrayBindingPattern");
1946
- children[index] = pattern.properties.map(patternAsValue);
1947
- return { ...pattern, children };
1948
- }
1949
- case "Identifier":
1950
- case "BindingProperty": {
1951
- const children = [
1952
- // { name: value } = ... declares value, not name
1953
- pattern.value ?? pattern.name,
1954
- pattern.delim
1955
- ];
1956
- if (isWhitespaceOrEmpty(pattern.children[0])) {
1957
- children.unshift(pattern.children[0]);
1958
- }
1959
- return { ...pattern, children };
1960
- }
1961
- default:
1962
- return pattern;
1742
+ function dotNumericLiteral(literal) {
1743
+ if (literal?.type === "Literal" && /^[+-]?(?:0|[1-9](?:_[0-9]|[0-9])*)$/.test(literal.raw)) {
1744
+ literal.children.push(".");
1745
+ literal.raw += ".";
1963
1746
  }
1747
+ return literal;
1964
1748
  }
1965
- function assignResults(node, collect) {
1966
- if (!node)
1967
- return;
1968
- switch (node.type) {
1969
- case "BlockStatement":
1970
- if (node.expressions.length) {
1971
- assignResults(node.expressions.at(-1), collect);
1972
- } else {
1973
- node.expressions.push(["", collect("void 0"), ";"]);
1974
- }
1975
- return;
1976
- case "CaseBlock":
1977
- node.clauses.forEach((clause) => {
1978
- return assignResults(clause, collect);
1979
- });
1980
- return;
1981
- case "WhenClause":
1982
- case "DefaultClause":
1983
- case "PatternClause": {
1984
- assignResults(node.block, collect);
1985
- return;
1986
- }
1749
+ function makeAsConst(node) {
1750
+ if (Array.isArray(node) && node.length === 1) {
1751
+ node = node[0];
1987
1752
  }
1988
- if (!Array.isArray(node)) {
1989
- return;
1753
+ if (node.type === "Literal" && node.raw !== "null" || node.type === "ArrayExpression" || node.type === "ObjectExpression") {
1754
+ return { ...node, children: [...node.children, asConst] };
1755
+ } else {
1756
+ return node;
1990
1757
  }
1991
- let [, exp, semi] = node;
1992
- if (semi?.type === "SemicolonDelimiter") {
1993
- return;
1758
+ }
1759
+ function isExistence(exp) {
1760
+ if (exp?.type === "ParenthesizedExpression" && exp.implicit) {
1761
+ exp = exp.expression;
1994
1762
  }
1995
- if (!exp) {
1996
- return;
1763
+ if (exp?.type === "Existence") {
1764
+ return exp;
1997
1765
  }
1998
- if (isExit(exp)) {
1999
- return;
1766
+ ;
1767
+ return;
1768
+ }
1769
+ function isRelationalOp(op) {
1770
+ return op.relational || getPrecedence(op) === precedenceRelational;
1771
+ }
1772
+ function expandChainedComparisons([first, binops]) {
1773
+ if (!binops.length) {
1774
+ return [first];
2000
1775
  }
2001
- const outer = exp;
2002
- let { type } = exp;
2003
- if (type === "LabelledStatement") {
2004
- exp = exp.statement;
2005
- ({ type } = exp);
1776
+ const results = [];
1777
+ let start = 0;
1778
+ const chains = [];
1779
+ var i = 0;
1780
+ for (let i3 = 0, len2 = binops.length; i3 < len2; i3++) {
1781
+ var i = i3;
1782
+ var [, op] = binops[i3];
1783
+ if (isRelationalOp(op)) {
1784
+ chains.push(i);
1785
+ } else if (getPrecedence(op) < precedenceRelational) {
1786
+ processChains();
1787
+ first = results.pop();
1788
+ }
2006
1789
  }
2007
- switch (exp.type) {
2008
- case "BreakStatement":
2009
- case "ContinueStatement":
2010
- case "DebuggerStatement":
2011
- case "EmptyStatement":
2012
- case "ReturnStatement":
2013
- case "ThrowStatement":
2014
- return;
2015
- case "Declaration":
2016
- exp.children.push([
2017
- "",
2018
- [";", collect(patternAsValue(exp.bindings.at(-1).pattern))]
2019
- ]);
2020
- return;
2021
- case "ForStatement":
2022
- case "IterationStatement":
2023
- case "DoStatement":
2024
- wrapIterationReturningResults(exp, outer, collect);
2025
- return;
2026
- case "BlockStatement":
2027
- assignResults(exp.expressions[exp.expressions.length - 1], collect);
2028
- return;
2029
- case "IfStatement":
2030
- assignResults(exp.then, collect);
2031
- if (exp.then.bare && !exp.then.semicolon) {
2032
- exp.then.children.push(exp.then.semicolon = ";");
1790
+ processChains();
1791
+ return results;
1792
+ function processChains() {
1793
+ if (chains.length > 0) {
1794
+ first = expandExistence(first);
1795
+ for (let i4 = 0, len3 = chains.length; i4 < len3; i4++) {
1796
+ const k = i4;
1797
+ const index = chains[i4];
1798
+ if (k > 0) {
1799
+ results.push(" ", "&&", " ");
1800
+ }
1801
+ const binop = binops[index];
1802
+ const exp = binop[3] = expandExistence(binop[3]);
1803
+ results.push(first);
1804
+ const endIndex = chains[k + 1] ?? i + 1;
1805
+ results.push(...binops.slice(start, endIndex).flat());
1806
+ first = [exp].concat(binops.slice(index + 1, endIndex));
1807
+ start = endIndex;
2033
1808
  }
2034
- if (exp.else) {
2035
- assignResults(exp.else[2], collect);
2036
- } else {
2037
- exp.children.push([" else {", collect("undefined"), "}"]);
1809
+ } else {
1810
+ results.push(first);
1811
+ results.push(...binops.slice(start, i + 1).flat());
1812
+ start = i + 1;
1813
+ }
1814
+ chains.length = 0;
1815
+ }
1816
+ function expandExistence(exp) {
1817
+ let ref;
1818
+ if (ref = isExistence(exp)) {
1819
+ const existence = ref;
1820
+ results.push(existence, " ", "&&", " ");
1821
+ return existence.expression;
1822
+ } else {
1823
+ return exp;
1824
+ }
1825
+ }
1826
+ ;
1827
+ }
1828
+ var precedenceOrder, precedenceMap, precedenceStep, precedenceRelational, precedenceCustomDefault, asConst;
1829
+ var init_op = __esm({
1830
+ "source/parser/op.civet"() {
1831
+ "use strict";
1832
+ init_util();
1833
+ precedenceOrder = [
1834
+ ["||", "??"],
1835
+ ["^^"],
1836
+ ["&&"],
1837
+ ["|"],
1838
+ ["^"],
1839
+ ["&"],
1840
+ // NOTE: Equality and inequality merged because of relational chaining
1841
+ [
1842
+ "==",
1843
+ "!=",
1844
+ "===",
1845
+ "!==",
1846
+ "<",
1847
+ "<=",
1848
+ ">",
1849
+ ">=",
1850
+ "in",
1851
+ "instanceof"
1852
+ ],
1853
+ // NOTE: Extra in-between level for default custom operators
1854
+ ["custom"],
1855
+ ["<<", ">>", ">>>"],
1856
+ ["+", "-"],
1857
+ ["*", "/", "%"],
1858
+ ["**"]
1859
+ ];
1860
+ precedenceMap = /* @__PURE__ */ new Map();
1861
+ for (let i1 = 0, len = precedenceOrder.length; i1 < len; i1++) {
1862
+ const prec = i1;
1863
+ const ops = precedenceOrder[i1];
1864
+ for (let i2 = 0, len1 = ops.length; i2 < len1; i2++) {
1865
+ const op = ops[i2];
1866
+ precedenceMap.set(op, prec);
2038
1867
  }
2039
- return;
2040
- case "PatternMatchingStatement":
2041
- assignResults(exp.children[0][0], collect);
2042
- return;
2043
- case "SwitchStatement":
2044
- assignResults(exp.children[2], collect);
2045
- return;
2046
- case "TryStatement":
2047
- exp.blocks.forEach((block) => assignResults(block, collect));
2048
- return;
2049
- }
2050
- if (node.at(-1)?.type === "SemicolonDelimiter") {
2051
- return;
1868
+ }
1869
+ precedenceStep = 1 / 64;
1870
+ precedenceRelational = precedenceMap.get("==");
1871
+ precedenceCustomDefault = precedenceMap.get("custom");
1872
+ asConst = {
1873
+ ts: true,
1874
+ children: [" as const"]
1875
+ };
2052
1876
  }
2053
- node[1] = collect(node[1]);
2054
- }
2055
- function insertReturn(node, outerNode = node) {
2056
- if (!node)
2057
- return;
2058
- switch (node.type) {
2059
- case "BlockStatement":
2060
- if (node.expressions.length) {
2061
- const last = node.expressions[node.expressions.length - 1];
2062
- insertReturn(last);
2063
- } else {
2064
- if (node.parent.type === "CatchClause") {
2065
- node.expressions.push(["return"]);
1877
+ });
1878
+
1879
+ // source/parser/pattern-matching.civet
1880
+ function processPatternMatching(statements, ReservedWord, getRef) {
1881
+ gatherRecursiveAll(statements, ($) => $.type === "SwitchStatement").forEach((s) => {
1882
+ const { caseBlock } = s;
1883
+ const { clauses } = caseBlock;
1884
+ for (const c of clauses) {
1885
+ if (c.type === "WhenClause" && c.break) {
1886
+ if (isExit(c.block)) {
1887
+ c.children.splice(c.children.indexOf(c.break), 1);
1888
+ c.break = void 0;
2066
1889
  }
2067
1890
  }
1891
+ }
1892
+ let errors = false;
1893
+ let isPattern = false;
1894
+ if (clauses.some(($1) => $1.type === "PatternClause")) {
1895
+ isPattern = true;
1896
+ clauses.forEach((c) => {
1897
+ if (!(c.type === "PatternClause" || c.type === "DefaultClause")) {
1898
+ errors = true;
1899
+ return c.children.push({
1900
+ type: "Error",
1901
+ message: "Can't mix pattern matching and non-pattern matching clauses"
1902
+ });
1903
+ }
1904
+ ;
1905
+ return;
1906
+ });
1907
+ }
1908
+ if (errors || !isPattern) {
2068
1909
  return;
2069
- case "WhenClause":
2070
- if (node.break) {
2071
- node.children.splice(node.children.indexOf(node.break), 1);
1910
+ }
1911
+ let { condition } = s;
1912
+ if (condition.type === "ParenthesizedExpression") {
1913
+ condition = condition.expression;
1914
+ }
1915
+ let hoistDec, refAssignment = [], ref = maybeRef(condition, "m");
1916
+ if (ref !== condition) {
1917
+ hoistDec = {
1918
+ type: "Declaration",
1919
+ children: ["let ", ref],
1920
+ names: []
1921
+ };
1922
+ refAssignment = [{
1923
+ type: "AssignmentExpression",
1924
+ children: [ref, " = ", condition]
1925
+ }, ","];
1926
+ }
1927
+ let prev = [], root = prev;
1928
+ const l = clauses.length;
1929
+ clauses.forEach((c, i) => {
1930
+ if (c.type === "DefaultClause") {
1931
+ prev.push(c.block);
1932
+ return;
2072
1933
  }
2073
- if (node.block.expressions.length) {
2074
- insertReturn(node.block);
2075
- } else {
2076
- node.block.expressions.push(wrapWithReturn());
1934
+ let { patterns, block } = c;
1935
+ let pattern = patterns[0];
1936
+ const indent = block.expressions?.[0]?.[0] || "";
1937
+ const alternativeConditions = patterns.map((pattern2, i2) => {
1938
+ const conditions = [];
1939
+ getPatternConditions(pattern2, ref, conditions, getRef);
1940
+ return conditions;
1941
+ });
1942
+ const conditionExpression = alternativeConditions.map((conditions, i2) => {
1943
+ const conditionArray = conditions.map((c2, i3) => {
1944
+ if (i3 === 0)
1945
+ return c2;
1946
+ return [" && ", ...c2];
1947
+ });
1948
+ if (i2 === 0)
1949
+ return conditionArray;
1950
+ return [" || ", ...conditionArray];
1951
+ });
1952
+ const condition2 = {
1953
+ type: "ParenthesizedExpression",
1954
+ children: ["(", ...refAssignment, conditionExpression, ")"],
1955
+ expression: conditionExpression
1956
+ };
1957
+ const prefix = [];
1958
+ switch (pattern.type) {
1959
+ case "ArrayBindingPattern":
1960
+ if (pattern.length === 0)
1961
+ break;
1962
+ case "ObjectBindingPattern": {
1963
+ if (pattern.properties?.length === 0)
1964
+ break;
1965
+ let [splices, thisAssignments] = gatherBindingCode(pattern);
1966
+ const patternBindings = nonMatcherBindings(pattern);
1967
+ splices = splices.map((s2) => [", ", nonMatcherBindings(s2)]);
1968
+ thisAssignments = thisAssignments.map((a) => [indent, a, ";"]);
1969
+ const duplicateDeclarations = aggregateDuplicateBindings([patternBindings, splices], ReservedWord);
1970
+ prefix.push([indent, "const ", patternBindings, " = ", ref, splices, ";"]);
1971
+ prefix.push(...thisAssignments);
1972
+ prefix.push(...duplicateDeclarations.map((d) => [indent, d, ";"]));
1973
+ break;
1974
+ }
2077
1975
  }
2078
- return;
2079
- case "DefaultClause":
2080
- insertReturn(node.block);
2081
- return;
2082
- }
2083
- if (!Array.isArray(node))
2084
- return;
2085
- let [, exp, semi] = node;
2086
- if (semi?.type === "SemicolonDelimiter") {
2087
- return;
2088
- }
2089
- if (!exp) {
2090
- return;
2091
- }
2092
- if (isExit(exp)) {
2093
- return;
2094
- }
2095
- const outer = exp;
2096
- let { type } = exp;
2097
- if (type === "LabelledStatement") {
2098
- exp = exp.statement;
2099
- ({ type } = exp);
2100
- }
2101
- switch (type) {
2102
- case "BreakStatement":
2103
- case "ContinueStatement":
2104
- case "DebuggerStatement":
2105
- case "EmptyStatement":
2106
- case "ReturnStatement":
2107
- case "ThrowStatement":
2108
- return;
2109
- case "Declaration":
2110
- exp.children.push(["", {
2111
- type: "ReturnStatement",
2112
- children: [";return ", patternAsValue(exp.bindings.at(-1).pattern)],
2113
- parent: exp
1976
+ block.expressions.unshift(...prefix);
1977
+ const next = [];
1978
+ braceBlock(block);
1979
+ if (i < l - 1)
1980
+ next.push("\n", "else ");
1981
+ prev.push(["", {
1982
+ type: "IfStatement",
1983
+ children: ["if", condition2, block, next],
1984
+ then: block,
1985
+ else: next,
1986
+ hoistDec
2114
1987
  }]);
2115
- return;
2116
- case "FunctionExpression":
2117
- if (exp.id) {
2118
- exp.children.push([
2119
- "",
2120
- {
2121
- type: "ReturnStatement",
2122
- children: [";return ", exp.id],
2123
- parent: exp
1988
+ hoistDec = void 0;
1989
+ refAssignment = [];
1990
+ return prev = next;
1991
+ });
1992
+ s.type = "PatternMatchingStatement";
1993
+ s.children = [root];
1994
+ return addParentPointers(s, s.parent);
1995
+ });
1996
+ }
1997
+ function getPatternConditions(pattern, ref, conditions, getRef) {
1998
+ if (pattern.rest)
1999
+ return;
2000
+ switch (pattern.type) {
2001
+ case "ArrayBindingPattern": {
2002
+ const { elements, length } = pattern, hasRest = elements.some((e) => e.rest), l = (length - hasRest).toString(), lengthCheck = hasRest ? [ref, ".length >= ", l] : [getRef("len"), "(", ref, ", ", l, ")"];
2003
+ conditions.push(
2004
+ ["Array.isArray(", ref, ")"],
2005
+ lengthCheck
2006
+ );
2007
+ elements.forEach(({ children: [, e] }, i) => {
2008
+ const subRef = [ref, "[", i.toString(), "]"];
2009
+ return getPatternConditions(e, subRef, conditions, getRef);
2010
+ });
2011
+ const { blockPrefix } = pattern;
2012
+ if (blockPrefix) {
2013
+ const postElements = blockPrefix.children[1], { length: postLength } = postElements;
2014
+ postElements.forEach(({ children: [, e] }, i) => {
2015
+ const subRef = [ref, "[", ref, ".length - ", (postLength + i).toString(), "]"];
2016
+ return getPatternConditions(e, subRef, conditions, getRef);
2017
+ });
2018
+ }
2019
+ break;
2020
+ }
2021
+ case "ObjectBindingPattern": {
2022
+ conditions.push(
2023
+ ["typeof ", ref, " === 'object'"],
2024
+ [ref, " != null"]
2025
+ );
2026
+ pattern.properties.forEach((p) => {
2027
+ switch (p.type) {
2028
+ case "PinProperty":
2029
+ case "BindingProperty": {
2030
+ const { name, value } = p;
2031
+ let subRef;
2032
+ switch (name.type) {
2033
+ case "ComputedPropertyName":
2034
+ conditions.push([name.expression, " in ", ref]);
2035
+ subRef = [ref, name];
2036
+ break;
2037
+ case "Literal":
2038
+ case "StringLiteral":
2039
+ case "NumericLiteral":
2040
+ conditions.push([name, " in ", ref]);
2041
+ subRef = [ref, "[", name, "]"];
2042
+ break;
2043
+ default:
2044
+ conditions.push(["'", name, "' in ", ref]);
2045
+ subRef = [ref, ".", name];
2046
+ }
2047
+ if (value) {
2048
+ getPatternConditions(value, subRef, conditions, getRef);
2049
+ }
2050
+ break;
2124
2051
  }
2125
- ]);
2126
- return;
2052
+ }
2053
+ });
2054
+ break;
2055
+ }
2056
+ case "ConditionFragment": {
2057
+ let { children } = pattern;
2058
+ if (children.length) {
2059
+ let [first, ...rest] = children;
2060
+ let [ws, ...op] = first;
2061
+ ws = [" "].concat(ws);
2062
+ first = [ws, ...op];
2063
+ children = [first, ...rest];
2127
2064
  }
2065
+ conditions.push(
2066
+ processBinaryOpExpression([ref, children])
2067
+ );
2068
+ break;
2069
+ }
2070
+ case "RegularExpressionLiteral": {
2071
+ conditions.push(
2072
+ ["typeof ", ref, " === 'string'"],
2073
+ [pattern, ".test(", ref, ")"]
2074
+ );
2075
+ break;
2076
+ }
2077
+ case "PinPattern":
2078
+ conditions.push([
2079
+ ref,
2080
+ " === ",
2081
+ pattern.expression
2082
+ ]);
2083
+ break;
2084
+ case "Literal":
2085
+ conditions.push([
2086
+ ref,
2087
+ " === ",
2088
+ pattern
2089
+ ]);
2090
+ break;
2091
+ default:
2128
2092
  break;
2129
- case "ForStatement":
2130
- case "IterationStatement":
2131
- case "DoStatement":
2132
- wrapIterationReturningResults(exp, outer);
2133
- return;
2134
- case "BlockStatement":
2135
- insertReturn(exp.expressions[exp.expressions.length - 1]);
2136
- return;
2137
- case "IfStatement":
2138
- insertReturn(exp.then);
2139
- if (exp.else && exp.else.length !== 0)
2140
- insertReturn(exp.else[2]);
2141
- else
2142
- exp.children.push(["", {
2143
- type: "ReturnStatement",
2144
- // NOTE: add a prefixed semi-colon because the if block may not be braced
2145
- children: [";return"],
2146
- parent: exp
2147
- }]);
2148
- return;
2149
- case "PatternMatchingStatement":
2150
- insertReturn(exp.children[0][0]);
2151
- return;
2152
- case "SwitchStatement":
2153
- insertSwitchReturns(exp);
2154
- return;
2155
- case "TryStatement":
2156
- exp.blocks.forEach((block) => insertReturn(block));
2157
- return;
2158
2093
  }
2159
- if (node[node.length - 1]?.type === "SemicolonDelimiter")
2160
- return;
2161
- const returnStatement = wrapWithReturn(node[1]);
2162
- node.splice(1, 1, returnStatement);
2163
2094
  }
2164
- function insertSwitchReturns(exp) {
2165
- exp.caseBlock.clauses.forEach((clause) => {
2166
- return insertReturn(clause);
2095
+ function elideMatchersFromArrayBindings(elements) {
2096
+ return elements.map((el) => {
2097
+ if (el.type === "BindingRestElement") {
2098
+ return ["", el, void 0];
2099
+ }
2100
+ const { children: [ws, e, delim] } = el;
2101
+ switch (e.type) {
2102
+ case "Literal":
2103
+ case "RegularExpressionLiteral":
2104
+ case "StringLiteral":
2105
+ case "PinPattern":
2106
+ return delim;
2107
+ default:
2108
+ return [ws, nonMatcherBindings(e), delim];
2109
+ }
2167
2110
  });
2168
2111
  }
2169
- function wrapIterationReturningResults(statement, outer, collect) {
2170
- if (statement.type === "DoStatement") {
2171
- if (collect) {
2172
- assignResults(statement.block, collect);
2173
- } else {
2174
- insertReturn(statement.block, outer);
2112
+ function elideMatchersFromPropertyBindings(properties) {
2113
+ return properties.map((p) => {
2114
+ switch (p.type) {
2115
+ case "BindingProperty": {
2116
+ const { children, name, value } = p;
2117
+ const [ws] = children;
2118
+ switch (value && value.type) {
2119
+ case "ArrayBindingPattern":
2120
+ case "ObjectBindingPattern":
2121
+ return {
2122
+ ...p,
2123
+ children: [ws, name, ": ", nonMatcherBindings(value), p.delim]
2124
+ };
2125
+ case "Identifier":
2126
+ return p;
2127
+ case "Literal":
2128
+ case "RegularExpressionLiteral":
2129
+ case "StringLiteral":
2130
+ default:
2131
+ return {
2132
+ ...p,
2133
+ children: [ws, name, p.delim]
2134
+ };
2135
+ }
2136
+ }
2137
+ case "PinProperty":
2138
+ case "BindingRestProperty":
2139
+ default:
2140
+ return p;
2175
2141
  }
2176
- return;
2177
- }
2178
- assert.equal(
2179
- statement.resultsRef,
2180
- void 0,
2181
- "wrapIterationReturningResults should not be called twice on the same statement"
2182
- );
2183
- const resultsRef = statement.resultsRef = makeRef("results");
2184
- const declaration = {
2185
- type: "Declaration",
2186
- children: ["const ", resultsRef, "=[]"]
2187
- };
2188
- outer.children.unshift(["", declaration, ";"]);
2189
- assignResults(statement.block, (node) => {
2190
- return [resultsRef, ".push(", node, ")"];
2191
2142
  });
2192
- if (collect) {
2193
- statement.children.push(collect(resultsRef));
2194
- } else {
2195
- statement.children.push(";return ", resultsRef, ";");
2196
- }
2197
2143
  }
2198
- function processParams(f) {
2199
- const { type, parameters, block } = f;
2200
- const isConstructor = f.name === "constructor";
2201
- if (type === "ArrowFunction" && parameters && parameters.tp && parameters.tp.parameters.length === 1) {
2202
- parameters.tp.parameters.push(",");
2203
- }
2204
- if (!block)
2205
- return;
2206
- const { expressions } = block;
2207
- if (!expressions)
2208
- return;
2209
- const { blockPrefix } = parameters;
2210
- let indent;
2211
- if (!expressions.length) {
2212
- indent = "";
2213
- } else {
2214
- indent = expressions[0][0];
2215
- }
2216
- const [splices, thisAssignments] = gatherBindingCode(parameters, {
2217
- injectParamProps: isConstructor
2218
- });
2219
- const delimiter = {
2220
- type: "SemicolonDelimiter",
2221
- children: [";"]
2222
- };
2223
- const prefix = splices.map((s) => ["let ", s]).concat(thisAssignments).map(
2224
- (s) => s.type ? {
2225
- // TODO: figure out how to get JS only statement tuples
2226
- ...s,
2227
- children: [indent, ...s.children, delimiter]
2228
- } : [indent, s, delimiter]
2229
- );
2230
- if (!prefix.length)
2231
- return;
2232
- if (isConstructor) {
2233
- const superCalls = gatherNodes(expressions, (exp) => {
2234
- return exp.type === "CallExpression" && exp.children[0]?.token === "super";
2235
- });
2236
- if (superCalls.length) {
2237
- const { child } = findAncestor(
2238
- superCalls[0],
2239
- (ancestor) => ancestor === block
2240
- );
2241
- const index = findChildIndex(expressions, child);
2242
- if (index < 0) {
2243
- throw new Error("Could not find super call within top-level expressions");
2244
- }
2245
- expressions.splice(index + 1, 0, ...prefix);
2246
- return;
2144
+ function nonMatcherBindings(pattern) {
2145
+ switch (pattern.type) {
2146
+ case "ArrayBindingPattern": {
2147
+ const elements = elideMatchersFromArrayBindings(pattern.elements);
2148
+ const children = ["[", elements, "]"];
2149
+ return {
2150
+ ...pattern,
2151
+ children,
2152
+ elements
2153
+ };
2154
+ }
2155
+ case "PostRestBindingElements": {
2156
+ const els = elideMatchersFromArrayBindings(pattern.children[1]);
2157
+ return {
2158
+ ...pattern,
2159
+ children: [
2160
+ pattern.children[0],
2161
+ els,
2162
+ ...pattern.children.slice(2)
2163
+ ]
2164
+ };
2247
2165
  }
2166
+ case "ObjectBindingPattern":
2167
+ return ["{", elideMatchersFromPropertyBindings(pattern.properties), "}"];
2168
+ default:
2169
+ return pattern;
2248
2170
  }
2249
- expressions.unshift(...prefix);
2250
2171
  }
2251
- function processFunctions(statements, config) {
2252
- gatherRecursiveAll(statements, ({ type }) => type === "FunctionExpression" || type === "ArrowFunction").forEach((f) => {
2253
- if (f.type === "FunctionExpression")
2254
- implicitFunctionBlock(f);
2255
- processParams(f);
2256
- return processReturn(f, config.implicitReturns);
2257
- });
2258
- gatherRecursiveAll(statements, ({ type }) => type === "MethodDefinition").forEach((f) => {
2259
- implicitFunctionBlock(f);
2260
- processParams(f);
2261
- return processReturn(f, config.implicitReturns);
2172
+ function aggregateDuplicateBindings(bindings, ReservedWord) {
2173
+ const props = gatherRecursiveAll(bindings, ($2) => $2.type === "BindingProperty");
2174
+ const arrayBindings = gatherRecursiveAll(bindings, ($3) => $3.type === "ArrayBindingPattern");
2175
+ arrayBindings.forEach((a) => {
2176
+ const { elements } = a;
2177
+ return elements.forEach((element) => {
2178
+ if (Array.isArray(element)) {
2179
+ const [, e] = element;
2180
+ if (e.type === "Identifier") {
2181
+ return props.push(e);
2182
+ } else if (e.type === "BindingRestElement") {
2183
+ return props.push(e);
2184
+ }
2185
+ ;
2186
+ return;
2187
+ }
2188
+ ;
2189
+ return;
2190
+ });
2262
2191
  });
2263
- }
2264
- function expressionizeIteration(exp) {
2265
- const { async, subtype, block, children, statement } = exp;
2266
- const i = children.indexOf(statement);
2267
- if (i < 0) {
2268
- throw new Error("Could not find iteration statement in iteration expression");
2269
- }
2270
- if (subtype === "DoStatement") {
2271
- children.splice(i, 1, ...wrapIIFE([["", statement, void 0]], async));
2272
- updateParentPointers(exp);
2273
- return;
2192
+ const declarations = [];
2193
+ const propsGroupedByName = /* @__PURE__ */ new Map();
2194
+ for (const p of props) {
2195
+ const { name, value } = p;
2196
+ const key = value?.name || name?.name || name;
2197
+ if (propsGroupedByName.has(key)) {
2198
+ propsGroupedByName.get(key).push(p);
2199
+ } else {
2200
+ propsGroupedByName.set(key, [p]);
2201
+ }
2274
2202
  }
2275
- exp.resultsRef ??= makeRef("results");
2276
- const { resultsRef } = exp;
2277
- assignResults(block, (node) => {
2278
- return [resultsRef, ".push(", node, ")"];
2203
+ propsGroupedByName.forEach((shared, key) => {
2204
+ if (!key) {
2205
+ return;
2206
+ }
2207
+ if (ReservedWord({ fail() {
2208
+ } }, {
2209
+ pos: 0,
2210
+ input: key
2211
+ })) {
2212
+ shared.forEach((p) => {
2213
+ return aliasBinding(p, makeRef(`_${key}`, key));
2214
+ });
2215
+ return;
2216
+ }
2217
+ if (shared.length === 1) {
2218
+ return;
2219
+ }
2220
+ const refs = shared.map((p) => {
2221
+ const ref = makeRef(key);
2222
+ aliasBinding(p, ref);
2223
+ return ref;
2224
+ });
2225
+ return declarations.push(["const ", key, " = [", ...refs.map((r, i) => {
2226
+ return i === 0 ? r : [", ", r];
2227
+ }), "]"]);
2279
2228
  });
2280
- braceBlock(block);
2281
- children.splice(
2282
- i,
2283
- 1,
2284
- ...wrapIIFE([
2285
- ["", ["const ", resultsRef, "=[]"], ";"],
2286
- ...children.map((c) => ["", c, void 0]),
2287
- ["", wrapWithReturn(resultsRef)]
2288
- ], async)
2289
- );
2290
- updateParentPointers(exp);
2229
+ return declarations;
2291
2230
  }
2292
- function skipImplicitArguments(args) {
2293
- if (args.length === 1) {
2294
- let arg0 = args[0];
2295
- if (arg0.type === "StatementExpression") {
2296
- arg0 = arg0.statement;
2297
- }
2298
- return arg0.type === "IterationExpression" && arg0.subtype !== "DoStatement" && !arg0.async && isEmptyBareBlock(arg0.block);
2231
+ function aliasBinding(p, ref) {
2232
+ if (p.type === "Identifier") {
2233
+ p.children[0] = ref;
2234
+ } else if (p.type === "BindingRestElement") {
2235
+ aliasBinding(p.binding, ref);
2236
+ } else if (p.value?.type === "Identifier") {
2237
+ aliasBinding(p.value, ref);
2238
+ } else {
2239
+ p.value = ref;
2240
+ const index = p.children.indexOf(p.name);
2241
+ p.children.splice(index + 1, 0, ": ", ref);
2299
2242
  }
2300
- return false;
2301
2243
  }
2302
- var init_function = __esm({
2303
- "source/parser/function.civet"() {
2244
+ var init_pattern_matching = __esm({
2245
+ "source/parser/pattern-matching.civet"() {
2304
2246
  "use strict";
2305
- init_block();
2306
- init_binding();
2307
2247
  init_traversal();
2308
2248
  init_util();
2249
+ init_block();
2250
+ init_binding();
2251
+ init_op();
2309
2252
  }
2310
2253
  });
2311
2254
 
@@ -2323,7 +2266,7 @@ var Civet = (() => {
2323
2266
  const thisAssignments = assignments.map((a) => ["", a, ";"]);
2324
2267
  const initializer = makeNode({
2325
2268
  type: "Initializer",
2326
- exp: e,
2269
+ expression: e,
2327
2270
  children: [ws, assign, e]
2328
2271
  });
2329
2272
  const binding = makeNode({
@@ -2364,7 +2307,7 @@ var Civet = (() => {
2364
2307
  });
2365
2308
  }
2366
2309
  function prependStatementExpressionBlock(initializer, statement) {
2367
- let { exp } = initializer;
2310
+ let { expression: exp } = initializer;
2368
2311
  let ws;
2369
2312
  if (Array.isArray(exp)) {
2370
2313
  ws = exp[0];
@@ -2384,7 +2327,7 @@ var Civet = (() => {
2384
2327
  const statement2 = statementExp.statement;
2385
2328
  blockStatement[1] = statement2;
2386
2329
  if (statement2.type === "DoStatement") {
2387
- ref = initializer.exp = initializer.children[2] = makeRef();
2330
+ ref = initializer.expression = initializer.children[2] = makeRef();
2388
2331
  assignResults(blockStatement, (resultNode) => {
2389
2332
  return makeNode({
2390
2333
  type: "AssignmentExpression",
@@ -2400,10 +2343,10 @@ var Civet = (() => {
2400
2343
  } else {
2401
2344
  wrapIterationReturningResults(statement2, { children: blockStatement }, function() {
2402
2345
  });
2403
- ref = initializer.exp = initializer.children[2] = statement2.resultsRef;
2346
+ ref = initializer.expression = initializer.children[2] = statement2.resultsRef;
2404
2347
  }
2405
2348
  } else {
2406
- ref = initializer.exp = initializer.children[2] = makeRef();
2349
+ ref = initializer.expression = initializer.children[2] = makeRef();
2407
2350
  assignResults(blockStatement, (resultNode) => {
2408
2351
  return makeNode({
2409
2352
  type: "AssignmentExpression",
@@ -2602,7 +2545,7 @@ var Civet = (() => {
2602
2545
  }
2603
2546
  })();
2604
2547
  const c = "const";
2605
- const exp = [
2548
+ const expression = [
2606
2549
  justDefault ? "(" : void 0,
2607
2550
  { type: "Await", children: ["await"] },
2608
2551
  " ",
@@ -2613,8 +2556,8 @@ var Civet = (() => {
2613
2556
  ];
2614
2557
  const initializer = {
2615
2558
  type: "Initializer",
2616
- exp,
2617
- children: [" ", "= ", exp]
2559
+ expression,
2560
+ children: [" ", "= ", expression]
2618
2561
  };
2619
2562
  const bindings = [{
2620
2563
  type: "Binding",
@@ -2631,7 +2574,7 @@ var Civet = (() => {
2631
2574
  ];
2632
2575
  const initializer2 = {
2633
2576
  type: "Initializer",
2634
- exp,
2577
+ expression,
2635
2578
  children: [" ", "= ", exp2]
2636
2579
  };
2637
2580
  bindings.push({
@@ -2644,7 +2587,7 @@ var Civet = (() => {
2644
2587
  const pattern3 = convertNamedImportsToObject(imports.children.at(-1), true);
2645
2588
  const initializer3 = {
2646
2589
  type: "Initializer",
2647
- exp: pattern,
2590
+ expression: pattern,
2648
2591
  children: [" ", "= ", pattern]
2649
2592
  };
2650
2593
  bindings.push({
@@ -2702,6 +2645,97 @@ var Civet = (() => {
2702
2645
  }
2703
2646
  });
2704
2647
 
2648
+ // source/parser/unary.civet
2649
+ function processUnaryExpression(pre, exp, post) {
2650
+ if (!(pre.length || post))
2651
+ return exp;
2652
+ if (post?.token === "?") {
2653
+ post = {
2654
+ $loc: post.$loc,
2655
+ token: " != null"
2656
+ };
2657
+ if (pre.length) {
2658
+ const lastPre = pre.at(-1);
2659
+ if (lastPre.token === "!") {
2660
+ post.token = " == null";
2661
+ pre = pre.slice(0, -1);
2662
+ } else if (lastPre.length === 2 && lastPre[0].token === "!") {
2663
+ post.token = " == null";
2664
+ pre = pre.slice(0, -1);
2665
+ }
2666
+ }
2667
+ const existence = {
2668
+ type: "Existence",
2669
+ expression: exp,
2670
+ children: [exp, post],
2671
+ parent: void 0
2672
+ };
2673
+ exp = makeLeftHandSideExpression(existence);
2674
+ if (pre.length) {
2675
+ return {
2676
+ type: "UnaryExpression",
2677
+ children: [...pre, exp]
2678
+ };
2679
+ }
2680
+ return exp;
2681
+ }
2682
+ if (exp.type === "Literal") {
2683
+ if (pre.length === 1) {
2684
+ const { token } = pre[0];
2685
+ if (token === "-" || token === "+") {
2686
+ const children = [pre[0], ...exp.children];
2687
+ const literal = {
2688
+ type: "Literal",
2689
+ children,
2690
+ raw: `${token}${exp.raw}`
2691
+ };
2692
+ if (post) {
2693
+ return {
2694
+ type: "UnaryExpression",
2695
+ children: [literal, post]
2696
+ };
2697
+ }
2698
+ return literal;
2699
+ }
2700
+ }
2701
+ }
2702
+ let ref;
2703
+ while (ref = pre.length) {
2704
+ const l = ref;
2705
+ const last = pre[l - 1];
2706
+ if (last.type === "Await") {
2707
+ if (last.op) {
2708
+ if (exp.type !== "ParenthesizedExpression") {
2709
+ exp = ["(", exp, ")"];
2710
+ }
2711
+ exp = {
2712
+ type: "CallExpression",
2713
+ children: [...last.children, "Promise", last.op, exp]
2714
+ };
2715
+ pre = pre.slice(0, -1);
2716
+ } else {
2717
+ exp = {
2718
+ type: "AwaitExpression",
2719
+ children: [...last.children, exp]
2720
+ };
2721
+ pre = pre.slice(0, -1);
2722
+ }
2723
+ } else {
2724
+ break;
2725
+ }
2726
+ }
2727
+ return {
2728
+ type: "UnaryExpression",
2729
+ children: [...pre, exp, post]
2730
+ };
2731
+ }
2732
+ var init_unary = __esm({
2733
+ "source/parser/unary.civet"() {
2734
+ "use strict";
2735
+ init_util();
2736
+ }
2737
+ });
2738
+
2705
2739
  // source/parser/pipe.civet
2706
2740
  function constructInvocation(fn, arg) {
2707
2741
  const fnArr = [fn.leadingComment, fn.expr, fn.trailingComment];
@@ -2828,7 +2862,7 @@ var Civet = (() => {
2828
2862
  names: null,
2829
2863
  lhs,
2830
2864
  assigned: arg,
2831
- exp: children
2865
+ expression: children
2832
2866
  });
2833
2867
  arg = clone(arg);
2834
2868
  removeHoistDecs(arg);
@@ -3204,7 +3238,7 @@ var Civet = (() => {
3204
3238
  scopes.pop();
3205
3239
  statements.splice(0, statements.length, ...targetStatements);
3206
3240
  }
3207
- function createVarDecs(statements, scopes, pushVar) {
3241
+ function createVarDecs(block, scopes, pushVar) {
3208
3242
  function hasDec(name) {
3209
3243
  return scopes.some((s) => s.has(name));
3210
3244
  }
@@ -3223,6 +3257,7 @@ var Civet = (() => {
3223
3257
  return decs.add(name);
3224
3258
  };
3225
3259
  }
3260
+ const { expressions: statements } = block;
3226
3261
  const decs = findDecs(statements);
3227
3262
  scopes.push(decs);
3228
3263
  const varIds = [];
@@ -3236,19 +3271,19 @@ var Civet = (() => {
3236
3271
  const fnNodes = gatherNodes(statements, isFunction);
3237
3272
  const forNodes = gatherNodes(statements, (s) => s.type === "ForStatement");
3238
3273
  const blockNodes = new Set(gatherNodes(statements, (s) => s.type === "BlockStatement"));
3239
- fnNodes.forEach(({ block }) => blockNodes.delete(block));
3240
- forNodes.forEach(({ block }) => blockNodes.delete(block));
3241
- blockNodes.forEach((block) => {
3242
- return createVarDecs(block.expressions, scopes, pushVar);
3274
+ fnNodes.forEach(({ block: block2 }) => blockNodes.delete(block2));
3275
+ forNodes.forEach(({ block: block2 }) => blockNodes.delete(block2));
3276
+ blockNodes.forEach((block2) => {
3277
+ return createVarDecs(block2, scopes, pushVar);
3243
3278
  });
3244
- forNodes.forEach(({ block, declaration }) => {
3279
+ forNodes.forEach(({ block: block2, declaration }) => {
3245
3280
  scopes.push(new Set(declaration.names));
3246
- createVarDecs(block.expressions, scopes, pushVar);
3281
+ createVarDecs(block2, scopes, pushVar);
3247
3282
  return scopes.pop();
3248
3283
  });
3249
- fnNodes.forEach(({ block, parameters }) => {
3284
+ fnNodes.forEach(({ block: block2, parameters }) => {
3250
3285
  scopes.push(new Set(parameters.names));
3251
- createVarDecs(block.expressions, scopes);
3286
+ createVarDecs(block2, scopes);
3252
3287
  return scopes.pop();
3253
3288
  });
3254
3289
  if (varIds.length) {
@@ -3257,6 +3292,7 @@ var Civet = (() => {
3257
3292
  if (statements[0][1]?.parent?.root) {
3258
3293
  delimiter = ";\n";
3259
3294
  }
3295
+ braceBlock(block);
3260
3296
  statements.unshift([indent, {
3261
3297
  type: "Declaration",
3262
3298
  children: ["var ", varIds.join(", ")]
@@ -3680,7 +3716,7 @@ var Civet = (() => {
3680
3716
  2,
3681
3717
  commaCount ? {
3682
3718
  type: "ParenthesizedExpression",
3683
- children: ["(", call, ")"]
3719
+ children: ["(", ...call.children, ")"]
3684
3720
  } : { ...call, type: "ParenthesizedExpression" }
3685
3721
  );
3686
3722
  }
@@ -4100,13 +4136,13 @@ var Civet = (() => {
4100
4136
  statements,
4101
4137
  (n) => n.type === "AssignmentExpression" && n.names === null,
4102
4138
  (exp) => {
4103
- let { lhs: $1, exp: $2 } = exp, tail = [], i = 0, len = $1.length;
4139
+ let { lhs: $1, expression: $2 } = exp, tail = [], i = 0, len = $1.length;
4104
4140
  let block;
4105
4141
  if (exp.parent?.type === "BlockStatement" && !$1.at(-1)?.at(-1)?.special) {
4106
4142
  block = makeBlockFragment();
4107
4143
  let ref4;
4108
4144
  if (ref4 = prependStatementExpressionBlock(
4109
- { type: "Initializer", exp: $2, children: [void 0, void 0, $2] },
4145
+ { type: "Initializer", expression: $2, children: [void 0, void 0, $2] },
4110
4146
  block
4111
4147
  )) {
4112
4148
  const ref = ref4;
@@ -4132,7 +4168,7 @@ var Civet = (() => {
4132
4168
  exp.children.splice(
4133
4169
  index2,
4134
4170
  1,
4135
- exp.exp = $2 = [call, "(", lhs, ", ", $2, ")"]
4171
+ exp.expression = $2 = [call, "(", lhs, ", ", $2, ")"]
4136
4172
  );
4137
4173
  if (omitLhs) {
4138
4174
  return $2;
@@ -4449,7 +4485,7 @@ var Civet = (() => {
4449
4485
  } else if (config.autoConst) {
4450
4486
  createConstLetDecs(statements, [], "const");
4451
4487
  } else if (config.autoVar) {
4452
- createVarDecs(statements, []);
4488
+ createVarDecs(root, []);
4453
4489
  }
4454
4490
  processBlocks(statements);
4455
4491
  populateRefs(statements);
@@ -4500,7 +4536,7 @@ var Civet = (() => {
4500
4536
  const { type } = ancestor2;
4501
4537
  return type === "Call" || type === "BlockStatement" || type === "PipelineExpression" || // Declaration
4502
4538
  type === "Initializer" || // Right-hand side of assignment
4503
- type === "AssignmentExpression" && ancestor2.exp === child2;
4539
+ type === "AssignmentExpression" && ancestor2.expression === child2 || type === "ReturnStatement" || type === "YieldExpression";
4504
4540
  }));
4505
4541
  switch (ancestor?.type) {
4506
4542
  case "Call": {
@@ -4540,11 +4576,13 @@ var Civet = (() => {
4540
4576
  break;
4541
4577
  }
4542
4578
  case "AssignmentExpression":
4543
- case "Initializer": {
4579
+ case "Initializer":
4580
+ case "ReturnStatement":
4581
+ case "YieldExpression": {
4544
4582
  const i = findChildIndex(ancestor, child);
4545
- if (i >= 0 && ancestor.exp === ancestor.children[i]) {
4546
- ancestor.exp = ancestor.children[i] = maybeWrap(ancestor.exp, ancestor);
4547
- ancestor = ancestor.exp;
4583
+ if (i >= 0 && ancestor.expression === ancestor.children[i]) {
4584
+ ancestor.expression = ancestor.children[i] = maybeWrap(ancestor.expression, ancestor);
4585
+ ancestor = ancestor.expression;
4548
4586
  } else {
4549
4587
  ancestor = void 0;
4550
4588
  }
@@ -4595,8 +4633,10 @@ var Civet = (() => {
4595
4633
  break;
4596
4634
  }
4597
4635
  case "AssignmentExpression":
4598
- case "Initializer": {
4599
- outer = ancestor === parent.exp;
4636
+ case "Initializer":
4637
+ case "ReturnStatement":
4638
+ case "YieldExpression": {
4639
+ outer = ancestor === parent.expression;
4600
4640
  break;
4601
4641
  }
4602
4642
  }
@@ -5344,7 +5384,6 @@ ${input.slice(result.pos)}
5344
5384
  ActualAssignment,
5345
5385
  NonPipelineActualAssignment,
5346
5386
  YieldExpression,
5347
- YieldTail,
5348
5387
  ArrowFunction,
5349
5388
  FatArrow,
5350
5389
  TrailingDeclaration,
@@ -6956,7 +6995,7 @@ ${input.slice(result.pos)}
6956
6995
  names: null,
6957
6996
  lhs: $1,
6958
6997
  assigned: $1[0][1],
6959
- exp: $2
6998
+ expression: $2
6960
6999
  };
6961
7000
  });
6962
7001
  function ActualAssignment(ctx, state) {
@@ -6973,22 +7012,30 @@ ${input.slice(result.pos)}
6973
7012
  names: null,
6974
7013
  lhs: $1,
6975
7014
  assigned: $1[0][1],
6976
- exp: $2
7015
+ expression: $2
6977
7016
  };
6978
7017
  });
6979
7018
  function NonPipelineActualAssignment(ctx, state) {
6980
7019
  return $EVENT(ctx, state, "NonPipelineActualAssignment", NonPipelineActualAssignment$0);
6981
7020
  }
6982
- var YieldExpression$0 = $S(Yield, YieldTail);
7021
+ var YieldExpression$0 = $TS($S(Yield, $E($S($E($S($E(_), Star)), MaybeNestedExpression))), function($skip, $loc, $0, $1, $2) {
7022
+ if ($2) {
7023
+ const [star, expression] = $2;
7024
+ return {
7025
+ type: "YieldExpression",
7026
+ star,
7027
+ expression,
7028
+ children: [$1, star, expression]
7029
+ };
7030
+ }
7031
+ return {
7032
+ type: "YieldExpression",
7033
+ children: [$1]
7034
+ };
7035
+ });
6983
7036
  function YieldExpression(ctx, state) {
6984
7037
  return $EVENT(ctx, state, "YieldExpression", YieldExpression$0);
6985
7038
  }
6986
- var YieldTail$0 = $Y(EOS);
6987
- var YieldTail$1 = $S($E($S($E(_), Star)), AssignmentExpression);
6988
- var YieldTail$$ = [YieldTail$0, YieldTail$1];
6989
- function YieldTail(ctx, state) {
6990
- return $EVENT_C(ctx, state, "YieldTail", YieldTail$$);
6991
- }
6992
7039
  var ArrowFunction$0 = ThinArrowFunction;
6993
7040
  var ArrowFunction$1 = $TS($S($E($S(Async, _)), ArrowParameters, $E(ReturnTypeSuffix), FatArrow, FatArrowBody), function($skip, $loc, $0, $1, $2, $3, $4, $5) {
6994
7041
  var async = $1;
@@ -8708,66 +8755,66 @@ ${input.slice(result.pos)}
8708
8755
  var op = $4;
8709
8756
  var ws2 = $5;
8710
8757
  var close = $6;
8711
- const refB = makeRef("b"), body = processBinaryOpExpression([lhs, [
8712
- [ws1, op, ws2, refB]
8713
- // BinaryOpRHS
8714
- ]]);
8715
- const parameters = {
8716
- type: "Parameters",
8717
- children: ["(", refB, ")"],
8718
- names: []
8719
- };
8720
- const block = {
8721
- expressions: [body]
8722
- };
8758
+ const refB = makeRef("b");
8759
+ const fn = makeAmpersandFunction({
8760
+ ref: refB,
8761
+ body: processBinaryOpExpression([lhs, [
8762
+ [ws1, op, ws2, refB]
8763
+ // BinaryOpRHS
8764
+ ]])
8765
+ });
8723
8766
  return {
8724
- type: "ArrowFunction",
8725
- signature: {
8726
- modifier: {}
8727
- },
8728
- children: [open, parameters, " => ", body, close],
8729
- body,
8730
- parenthesized: true,
8731
- ampersandBlock: true,
8767
+ type: "ParenthesizedExpression",
8768
+ children: [open, fn, close],
8769
+ expression: fn
8770
+ };
8771
+ });
8772
+ var FunctionExpression$3 = $TS($S(OpenParen, $P($S(NotDedented, UpdateExpression, WAssignmentOp)), __, CloseParen), function($skip, $loc, $0, $1, $2, $3, $4) {
8773
+ var open = $1;
8774
+ var lhs = $2;
8775
+ var ws2 = $3;
8776
+ var close = $4;
8777
+ lhs = lhs.map((x) => [x[0], x[1], ...x[2]]);
8778
+ const refB = makeRef("b");
8779
+ const fn = makeAmpersandFunction({
8732
8780
  ref: refB,
8733
- block,
8734
- parameters
8781
+ body: {
8782
+ type: "AssignmentExpression",
8783
+ children: [lhs, ws2, refB],
8784
+ names: null,
8785
+ lhs,
8786
+ assigned: lhs[0][1],
8787
+ expression: refB
8788
+ }
8789
+ });
8790
+ return {
8791
+ type: "ParenthesizedExpression",
8792
+ children: [open, fn, close],
8793
+ expression: fn
8735
8794
  };
8736
8795
  });
8737
- var FunctionExpression$3 = $TS($S(OpenParen, __, $N($EXPECT($R13, "FunctionExpression /\\+\\+|--|[\\+\\-&]\\S/")), BinaryOp, __, NonPipelineAssignmentExpression, CloseParen), function($skip, $loc, $0, $1, $2, $3, $4, $5, $6, $7) {
8796
+ var FunctionExpression$4 = $TS($S(OpenParen, __, $N($EXPECT($R13, "FunctionExpression /\\+\\+|--|[\\+\\-&]\\S/")), BinaryOp, __, NonPipelineAssignmentExpression, CloseParen), function($skip, $loc, $0, $1, $2, $3, $4, $5, $6, $7) {
8738
8797
  var open = $1;
8739
8798
  var ws1 = $2;
8740
8799
  var op = $4;
8741
8800
  var ws2 = $5;
8742
8801
  var rhs = $6;
8743
8802
  var close = $7;
8744
- const refA = makeRef("a"), body = processBinaryOpExpression([refA, [
8745
- [ws1, op, ws2, rhs]
8746
- // BinaryOpRHS
8747
- ]]);
8748
- const parameters = {
8749
- type: "Parameters",
8750
- children: ["(", refA, ")"],
8751
- names: []
8752
- };
8753
- const block = {
8754
- expressions: [body]
8755
- };
8756
- return {
8757
- type: "ArrowFunction",
8758
- signature: {
8759
- modifier: {}
8760
- },
8761
- children: [open, parameters, " => ", body, close],
8762
- body,
8763
- parenthesized: true,
8764
- ampersandBlock: true,
8803
+ const refA = makeRef("a");
8804
+ const fn = makeAmpersandFunction({
8765
8805
  ref: refA,
8766
- block,
8767
- parameters
8806
+ body: processBinaryOpExpression([refA, [
8807
+ [ws1, op, ws2, rhs]
8808
+ // BinaryOpRHS
8809
+ ]])
8810
+ });
8811
+ return {
8812
+ type: "ParenthesizedExpression",
8813
+ children: [open, fn, close],
8814
+ expression: fn
8768
8815
  };
8769
8816
  });
8770
- var FunctionExpression$$ = [FunctionExpression$0, FunctionExpression$1, FunctionExpression$2, FunctionExpression$3];
8817
+ var FunctionExpression$$ = [FunctionExpression$0, FunctionExpression$1, FunctionExpression$2, FunctionExpression$3, FunctionExpression$4];
8771
8818
  function FunctionExpression(ctx, state) {
8772
8819
  return $EVENT_C(ctx, state, "FunctionExpression", FunctionExpression$$);
8773
8820
  }
@@ -12339,8 +12386,8 @@ ${input.slice(result.pos)}
12339
12386
  return $EVENT_C(ctx, state, "LexicalBinding", LexicalBinding$$);
12340
12387
  }
12341
12388
  var Initializer$0 = $T($S(__, Equals, ExtendedExpression), function(value) {
12342
- var exp = value[2];
12343
- return { "type": "Initializer", "exp": exp, "children": value };
12389
+ var expression = value[2];
12390
+ return { "type": "Initializer", "expression": expression, "children": value };
12344
12391
  });
12345
12392
  function Initializer(ctx, state) {
12346
12393
  return $EVENT(ctx, state, "Initializer", Initializer$0);
@@ -15812,7 +15859,6 @@ ${input.slice(result.pos)}
15812
15859
  exports.ActualAssignment = ActualAssignment;
15813
15860
  exports.NonPipelineActualAssignment = NonPipelineActualAssignment;
15814
15861
  exports.YieldExpression = YieldExpression;
15815
- exports.YieldTail = YieldTail;
15816
15862
  exports.ArrowFunction = ArrowFunction;
15817
15863
  exports.FatArrow = FatArrow;
15818
15864
  exports.TrailingDeclaration = TrailingDeclaration;