parseman 0.49.0 → 0.50.0

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 (77) hide show
  1. package/dist/analysis/commitment.d.ts +2 -1
  2. package/dist/analysis/commitment.d.ts.map +1 -1
  3. package/dist/analysis/diagnostics.js +1931 -861
  4. package/dist/analysis/diagnostics.js.map +3 -3
  5. package/dist/analysis/rebuild.d.ts.map +1 -1
  6. package/dist/cli/index.js +1235 -164
  7. package/dist/cli/index.js.map +3 -3
  8. package/dist/combinators/trivia-skip.d.ts +1 -1
  9. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  10. package/dist/compiler/build-arity.d.ts +16 -0
  11. package/dist/compiler/build-arity.d.ts.map +1 -1
  12. package/dist/compiler/degradation.d.ts +0 -2
  13. package/dist/compiler/degradation.d.ts.map +1 -1
  14. package/dist/compiler/ir-serialize.d.ts.map +1 -1
  15. package/dist/compiler/token-alphabet.d.ts +11 -0
  16. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  17. package/dist/compiler/token-capability.js +185 -20
  18. package/dist/compiler/token-capability.js.map +1 -1
  19. package/dist/cst/capture-buffer.d.ts +5 -1
  20. package/dist/cst/capture-buffer.d.ts.map +1 -1
  21. package/dist/index.js +1348 -279
  22. package/dist/index.js.map +3 -3
  23. package/dist/language-service/index.js +2 -1
  24. package/dist/language-service/index.js.map +1 -1
  25. package/dist/plugin/entry-supercompiler.d.ts +48 -0
  26. package/dist/plugin/entry-supercompiler.d.ts.map +1 -0
  27. package/dist/plugin/evaluator.d.ts.map +1 -1
  28. package/dist/plugin/index.d.ts.map +1 -1
  29. package/dist/plugin/index.js +1940 -385
  30. package/dist/plugin/index.js.map +3 -3
  31. package/dist/run/index.js +2 -1
  32. package/dist/run/index.js.map +1 -1
  33. package/dist/spec/index.js +28 -7
  34. package/dist/spec/index.js.map +1 -1
  35. package/dist/table/assemble.d.ts.map +1 -1
  36. package/dist/table/compile-rule-map.d.ts +6 -5
  37. package/dist/table/compile-rule-map.d.ts.map +1 -1
  38. package/dist/table/emit-assembly.d.ts +6 -1
  39. package/dist/table/emit-assembly.d.ts.map +1 -1
  40. package/dist/table/encode.d.ts.map +1 -1
  41. package/dist/table/index.js +1298 -231
  42. package/dist/table/index.js.map +3 -3
  43. package/dist/table/ops.d.ts +3 -2
  44. package/dist/table/ops.d.ts.map +1 -1
  45. package/dist/table/program.d.ts +15 -1
  46. package/dist/table/program.d.ts.map +1 -1
  47. package/dist/table/scalar-terminal.d.ts +30 -0
  48. package/dist/table/scalar-terminal.d.ts.map +1 -1
  49. package/dist/table/site-labels.d.ts +8 -0
  50. package/dist/table/site-labels.d.ts.map +1 -1
  51. package/dist/types.d.ts +2 -1
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/version.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/src/analysis/commitment.ts +19 -8
  56. package/src/analysis/rebuild.ts +1 -0
  57. package/src/combinators/trivia-skip.ts +2 -2
  58. package/src/compiler/build-arity.ts +50 -0
  59. package/src/compiler/degradation.ts +0 -6
  60. package/src/compiler/ir-serialize.ts +6 -4
  61. package/src/compiler/token-alphabet.ts +322 -28
  62. package/src/cst/capture-buffer.ts +34 -11
  63. package/src/plugin/entry-supercompiler.ts +567 -0
  64. package/src/plugin/evaluator.ts +10 -0
  65. package/src/plugin/index.ts +7 -3
  66. package/src/table/assemble.ts +125 -42
  67. package/src/table/compile-rule-map.ts +8 -7
  68. package/src/table/compile.ts +7 -8
  69. package/src/table/emit-assembly.ts +646 -126
  70. package/src/table/emit.ts +1 -1
  71. package/src/table/encode.ts +132 -7
  72. package/src/table/ops.ts +3 -2
  73. package/src/table/program.ts +44 -3
  74. package/src/table/scalar-terminal.ts +213 -1
  75. package/src/table/site-labels.ts +22 -9
  76. package/src/types.ts +1 -1
  77. package/src/version.ts +1 -1
@@ -2,7 +2,7 @@
2
2
  import * as fs2 from "node:fs";
3
3
  import * as path2 from "node:path";
4
4
  import { createUnplugin } from "unplugin";
5
- import { parseSync as parseSync4 } from "oxc-parser";
5
+ import { parseSync as parseSync5 } from "oxc-parser";
6
6
  import { ResolverFactory } from "oxc-resolver";
7
7
  import MagicString from "magic-string";
8
8
 
@@ -27,9 +27,9 @@ function classifyFinalChoice(arms, resolve3) {
27
27
  break;
28
28
  }
29
29
  let ownsHigh = false;
30
- for (const range of first.ranges) {
31
- if (range.hi >= 128) ownsHigh = true;
32
- for (let code = Math.max(0, range.lo); code <= Math.min(127, range.hi); code++) {
30
+ for (const range2 of first.ranges) {
31
+ if (range2.hi >= 128) ownsHigh = true;
32
+ for (let code = Math.max(0, range2.lo); code <= Math.min(127, range2.hi); code++) {
33
33
  if (ascii[code] !== 0) {
34
34
  exclusive = false;
35
35
  break;
@@ -551,10 +551,10 @@ function beginCstNodeCapture(ctx) {
551
551
  }
552
552
  function finishCstBuf(buf) {
553
553
  if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
554
- const children2 = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
555
- const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
554
+ const children3 = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
555
+ const rawChildren = buf.noRaw === true ? EMPTY : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
556
556
  const triviaLog = buf.tl ?? EMPTY_TL;
557
- return { children: children2, rawChildren, triviaLog };
557
+ return { children: children3, rawChildren, triviaLog };
558
558
  }
559
559
  function endCstNodeCapture(ctx, saved) {
560
560
  const materialized = finishCstBuf(ctx._cstBuf);
@@ -584,7 +584,8 @@ function pushCstChild(ctx, built, rawEntry2) {
584
584
  b.single = void 0;
585
585
  } else b.single = built;
586
586
  }
587
- if (b.raw) b.raw.push(rawEntry2);
587
+ if (b.noRaw === true) b.rawLen = (b.rawLen ?? 0) + 1;
588
+ else if (b.raw) b.raw.push(rawEntry2);
588
589
  else if (b.rawSingle !== void 0) {
589
590
  b.raw = [b.rawSingle, rawEntry2];
590
591
  b.rawSingle = void 0;
@@ -598,6 +599,7 @@ function pushCstChild(ctx, built, rawEntry2) {
598
599
  function cstRawLen(ctx) {
599
600
  const b = ctx._cstBuf;
600
601
  if (b) {
602
+ if (b.noRaw === true) return b.rawLen ?? 0;
601
603
  if (b.raw) return b.raw.length;
602
604
  return b.rawSingle !== void 0 ? 1 : 0;
603
605
  }
@@ -657,19 +659,37 @@ function rollbackCstCaptureAt(ctx, raw, tlog, leaves, fields, errors) {
657
659
  if (ctx._errors && errors !== void 0 && ctx._errors.length !== errors) ctx._errors.length = errors;
658
660
  const b = ctx._cstBuf;
659
661
  if (b) {
660
- rollbackBufList(b, "raw", "rawSingle", raw);
661
- rollbackBufList(b, "ch", "single", leaves);
662
+ if (b.noRaw === true) {
663
+ if (b.rawLen !== raw) b.rawLen = raw;
664
+ } else {
665
+ const rawList = b.raw;
666
+ if (rawList) {
667
+ if (raw === 0) b.raw = void 0;
668
+ else if (raw === 1) {
669
+ b.rawSingle = rawList[0];
670
+ b.raw = void 0;
671
+ } else if (rawList.length !== raw) rawList.length = raw;
672
+ } else if (raw === 0) b.rawSingle = void 0;
673
+ }
674
+ const childList = b.ch;
675
+ if (childList) {
676
+ if (leaves === 0) b.ch = void 0;
677
+ else if (leaves === 1) {
678
+ b.single = childList[0];
679
+ b.ch = void 0;
680
+ } else if (childList.length !== leaves) childList.length = leaves;
681
+ } else if (leaves === 0) b.single = void 0;
662
682
  if (b.tl) {
663
683
  if (tlog === 0) b.tl = void 0;
664
684
  else if (b.tl.length !== tlog) b.tl.length = tlog;
665
685
  }
666
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
686
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
667
687
  return;
668
688
  }
669
689
  if (ctx._cstRawChildren && ctx._cstRawChildren.length !== raw) ctx._cstRawChildren.length = raw;
670
690
  if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== tlog) ctx._cstTriviaLog.length = tlog;
671
691
  if (ctx._cstLeaves && ctx._cstLeaves.length !== leaves) ctx._cstLeaves.length = leaves;
672
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
692
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
673
693
  }
674
694
  function pushCstTriviaEntry(ctx, start, end, kindIndex) {
675
695
  const insertIdx = cstRawLen(ctx);
@@ -2158,15 +2178,22 @@ function canConsumeNewline(n) {
2158
2178
  return n.parts.some(canConsumeNewline);
2159
2179
  }
2160
2180
  }
2181
+ function regexCanMatchEmpty(source) {
2182
+ try {
2183
+ return nullable(parseRegex(source));
2184
+ } catch {
2185
+ return true;
2186
+ }
2187
+ }
2161
2188
  function firstSetFromRegex(source) {
2162
- let ast;
2189
+ let ast2;
2163
2190
  try {
2164
- ast = parseRegex(source);
2191
+ ast2 = parseRegex(source);
2165
2192
  } catch {
2166
2193
  return { firstSet: any(), canMatchNewline: true };
2167
2194
  }
2168
- if (nullable(ast)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast) };
2169
- return { firstSet: firstSet(ast), canMatchNewline: canConsumeNewline(ast) };
2195
+ if (nullable(ast2)) return { firstSet: any(), canMatchNewline: canConsumeNewline(ast2) };
2196
+ return { firstSet: firstSet(ast2), canMatchNewline: canConsumeNewline(ast2) };
2170
2197
  }
2171
2198
 
2172
2199
  // src/combinators/regex.ts
@@ -3789,21 +3816,21 @@ function when(key, parser2, opts = {}) {
3789
3816
  function otherwise(parser2) {
3790
3817
  return { kind: "otherwise", parser: parser2, usesRouted: parserUsesRouted(parser2) };
3791
3818
  }
3792
- function routed(fallback) {
3819
+ function routed(fallback2) {
3793
3820
  return {
3794
3821
  _tag: "routed",
3795
3822
  _meta: {
3796
3823
  // The routed token is whatever the selector matched, so the first set stays
3797
3824
  // `any` even with a fallback — `any` already subsumes the fallback's.
3798
3825
  firstSet: { kind: "any" },
3799
- canMatchNewline: fallback?._meta.canMatchNewline ?? false,
3826
+ canMatchNewline: fallback2?._meta.canMatchNewline ?? false,
3800
3827
  isTrivia: false
3801
3828
  },
3802
- _def: fallback === void 0 ? { tag: "routed" } : { tag: "routed", fallback },
3829
+ _def: fallback2 === void 0 ? { tag: "routed" } : { tag: "routed", fallback: fallback2 },
3803
3830
  parse(_input, pos, ctx) {
3804
3831
  const item = ctx._routed;
3805
3832
  if (item === void 0 || pos !== item.span.start) {
3806
- if (fallback !== void 0) return fallback.parse(_input, pos, ctx);
3833
+ if (fallback2 !== void 0) return fallback2.parse(_input, pos, ctx);
3807
3834
  return { ok: false, expected: ["routed()"], span: { start: pos, end: pos } };
3808
3835
  }
3809
3836
  if (cstCaptureActive(ctx)) {
@@ -3817,7 +3844,7 @@ function dispatch(selector, ...arms) {
3817
3844
  if (parserUsesRouted(selector)) {
3818
3845
  throw new Error("parseman: routed() can only appear inside a dispatch() branch");
3819
3846
  }
3820
- let fallback;
3847
+ let fallback2;
3821
3848
  let fallbackUsesRouted = false;
3822
3849
  const matchers = [];
3823
3850
  const cases = [];
@@ -3825,9 +3852,9 @@ function dispatch(selector, ...arms) {
3825
3852
  for (let i = 0; i < arms.length; i++) {
3826
3853
  const arm = arms[i];
3827
3854
  if (arm.kind === "otherwise") {
3828
- if (fallback !== void 0) throw new Error("parseman: dispatch() accepts at most one otherwise() arm");
3855
+ if (fallback2 !== void 0) throw new Error("parseman: dispatch() accepts at most one otherwise() arm");
3829
3856
  if (i !== arms.length - 1) throw new Error("parseman: otherwise() must be the last dispatch() arm");
3830
- fallback = arm.parser;
3857
+ fallback2 = arm.parser;
3831
3858
  fallbackUsesRouted = arm.usesRouted === true;
3832
3859
  continue;
3833
3860
  }
@@ -3860,7 +3887,7 @@ function dispatch(selector, ...arms) {
3860
3887
  }
3861
3888
  const meta = {
3862
3889
  firstSet: selector._meta.firstSet,
3863
- canMatchNewline: selector._meta.canMatchNewline || cases.some((entry) => entry.parser._meta.canMatchNewline) || matchers.some((entry) => entry.parser._meta.canMatchNewline) || (fallback?._meta.canMatchNewline ?? false),
3890
+ canMatchNewline: selector._meta.canMatchNewline || cases.some((entry) => entry.parser._meta.canMatchNewline) || matchers.some((entry) => entry.parser._meta.canMatchNewline) || (fallback2?._meta.canMatchNewline ?? false),
3864
3891
  isTrivia: false
3865
3892
  };
3866
3893
  const byKey = /* @__PURE__ */ new Map();
@@ -3879,7 +3906,7 @@ function dispatch(selector, ...arms) {
3879
3906
  selector,
3880
3907
  cases,
3881
3908
  ...matchers.length === 0 ? {} : { matchers },
3882
- ...fallback === void 0 ? {} : { otherwise: fallback, ...fallbackUsesRouted ? { otherwiseUsesRouted: true } : {} }
3909
+ ...fallback2 === void 0 ? {} : { otherwise: fallback2, ...fallbackUsesRouted ? { otherwiseUsesRouted: true } : {} }
3883
3910
  },
3884
3911
  parse(input, pos, ctx) {
3885
3912
  if (parserUsesRouted(selector)) {
@@ -3888,7 +3915,7 @@ function dispatch(selector, ...arms) {
3888
3915
  const selectorMark = saveTriviaMark(ctx);
3889
3916
  const selected = selector.parse(input, pos, ctx);
3890
3917
  if (!selected.ok) return selected;
3891
- const branch = byKey.get(selected.value) ?? (byFoldedKey.size === 0 ? void 0 : byFoldedKey.get(asciiFoldKey(selected.value))) ?? matchers.find((matcher) => matchesDispatchMatcher(selected.value, matcher)) ?? (fallback === void 0 ? void 0 : { keys: [], parser: fallback, caseInsensitive: false, usesRouted: fallbackUsesRouted });
3918
+ const branch = byKey.get(selected.value) ?? (byFoldedKey.size === 0 ? void 0 : byFoldedKey.get(asciiFoldKey(selected.value))) ?? matchers.find((matcher) => matchesDispatchMatcher(selected.value, matcher)) ?? (fallback2 === void 0 ? void 0 : { keys: [], parser: fallback2, caseInsensitive: false, usesRouted: fallbackUsesRouted });
3892
3919
  if (branch === void 0) {
3893
3920
  const expected = cases.flatMap((entry) => entry.keys.map((key) => JSON.stringify(key)));
3894
3921
  return { ok: false, expected, span: { start: selected.span.end, end: selected.span.end } };
@@ -4385,6 +4412,7 @@ var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
4385
4412
  var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
4386
4413
  var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
4387
4414
  var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
4415
+ var PARAM_NAME_RE = /^([A-Za-z_$][\w$]*)\s*\??\s*/;
4388
4416
  function confirmedBuildArity(src) {
4389
4417
  const s = src.trim();
4390
4418
  if (NATIVE_CODE_RE.test(s)) return null;
@@ -4400,6 +4428,34 @@ function confirmedBuildArity(src) {
4400
4428
  }
4401
4429
  return parts.length;
4402
4430
  }
4431
+ function confirmedBuildParamUnused(src, index) {
4432
+ if (!Number.isInteger(index) || index < 0) return false;
4433
+ const s = src.trim();
4434
+ if (NATIVE_CODE_RE.test(s) || /\b(?:arguments|eval|Function)\b/.test(s) || /\bwith\s*\(/.test(s)) return false;
4435
+ let names;
4436
+ const single = /^([A-Za-z_$][\w$]*)\s*=>/.exec(s);
4437
+ if (single) {
4438
+ names = [single[1]];
4439
+ } else {
4440
+ const inner = paramListText(s);
4441
+ if (inner === null || inner.trim() === "") return false;
4442
+ const parts = splitTopLevel(inner);
4443
+ if (parts === null) return false;
4444
+ names = [];
4445
+ for (const part of parts) {
4446
+ const trimmed = part.trim();
4447
+ if (!isConfirmableParam(trimmed)) return false;
4448
+ const name2 = PARAM_NAME_RE.exec(trimmed)?.[1];
4449
+ if (name2 === void 0) return false;
4450
+ names.push(name2);
4451
+ }
4452
+ }
4453
+ const name = names[index];
4454
+ if (name === void 0) return false;
4455
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4456
+ const uses = s.match(new RegExp(`(^|[^A-Za-z0-9_$])${escaped}(?=$|[^A-Za-z0-9_$])`, "g"));
4457
+ return uses?.length === 1;
4458
+ }
4403
4459
  function paramListText(s) {
4404
4460
  const open = PARAM_LIST_OPEN_RE.exec(s);
4405
4461
  if (!open) return null;
@@ -4537,6 +4593,7 @@ function confirmedArityForDef(def) {
4537
4593
  }
4538
4594
  function buildReadsRaw(def) {
4539
4595
  if (!def.build) return true;
4596
+ if (def.buildRawUnused === true) return false;
4540
4597
  const arity = confirmedArityForDef(def);
4541
4598
  if (arity === null) return true;
4542
4599
  return arity >= 4;
@@ -4647,11 +4704,11 @@ function normalizeProject(project) {
4647
4704
  }
4648
4705
  return project;
4649
4706
  }
4650
- function projectChild(children2, project, type) {
4651
- if (!(project in children2)) {
4707
+ function projectChild(children3, project, type) {
4708
+ if (!(project in children3)) {
4652
4709
  throw new Error(`node(${JSON.stringify(type)}) project child ${project} was not captured`);
4653
4710
  }
4654
- return unwrapChild(children2[project]);
4711
+ return unwrapChild(children3[project]);
4655
4712
  }
4656
4713
  function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
4657
4714
  const hasExplicitType = typeof typeOrCombinator === "string";
@@ -4723,14 +4780,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
4723
4780
  const fields = effFields ? buildFieldMap(ctx._fields) : void 0;
4724
4781
  ctx._fields = savedFields;
4725
4782
  ctx._triviaCaptureMask = savedMask;
4726
- const { children: children2, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
4783
+ const { children: children3, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
4727
4784
  if (!r.ok) return r;
4728
4785
  const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
4729
4786
  const nodeType = def.type ?? missingInferredType();
4730
4787
  const cstOutput = cstOutputHost(ctx.build);
4731
4788
  const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
4732
4789
  const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
4733
- const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children2, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : build(children2, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
4790
+ const built = unwrap && children3.length === 1 ? unwrapChild(children3[0]) : collapse && children3.length === 1 ? children3[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children3.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children3[0], children3, rawChildren) ? children3[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children3, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, hostState, tags) : build(children3, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children3, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children3 };
4734
4791
  const rawEntry2 = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
4735
4792
  if (saved.buf !== void 0 || saved.ch !== void 0) {
4736
4793
  pushCstChild(ctx, built, rawEntry2);
@@ -4957,6 +5014,399 @@ function firstSetToString(fs3) {
4957
5014
  return fs3.ranges.map((r) => r.lo === r.hi ? ch(r.lo) : `${ch(r.lo)}-${ch(r.hi)}`).join(",");
4958
5015
  }
4959
5016
 
5017
+ // src/analysis/commitment.ts
5018
+ function mayFail(p, seen = /* @__PURE__ */ new Set()) {
5019
+ if (seen.has(p)) return true;
5020
+ seen.add(p);
5021
+ const d = p._def;
5022
+ switch (d.tag) {
5023
+ case "literal":
5024
+ return d.value.length > 0;
5025
+ case "trivia":
5026
+ return false;
5027
+ // `optional`/`many`/a min-0 `sepBy` swallow an ORDINARY failure — zero
5028
+ // repetitions is a match. They do NOT swallow a COMMITTED one: a dispatch
5029
+ // that has selected an arm and then failed inside it breaks out past every
5030
+ // enclosing repeat, straight to the fallible boundary. So these are total
5031
+ // exactly when their body cannot commit. (Measured: treating them as
5032
+ // unconditionally total left an extra zero-width leaf in
5033
+ // `BareInterpolatedSelector` on benchmark.less — a rollback the legacy
5034
+ // build fired and this one had deleted.)
5035
+ case "optional":
5036
+ case "many":
5037
+ return mayCommitFailure(d.parser);
5038
+ case "sepBy":
5039
+ return d.min >= 1 ? mayFail(d.parser, seen) : mayCommitFailure(d.parser) || mayCommitFailure(d.separator);
5040
+ case "oneOrMore":
5041
+ return mayFail(d.parser, seen);
5042
+ case "sequence":
5043
+ return d.parsers.some((x) => mayFail(x, seen));
5044
+ // Delegating wrappers: as fallible as what they wrap.
5045
+ case "node":
5046
+ case "transform":
5047
+ case "label":
5048
+ case "field":
5049
+ case "expect":
5050
+ case "withCtx":
5051
+ case "grammar":
5052
+ case "token":
5053
+ case "leaf":
5054
+ return mayFail(d.parser, seen);
5055
+ case "lazy": {
5056
+ try {
5057
+ return mayFail(d.thunk(), seen);
5058
+ } catch {
5059
+ return true;
5060
+ }
5061
+ }
5062
+ // An adjacency assertion is a TEST — failing is its whole job.
5063
+ case "adjacency":
5064
+ return true;
5065
+ default:
5066
+ return true;
5067
+ }
5068
+ }
5069
+ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
5070
+ if (seen.has(p)) return false;
5071
+ seen.add(p);
5072
+ const d = p._def;
5073
+ switch (d.tag) {
5074
+ // Atomic / non-capturing-then-failing: a failure happens before any push.
5075
+ case "literal":
5076
+ case "regex":
5077
+ case "keywords":
5078
+ case "guard":
5079
+ // Adjacency probes with `_cap = 0` / no `commit()`: it cannot push anything.
5080
+ case "adjacency":
5081
+ case "not":
5082
+ // peek(): emitted under a non-capturing probe ctx and zero-width on both
5083
+ // outcomes, so it can never leave a partial capture behind.
5084
+ case "peek":
5085
+ case "trivia":
5086
+ case "token":
5087
+ case "leaf":
5088
+ case "scanTo":
5089
+ case "unknown":
5090
+ return false;
5091
+ // node() captures into its own private buffers and rolls them back on
5092
+ // failure (emitNode restores _ctx.* and never pushes on the !ok path).
5093
+ case "node":
5094
+ return false;
5095
+ // choice/firstMatch already roll back each failed arm; on overall failure
5096
+ // nothing committed remains.
5097
+ case "choice":
5098
+ return false;
5099
+ case "dispatch":
5100
+ return capturesLeaf(d.selector, new Set(seen)) || d.cases.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) || (d.matchers ? d.matchers.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) : false) || (d.otherwise ? mayLeavePartialCapture(d.otherwise, new Set(seen), triviaActive) || capturesLeaf(d.otherwise, new Set(seen)) : false);
5101
+ case "attempt":
5102
+ return false;
5103
+ // optional never fails; many/oneOrMore only "fail" with zero captured items.
5104
+ case "optional":
5105
+ case "many":
5106
+ case "oneOrMore":
5107
+ return false;
5108
+ // sepBy emits its own per-iteration rollback in emitSepBy.
5109
+ case "sepBy":
5110
+ return false;
5111
+ // A sequence is the real case: an earlier capturing term followed by a term
5112
+ // that can fail leaves the earlier captures buffered.
5113
+ //
5114
+ // BOTH halves of that sentence are load-bearing, and the second half is what
5115
+ // this walk exists to exploit. "Some earlier term captures" alone was the old
5116
+ // test, and it is true of very nearly every sequence in a real grammar — a
5117
+ // sequence almost always opens with a literal or a node. The rollback is only
5118
+ // reachable if something AFTER the capture can still fail; once the remainder
5119
+ // is total (`optional`/`many`/trivia/a min-0 `sepBy`), the sequence has no
5120
+ // failure path left to roll back from, and the save+restore is dead code.
5121
+ //
5122
+ // `captured` tracks whether anything is in the buffers yet as the scan moves
5123
+ // left to right. Two things put it there:
5124
+ // - a term that captures (`capturesLeaf`/`hasNodeDef`), and
5125
+ // - the inter-term TRIVIA scan, which under `capturing` pushes into
5126
+ // `_cstRawChildren`/`_cstTriviaLog` BEFORE the term at each boundary
5127
+ // i >= 1. `emitSeqValues` only rewinds that push on the term's SUCCESS
5128
+ // path (the "matched empty, so leave the whitespace out of the span"
5129
+ // branch); a term that FAILS breaks straight out with the trivia still
5130
+ // buffered, so from boundary 1 onward the buffers are dirty regardless of
5131
+ // what the earlier terms did.
5132
+ // Each term is also asked about itself: a nested sequence can leave its own
5133
+ // partial capture behind, and its terms are emitted inline into this same
5134
+ // block with no boundary of their own to roll them back.
5135
+ case "sequence": {
5136
+ const parts = d.parsers;
5137
+ let captured = false;
5138
+ for (let i = 0; i < parts.length; i++) {
5139
+ const part = parts[i];
5140
+ if (i > 0 && triviaActive) captured = true;
5141
+ if (captured && mayFail(part)) return true;
5142
+ if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
5143
+ if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
5144
+ }
5145
+ return false;
5146
+ }
5147
+ // Delegating wrappers: defer to the wrapped parser.
5148
+ case "transform":
5149
+ case "label":
5150
+ case "field":
5151
+ case "expect":
5152
+ case "withCtx":
5153
+ case "grammar":
5154
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
5155
+ case "recover":
5156
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
5157
+ case "lazy": {
5158
+ try {
5159
+ return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
5160
+ } catch {
5161
+ return true;
5162
+ }
5163
+ }
5164
+ // Unknown shapes: be safe and keep the rollback.
5165
+ default:
5166
+ return true;
5167
+ }
5168
+ }
5169
+ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
5170
+ if (seen.has(p)) return false;
5171
+ seen.add(p);
5172
+ const d = p._def;
5173
+ switch (d.tag) {
5174
+ case "literal":
5175
+ case "regex":
5176
+ case "keywords":
5177
+ case "node":
5178
+ case "token":
5179
+ case "routed":
5180
+ case "leaf":
5181
+ return true;
5182
+ case "not":
5183
+ case "peek":
5184
+ case "guard":
5185
+ case "adjacency":
5186
+ case "trivia":
5187
+ case "unknown":
5188
+ return false;
5189
+ case "sequence":
5190
+ case "choice":
5191
+ return d.parsers.some((x) => capturesLeaf(x, seen));
5192
+ case "dispatch":
5193
+ return capturesLeaf(d.selector, seen) || d.cases.some((x) => capturesLeaf(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => capturesLeaf(entry.parser, seen)) : false) || (d.otherwise ? capturesLeaf(d.otherwise, seen) : false);
5194
+ case "sepBy":
5195
+ return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
5196
+ case "many":
5197
+ case "oneOrMore":
5198
+ case "optional":
5199
+ case "attempt":
5200
+ case "transform":
5201
+ case "label":
5202
+ case "field":
5203
+ case "expect":
5204
+ case "withCtx":
5205
+ case "grammar":
5206
+ case "recover":
5207
+ return capturesLeaf(d.parser, seen);
5208
+ case "scanTo":
5209
+ return true;
5210
+ case "lazy": {
5211
+ try {
5212
+ return capturesLeaf(d.thunk(), seen);
5213
+ } catch {
5214
+ return true;
5215
+ }
5216
+ }
5217
+ default:
5218
+ return true;
5219
+ }
5220
+ }
5221
+ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
5222
+ if (seen.has(p)) return false;
5223
+ seen.add(p);
5224
+ const d = p._def;
5225
+ switch (d.tag) {
5226
+ case "node":
5227
+ return true;
5228
+ case "lazy": {
5229
+ try {
5230
+ return hasNodeDef(d.thunk(), seen);
5231
+ } catch {
5232
+ return false;
5233
+ }
5234
+ }
5235
+ case "grammar":
5236
+ case "trivia":
5237
+ case "token":
5238
+ case "leaf":
5239
+ case "label":
5240
+ case "field":
5241
+ case "optional":
5242
+ case "many":
5243
+ case "oneOrMore":
5244
+ case "not":
5245
+ case "peek":
5246
+ case "transform":
5247
+ return hasNodeDef(d.parser, seen);
5248
+ case "sequence":
5249
+ case "choice":
5250
+ return d.parsers.some((x) => hasNodeDef(x, seen));
5251
+ case "dispatch":
5252
+ return hasNodeDef(d.selector, seen) || d.cases.some((x) => hasNodeDef(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => hasNodeDef(entry.parser, seen)) : false) || (d.otherwise ? hasNodeDef(d.otherwise, seen) : false);
5253
+ case "sepBy":
5254
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
5255
+ case "scanTo":
5256
+ return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
5257
+ case "recover":
5258
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
5259
+ case "expect":
5260
+ return hasNodeDef(d.parser, seen);
5261
+ case "withCtx":
5262
+ return hasNodeDef(d.parser, seen);
5263
+ default:
5264
+ return false;
5265
+ }
5266
+ }
5267
+ function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
5268
+ if (seen.has(p)) return false;
5269
+ seen.add(p);
5270
+ const d = p._def;
5271
+ switch (d.tag) {
5272
+ case "node":
5273
+ return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
5274
+ case "lazy": {
5275
+ try {
5276
+ return hasDirectBuildDef(d.thunk(), seen);
5277
+ } catch {
5278
+ return false;
5279
+ }
5280
+ }
5281
+ case "grammar":
5282
+ case "trivia":
5283
+ case "token":
5284
+ case "leaf":
5285
+ case "label":
5286
+ case "field":
5287
+ case "optional":
5288
+ case "many":
5289
+ case "oneOrMore":
5290
+ case "attempt":
5291
+ case "not":
5292
+ case "peek":
5293
+ case "withCtx":
5294
+ case "expect":
5295
+ case "transform":
5296
+ return hasDirectBuildDef(d.parser, seen);
5297
+ case "sequence":
5298
+ case "choice":
5299
+ return d.parsers.some((x) => hasDirectBuildDef(x, seen));
5300
+ case "dispatch":
5301
+ return hasDirectBuildDef(d.selector, seen) || d.cases.some((x) => hasDirectBuildDef(x.parser, seen)) || (d.matchers ? d.matchers.some((x) => hasDirectBuildDef(x.parser, seen)) : false) || (d.otherwise ? hasDirectBuildDef(d.otherwise, seen) : false);
5302
+ case "sepBy":
5303
+ return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
5304
+ case "scanTo":
5305
+ return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen));
5306
+ case "recover":
5307
+ return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
5308
+ case "routed":
5309
+ return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
5310
+ default:
5311
+ return false;
5312
+ }
5313
+ }
5314
+ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve3) {
5315
+ if (seen.has(p)) return false;
5316
+ seen.add(p);
5317
+ const d = p._def;
5318
+ switch (d.tag) {
5319
+ case "dispatch":
5320
+ return true;
5321
+ case "choice":
5322
+ case "sequence":
5323
+ return d.parsers.some((x) => mayCommitFailure(x, seen, resolve3));
5324
+ case "many":
5325
+ case "oneOrMore":
5326
+ case "optional":
5327
+ case "attempt":
5328
+ case "transform":
5329
+ case "label":
5330
+ case "field":
5331
+ case "grammar":
5332
+ case "node":
5333
+ return mayCommitFailure(d.parser, seen, resolve3);
5334
+ case "sepBy":
5335
+ return mayCommitFailure(d.parser, seen, resolve3) || mayCommitFailure(d.separator, seen, resolve3);
5336
+ case "token":
5337
+ case "leaf":
5338
+ return mayCommitFailure(d.parser, seen, resolve3);
5339
+ case "withCtx":
5340
+ return mayCommitFailure(d.parser, seen, resolve3);
5341
+ case "scanTo":
5342
+ return mayCommitFailure(d.sentinel, seen, resolve3) || d.skip.some((x) => mayCommitFailure(x, seen, resolve3));
5343
+ case "lazy": {
5344
+ try {
5345
+ return mayCommitFailure(d.thunk(), seen, resolve3);
5346
+ } catch {
5347
+ const name = p._ruleName;
5348
+ const target = name === void 0 ? void 0 : resolve3?.(name);
5349
+ return target === void 0 ? true : mayCommitFailure(target, seen, resolve3);
5350
+ }
5351
+ }
5352
+ case "unknown":
5353
+ return true;
5354
+ default:
5355
+ return false;
5356
+ }
5357
+ }
5358
+ function hasSemanticReduction(roots, externalRefs) {
5359
+ const seen = /* @__PURE__ */ new Set();
5360
+ const visit = (parser2) => {
5361
+ if (seen.has(parser2)) return false;
5362
+ seen.add(parser2);
5363
+ const def = parser2._def;
5364
+ if (def.tag === "transform" && !def.recognitionOnly) return true;
5365
+ if (def.tag === "choice" && def.gates.some(Boolean)) return true;
5366
+ if (def.tag === "guard" || def.tag === "withCtx") return true;
5367
+ if (def.tag === "node" && def.build !== void 0) return true;
5368
+ if (def.tag === "lazy") {
5369
+ if (externalRefs?.has(parser2)) return false;
5370
+ try {
5371
+ return visit(def.thunk());
5372
+ } catch {
5373
+ return true;
5374
+ }
5375
+ }
5376
+ return childrenOf2(def).some(visit);
5377
+ };
5378
+ return roots.some(visit);
5379
+ }
5380
+ function classifyRuleMap(ruleMap) {
5381
+ const externalRefs = /* @__PURE__ */ new Set();
5382
+ const scanned = /* @__PURE__ */ new Set();
5383
+ const scanExternal = (p) => {
5384
+ if (scanned.has(p)) return;
5385
+ scanned.add(p);
5386
+ const def = p._def;
5387
+ if (def.tag === "lazy") {
5388
+ let resolved;
5389
+ try {
5390
+ resolved = def.thunk();
5391
+ } catch {
5392
+ resolved = void 0;
5393
+ }
5394
+ if (resolved === void 0) {
5395
+ if (p._ruleName) externalRefs.add(p);
5396
+ return;
5397
+ }
5398
+ scanExternal(resolved);
5399
+ return;
5400
+ }
5401
+ for (const child of childrenOf2(def)) scanExternal(child);
5402
+ };
5403
+ for (const [, rule] of ruleMap) scanExternal(rule);
5404
+ return {
5405
+ hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
5406
+ isRecognitionOnly: !hasSemanticReduction(ruleMap.map(([, rule]) => rule), externalRefs)
5407
+ };
5408
+ }
5409
+
4960
5410
  // src/table/ops.ts
4961
5411
  var OP_LIT = 1;
4962
5412
  var OP_RX = 2;
@@ -5273,11 +5723,11 @@ function fixedTreeRunner(words, matchers, classes, expected) {
5273
5723
  }
5274
5724
  if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
5275
5725
  const count = op - LEX_NODE_SEQUENCE2 + 2;
5276
- const nodes = Array.from({ length: count }, pop).reverse();
5277
- if (count === 2) stack.push(sequence2(nodes[0], nodes[1]));
5278
- else if (count === 3) stack.push(sequence3(nodes[0], nodes[1], nodes[2]));
5279
- else if (count === 4) stack.push(sequence4(nodes[0], nodes[1], nodes[2], nodes[3]));
5280
- else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
5726
+ const nodes2 = Array.from({ length: count }, pop).reverse();
5727
+ if (count === 2) stack.push(sequence2(nodes2[0], nodes2[1]));
5728
+ else if (count === 3) stack.push(sequence3(nodes2[0], nodes2[1], nodes2[2]));
5729
+ else if (count === 4) stack.push(sequence4(nodes2[0], nodes2[1], nodes2[2], nodes2[3]));
5730
+ else stack.push(sequence5(nodes2[0], nodes2[1], nodes2[2], nodes2[3], nodes2[4]));
5281
5731
  continue;
5282
5732
  }
5283
5733
  if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
@@ -5512,8 +5962,26 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
5512
5962
  }
5513
5963
  }
5514
5964
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
5515
- function ownTableProgram(prog, resolved) {
5516
- return { ...prog, [TABLE_RUNTIME]: { resolved } };
5965
+ function ownTableProgram(prog, resolved, caches = {}) {
5966
+ const runtime = prog[TABLE_RUNTIME];
5967
+ return {
5968
+ ...prog,
5969
+ [TABLE_RUNTIME]: {
5970
+ resolved,
5971
+ choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
5972
+ nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
5973
+ failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
5974
+ }
5975
+ };
5976
+ }
5977
+ function choiceRollbackMask(prog, ip) {
5978
+ return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
5979
+ }
5980
+ function choiceCannotCommit(prog, ip) {
5981
+ return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
5982
+ }
5983
+ function failureRollbackClean(prog, ip) {
5984
+ return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
5517
5985
  }
5518
5986
  var WIDE_CLASS_PREFIX_LO = 65535;
5519
5987
  var WIDE_CLASS_PREFIX_HI = 0;
@@ -5529,22 +5997,22 @@ function validateClassRange(lo, hi) {
5529
5997
  }
5530
5998
  function encodeClassSpec(ranges) {
5531
5999
  let wide = false;
5532
- for (const range of ranges) {
5533
- validateClassRange(range.lo, range.hi);
5534
- if (range.hi > 65535) wide = true;
6000
+ for (const range2 of ranges) {
6001
+ validateClassRange(range2.lo, range2.hi);
6002
+ if (range2.hi > 65535) wide = true;
5535
6003
  }
5536
6004
  if (!wide) {
5537
6005
  let spec2 = "";
5538
- for (const range of ranges) spec2 += String.fromCharCode(range.lo, range.hi);
6006
+ for (const range2 of ranges) spec2 += String.fromCharCode(range2.lo, range2.hi);
5539
6007
  return spec2;
5540
6008
  }
5541
6009
  let spec = String.fromCharCode(WIDE_CLASS_PREFIX_LO, WIDE_CLASS_PREFIX_HI);
5542
- for (const range of ranges) {
6010
+ for (const range2 of ranges) {
5543
6011
  spec += String.fromCharCode(
5544
- range.lo >>> 16,
5545
- range.lo & 65535,
5546
- range.hi >>> 16,
5547
- range.hi & 65535
6012
+ range2.lo >>> 16,
6013
+ range2.lo & 65535,
6014
+ range2.hi >>> 16,
6015
+ range2.hi & 65535
5548
6016
  );
5549
6017
  }
5550
6018
  return spec;
@@ -5688,7 +6156,6 @@ function directArrayProjection(fn, fnSrc, arity) {
5688
6156
 
5689
6157
  // src/table/encode.ts
5690
6158
  import {
5691
- assertLexicalCapabilityClosure,
5692
6159
  collectLexicalCapabilities,
5693
6160
  winnerWrapsReference as winnerWrapsReference2
5694
6161
  } from "../compiler/token-capability.js";
@@ -6070,6 +6537,9 @@ var Encoder = class {
6070
6537
  lexIndex = /* @__PURE__ */ new Map();
6071
6538
  lexPrograms = [];
6072
6539
  lexProgramIndex = /* @__PURE__ */ new Map();
6540
+ choiceRollbackMasks = /* @__PURE__ */ new Map();
6541
+ nonCommittingChoiceSites = /* @__PURE__ */ new Set();
6542
+ failureRollbackCleanSites = /* @__PURE__ */ new Set();
6073
6543
  labels = void 0;
6074
6544
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
6075
6545
  activeTrivia = void 0;
@@ -6480,6 +6950,71 @@ var Encoder = class {
6480
6950
  const w = this.winners;
6481
6951
  return w === void 0 ? void 0 : (name) => w[name];
6482
6952
  }
6953
+ /**
6954
+ * Whether a failed ordered-choice arm can leave state that the enclosing
6955
+ * choice must restore before trying its successor.
6956
+ *
6957
+ * `mayLeavePartialCapture` is the existing sound CST/trivia proof. The extra
6958
+ * writer census covers the side sinks that proof deliberately does not model:
6959
+ * fields, recovered errors, and interpreted scanners. Strict assemblies do
6960
+ * not run repeat recovery, but these rows can still publish through a caller's
6961
+ * context. Cycles are safe to stop: revisiting the same combinator cannot
6962
+ * discover a writer the first traversal did not already reach.
6963
+ */
6964
+ failureNeedsRollback(p, autoNot) {
6965
+ const refName = p._ruleName;
6966
+ const winner = refName === void 0 ? void 0 : this.winners?.[refName];
6967
+ const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
6968
+ const sideWriterMemo = /* @__PURE__ */ new Map();
6969
+ const hasSideWriter = (current, seen = /* @__PURE__ */ new Set()) => {
6970
+ const cached = sideWriterMemo.get(current);
6971
+ if (cached !== void 0) return { found: cached, complete: true };
6972
+ if (seen.has(current)) return { found: false, complete: false };
6973
+ const next = new Set(seen);
6974
+ next.add(current);
6975
+ const def = current._def;
6976
+ let result;
6977
+ switch (def.tag) {
6978
+ case "field":
6979
+ case "expect":
6980
+ case "recover":
6981
+ case "scanTo":
6982
+ case "unknown":
6983
+ result = { found: true, complete: true };
6984
+ break;
6985
+ case "lazy": {
6986
+ const name = current._ruleName;
6987
+ const resolvedWinner = name === void 0 ? void 0 : this.winners?.[name];
6988
+ if (resolvedWinner !== void 0 && !winnerWrapsReference2(resolvedWinner, current)) {
6989
+ result = hasSideWriter(resolvedWinner, next);
6990
+ break;
6991
+ }
6992
+ try {
6993
+ result = hasSideWriter(def.thunk(), next);
6994
+ } catch {
6995
+ result = { found: true, complete: true };
6996
+ }
6997
+ break;
6998
+ }
6999
+ default: {
7000
+ let complete = true;
7001
+ result = { found: false, complete: true };
7002
+ for (const child of childrenOf2(def)) {
7003
+ const childResult = hasSideWriter(child, next);
7004
+ if (childResult.found) {
7005
+ result = { found: true, complete: true };
7006
+ break;
7007
+ }
7008
+ complete &&= childResult.complete;
7009
+ }
7010
+ if (!result.found) result = { found: false, complete };
7011
+ }
7012
+ }
7013
+ if (result.found || result.complete) sideWriterMemo.set(current, result.found);
7014
+ return result;
7015
+ };
7016
+ return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || hasSideWriter(root).found || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
7017
+ }
6483
7018
  /** A first set becomes a char class string, or −1 for `any`. */
6484
7019
  charClass(fs3) {
6485
7020
  if (fs3.kind !== "ranges" || fs3.ranges.length === 0) return -1;
@@ -6765,9 +7300,39 @@ var Encoder = class {
6765
7300
  });
6766
7301
  const rr = this.refResolver();
6767
7302
  const finalChoice = classifyFinalChoice(arms, rr);
6768
- const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
7303
+ const transactionalFirst = arms.map((arm, i) => {
7304
+ if (!finalChoice.nullable[i]) return void 0;
7305
+ const def = arm._def;
7306
+ if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
7307
+ return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr);
7308
+ });
7309
+ const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
7310
+ const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
7311
+ if (transactionalFirst.some((first) => first !== void 0) && classes.every((cls) => cls >= 0)) {
7312
+ let overlap = false;
7313
+ for (let i = 0; i < gateFirst.length && !overlap; i++) {
7314
+ for (let j = i + 1; j < gateFirst.length; j++) {
7315
+ if (intersects(gateFirst[i], gateFirst[j])) {
7316
+ overlap = true;
7317
+ break;
7318
+ }
7319
+ }
7320
+ }
7321
+ if (!overlap) for (let i = 0; i < classes.length; i++) {
7322
+ if (transactionalFirst[i] !== void 0) classes[i] = -1;
7323
+ }
7324
+ }
6769
7325
  const dispIdx = this.disp.length;
6770
7326
  this.disp.push(classes);
7327
+ let rollbackMask = kids.length > 31 ? -1 : 0;
7328
+ if (rollbackMask === 0) {
7329
+ for (let i = 0; i < arms.length; i++) {
7330
+ const src = order[i];
7331
+ if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
7332
+ rollbackMask |= 1 << i;
7333
+ }
7334
+ }
7335
+ }
6771
7336
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
6772
7337
  this.code[head + 1] = dispIdx;
6773
7338
  this.code[head + 2] = kids.length;
@@ -6776,6 +7341,10 @@ var Encoder = class {
6776
7341
  this.code[head + 4 + i] = kids[i];
6777
7342
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
6778
7343
  }
7344
+ this.choiceRollbackMasks.set(head, rollbackMask);
7345
+ if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
7346
+ this.nonCommittingChoiceSites.add(head);
7347
+ }
6779
7348
  return head;
6780
7349
  }
6781
7350
  case "many":
@@ -6805,8 +7374,11 @@ var Encoder = class {
6805
7374
  }
6806
7375
  return d.min >= 2 ? this.emit(OP_REP, child, d.min, d.max ?? -1, sep2, flags, this.expected(deriveExpected(d.parser))) : this.emit(OP_REP, child, d.min, d.max ?? -1, sep2, flags);
6807
7376
  }
6808
- case "optional":
6809
- return this.emit(OP_OPT, this.node(d.parser).ip);
7377
+ case "optional": {
7378
+ const head = this.emit(OP_OPT, this.node(d.parser).ip);
7379
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
7380
+ return head;
7381
+ }
6810
7382
  case "transform": {
6811
7383
  const inner = d.parser._def;
6812
7384
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
@@ -6965,6 +7537,7 @@ var Encoder = class {
6965
7537
  // lowering was correct only for a choice arm.
6966
7538
  case "attempt": {
6967
7539
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
7540
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
6968
7541
  const fs3 = d.parser._meta.firstSet;
6969
7542
  if (fs3.kind === "any" || matchesEmpty(d.parser)) return inner;
6970
7543
  const cls = this.charClass(fs3);
@@ -7133,6 +7706,10 @@ var Encoder = class {
7133
7706
  ...this.rec ? { rec: 1 } : {},
7134
7707
  ...this.cov === void 0 ? {} : { cov: this.cov },
7135
7708
  lines: this.track ? 1 : 0
7709
+ }, void 0, {
7710
+ choiceRollbackMasks: this.choiceRollbackMasks,
7711
+ failureRollbackCleanSites: this.failureRollbackCleanSites,
7712
+ nonCommittingChoiceSites: this.nonCommittingChoiceSites
7136
7713
  });
7137
7714
  }
7138
7715
  };
@@ -7177,7 +7754,6 @@ function encodeTableProgram(ruleMap, settings = {}) {
7177
7754
  const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
7178
7755
  const resolveLexical = (name) => ruleMap[name];
7179
7756
  const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
7180
- assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
7181
7757
  const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
7182
7758
  enc.winners = ruleMap;
7183
7759
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
@@ -8310,13 +8886,17 @@ var TRI_NONE = -1;
8310
8886
  var CAP_UNKNOWN = 0;
8311
8887
  var CAP_OFF = 1;
8312
8888
  var CAP_ON = 2;
8313
- var TOP = { tri: TRI_UNKNOWN, buf: false, cap: CAP_UNKNOWN };
8889
+ var RAW_UNKNOWN = 0;
8890
+ var RAW_CAPTURE = 1;
8891
+ var RAW_OMIT = 2;
8892
+ var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
8314
8893
  function meet(a, b) {
8315
8894
  const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
8316
8895
  const buf = a.buf && b.buf;
8896
+ const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
8317
8897
  const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
8318
- if (tri === a.tri && buf === a.buf && cap === a.cap) return a;
8319
- return { tri, buf, cap };
8898
+ if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
8899
+ return { tri, buf, raw, cap };
8320
8900
  }
8321
8901
  function reachableSites(code, roots) {
8322
8902
  const seen = /* @__PURE__ */ new Set();
@@ -8339,25 +8919,26 @@ function transfer(code, ip, at, hostCst) {
8339
8919
  const tri = ki < 0 ? TRI_NONE : ki;
8340
8920
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
8341
8921
  if (tri === at.tri && cap === at.cap) return at;
8342
- return { tri, buf: at.buf, cap };
8922
+ return { tri, buf: at.buf, raw: at.raw, cap };
8343
8923
  }
8344
8924
  if (op === OP_NODE || op === OP_NODE_TRACK) {
8345
8925
  const flags = code[ip + 3];
8346
8926
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
8347
8927
  if (directChildren) {
8348
- return { tri: at.tri, buf: false, cap: CAP_OFF };
8928
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
8349
8929
  }
8350
8930
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
8351
- if (at.buf && cap === at.cap) return at;
8352
- return { tri: at.tri, buf: true, cap };
8931
+ const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
8932
+ if (at.buf && raw === at.raw && cap === at.cap) return at;
8933
+ return { tri: at.tri, buf: true, raw, cap };
8353
8934
  }
8354
8935
  if (op === OP_TOKEN) {
8355
8936
  if (at.tri === TRI_NONE && !at.buf) return at;
8356
- return { tri: TRI_NONE, buf: false, cap: at.cap };
8937
+ return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
8357
8938
  }
8358
8939
  if (op === OP_LEAF) {
8359
8940
  if (!at.buf) return at;
8360
- return { tri: at.tri, buf: false, cap: at.cap };
8941
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
8361
8942
  }
8362
8943
  return at;
8363
8944
  }
@@ -8424,6 +9005,162 @@ function scalarTerminalNotChild(code, ip) {
8424
9005
  const op = code[child];
8425
9006
  return op === OP_RX || op === OP_LIT ? child : -1;
8426
9007
  }
9008
+ function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
9009
+ const seen = /* @__PURE__ */ new Set();
9010
+ let at = ip;
9011
+ let depth = 0;
9012
+ while (!seen.has(at)) {
9013
+ seen.add(at);
9014
+ const op = code[at];
9015
+ if (op === OP_LIT || op === OP_RX) return depth >= minDepth ? at : -1;
9016
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || throughAttempt && op === OP_ATTEMPT) {
9017
+ at = code[at + 1];
9018
+ depth++;
9019
+ continue;
9020
+ }
9021
+ if (throughPeek && op === OP_PEEK) {
9022
+ at = code[at + 1];
9023
+ depth++;
9024
+ continue;
9025
+ }
9026
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9027
+ at = code[at + 2];
9028
+ depth++;
9029
+ continue;
9030
+ }
9031
+ if (op === OP_SEQ || op === OP_SEQV) {
9032
+ if (code[at + 1] < 1) return -1;
9033
+ at = code[at + 2];
9034
+ depth++;
9035
+ continue;
9036
+ }
9037
+ if (op === OP_SEQX) {
9038
+ if (code[at + 2] < 1) return -1;
9039
+ at = code[at + 3];
9040
+ depth++;
9041
+ continue;
9042
+ }
9043
+ return -1;
9044
+ }
9045
+ return -1;
9046
+ }
9047
+ function leadingScalarSequence(code, ip) {
9048
+ const wholeScalar = (start) => {
9049
+ const seen2 = /* @__PURE__ */ new Set();
9050
+ let at2 = start;
9051
+ while (!seen2.has(at2)) {
9052
+ seen2.add(at2);
9053
+ const op = code[at2];
9054
+ if (op === OP_LIT || op === OP_RX) return at2;
9055
+ if (op === OP_RULE || op === OP_TOKEN || op === OP_ATTEMPT) {
9056
+ at2 = code[at2 + 1];
9057
+ continue;
9058
+ }
9059
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9060
+ at2 = code[at2 + 2];
9061
+ continue;
9062
+ }
9063
+ if (op === OP_SEQ || op === OP_SEQV) {
9064
+ if (code[at2 + 1] !== 1) return -1;
9065
+ at2 = code[at2 + 2];
9066
+ continue;
9067
+ }
9068
+ if (op === OP_SEQX) {
9069
+ if (code[at2 + 2] !== 1) return -1;
9070
+ at2 = code[at2 + 3];
9071
+ continue;
9072
+ }
9073
+ return -1;
9074
+ }
9075
+ return -1;
9076
+ };
9077
+ const seen = /* @__PURE__ */ new Set();
9078
+ let at = ip;
9079
+ let ambientTrivia;
9080
+ while (!seen.has(at)) {
9081
+ seen.add(at);
9082
+ const op = code[at];
9083
+ if (op === OP_RULE) {
9084
+ at = code[at + 1];
9085
+ continue;
9086
+ }
9087
+ if (op === OP_SCOPE_PLAIN) {
9088
+ ambientTrivia = code[at + 1];
9089
+ at = code[at + 2];
9090
+ continue;
9091
+ }
9092
+ if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9093
+ at = code[at + 2];
9094
+ continue;
9095
+ }
9096
+ const n = op === OP_SEQ || op === OP_SEQV ? code[at + 1] : op === OP_SEQX ? code[at + 2] : 0;
9097
+ if (n < 3 || ambientTrivia === void 0) return void 0;
9098
+ const base = op === OP_SEQX ? at + 3 : at + 2;
9099
+ const terminals = [
9100
+ wholeScalar(code[base]),
9101
+ wholeScalar(code[base + 1]),
9102
+ wholeScalar(code[base + 2])
9103
+ ];
9104
+ return terminals.every((terminal) => terminal >= 0) ? { terminals, trivia: ambientTrivia } : void 0;
9105
+ }
9106
+ return void 0;
9107
+ }
9108
+ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
9109
+ const active = /* @__PURE__ */ new Set();
9110
+ const walk = (at, depth) => {
9111
+ if (active.has(at)) return void 0;
9112
+ active.add(at);
9113
+ try {
9114
+ const op = code[at];
9115
+ if (op === OP_LIT) {
9116
+ const value = constants[code[at + 1]];
9117
+ return depth >= minDepth && typeof value === "string" && value.length > 0 ? [at] : void 0;
9118
+ }
9119
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
9120
+ return walk(code[at + 1], depth + 1);
9121
+ }
9122
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9123
+ return walk(code[at + 2], depth + 1);
9124
+ }
9125
+ if (op === OP_SEQ || op === OP_SEQV) {
9126
+ return code[at + 1] < 1 ? void 0 : walk(code[at + 2], depth + 1);
9127
+ }
9128
+ if (op === OP_SEQX) {
9129
+ return code[at + 2] < 1 ? void 0 : walk(code[at + 3], depth + 1);
9130
+ }
9131
+ if (op !== OP_CHOICE) return void 0;
9132
+ const n = code[at + 2];
9133
+ if (n < 1) return void 0;
9134
+ const out = [];
9135
+ for (let i = 0; i < n; i++) {
9136
+ const branch = walk(code[at + 4 + i], depth + 1);
9137
+ if (branch === void 0) return void 0;
9138
+ for (const terminal of branch) {
9139
+ const value = constants[code[terminal + 1]];
9140
+ let covered = false;
9141
+ for (let j = 0; j < out.length; j++) {
9142
+ const prior = constants[code[out[j] + 1]];
9143
+ if (value.startsWith(prior)) {
9144
+ covered = true;
9145
+ break;
9146
+ }
9147
+ }
9148
+ if (covered) continue;
9149
+ for (let j = out.length - 1; j >= 0; j--) {
9150
+ const prior = constants[code[out[j] + 1]];
9151
+ if (prior.startsWith(value)) out.splice(j, 1);
9152
+ }
9153
+ out.push(terminal);
9154
+ if (out.length > limit) return void 0;
9155
+ }
9156
+ }
9157
+ return out;
9158
+ } finally {
9159
+ active.delete(at);
9160
+ }
9161
+ };
9162
+ return walk(ip, 0);
9163
+ }
8427
9164
 
8428
9165
  // src/table/emit-assembly.ts
8429
9166
  var Unemittable = class extends Error {
@@ -8505,6 +9242,16 @@ let _pfScan=null
8505
9242
  let _pfHost
8506
9243
  let _pfDepth=0
8507
9244
  const _pfFrames=[]
9245
+ let _pfTokInput
9246
+ let _pfTokPos=-1
9247
+ let _pfTokBody=-1
9248
+ let _pfTokPacked=-1
9249
+ let _pfTokValue
9250
+ let _pfTokDispatch=-1
9251
+ let _pfTokArm=-1
9252
+ let _pfTokEnd=-1
9253
+ let _pfSeqEnd=-1
9254
+ function _asciiFoldCode(c){return c>=65&&c<=90?c+32:c}
8508
9255
  function _skipTrivia(input,cur,ctx){
8509
9256
  const s=_pfScan
8510
9257
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
@@ -8570,6 +9317,40 @@ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=
8570
9317
  if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
8571
9318
  }
8572
9319
  `;
9320
+ var NO_RAW_RUNTIME_PRELUDE = `
9321
+ function _pushLeafNoRawBuf(ctx,value,s,e){
9322
+ const l={_tag:'leaf',value,span:{start:s,end:e}}
9323
+ const b=ctx._cstBuf
9324
+ if(b.ch!==undefined)b.ch.push(l)
9325
+ else if(b.single!==undefined){b.ch=[b.single,l];b.single=undefined}
9326
+ else b.single=l
9327
+ b.rawLen++
9328
+ }
9329
+ function _pushNodeNoRawBuf(ctx,value){
9330
+ const b=ctx._cstBuf
9331
+ if(b.ch!==undefined)b.ch.push(value)
9332
+ else if(b.single!==undefined){b.ch=[b.single,value];b.single=undefined}
9333
+ else b.single=value
9334
+ b.rawLen++
9335
+ }
9336
+ function _rbNoRawBuf(ctx,raw,tl,lv,lg,rt){
9337
+ const b=ctx._cstBuf
9338
+ if(b.rawLen!==raw)b.rawLen=raw
9339
+ const ch=b.ch
9340
+ if(ch!==undefined){
9341
+ if(lv===0)b.ch=undefined
9342
+ else if(lv===1){b.single=ch[0];b.ch=undefined}
9343
+ else if(ch.length!==lv)ch.length=lv
9344
+ }else if(lv===0)b.single=undefined
9345
+ const bt=b.tl
9346
+ if(bt!==undefined){
9347
+ if(tl===0)b.tl=undefined
9348
+ else if(bt.length!==tl)bt.length=tl
9349
+ }
9350
+ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=lg
9351
+ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
9352
+ }
9353
+ `;
8573
9354
  function q(s) {
8574
9355
  return JSON.stringify(s);
8575
9356
  }
@@ -8582,11 +9363,12 @@ function sinkReads(t, s) {
8582
9363
  ${t}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${s.er ? `
8583
9364
  ${t}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
8584
9365
  }
8585
- function emitMark(t, buf, s = NO_SINKS, decl = true) {
9366
+ function emitMark(t, buf, rawMode, s = NO_SINKS, decl = true) {
8586
9367
  if (buf) {
9368
+ const raw = rawMode === RAW_OMIT ? `${t}raw=b.rawLen` : rawMode === RAW_CAPTURE ? `const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${t}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
8587
9369
  return `${decl ? `let ${t}raw=0,${t}tl=0,${t}lv=0,${t}lg=0,${t}rt=0${sinkSlots(t, s)}
8588
9370
  ` : ""}{const b=ctx._cstBuf
8589
- const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9371
+ ${raw}
8590
9372
  const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
8591
9373
  const l=b.tl;${t}tl=l!==undefined?l.length:0
8592
9374
  ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
@@ -8596,7 +9378,7 @@ ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t,
8596
9378
  ` : `${t}n=false
8597
9379
  `}{const b=ctx._cstBuf
8598
9380
  if(b!==undefined){
8599
- const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9381
+ const r=b.raw;${t}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
8600
9382
  const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
8601
9383
  const l=b.tl;${t}tl=l!==undefined?l.length:0
8602
9384
  ${t}n=true
@@ -8611,14 +9393,16 @@ ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8611
9393
  ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t, s)}
8612
9394
  }}`;
8613
9395
  }
8614
- function emitRollback(t, buf, s = NO_SINKS) {
9396
+ function emitRollback(t, buf, rawMode, s = NO_SINKS) {
8615
9397
  const fd = s.fd ? `
8616
9398
  if(ctx._fields!==undefined&&ctx._fields.length!==${t}fd)ctx._fields.length=${t}fd` : "";
8617
9399
  const er = s.er ? `
8618
9400
  if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}er` : "";
8619
- if (buf) return `_rbBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
8620
- if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,0,undefined,${t}lg,${t}rt)`;
8621
- return `if(${t}n){rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "0"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)}`;
9401
+ if (buf && rawMode === RAW_OMIT) return `_rbNoRawBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
9402
+ if (buf && rawMode === RAW_CAPTURE) return `_rbBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
9403
+ if (buf) return `rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "undefined"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)`;
9404
+ if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,undefined,undefined,${t}lg,${t}rt)`;
9405
+ return `if(${t}n){rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "undefined"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)}`;
8622
9406
  }
8623
9407
  function emitTerm(callee, dst, t, l, skip) {
8624
9408
  const fast = `const ${t}v=${callee}(input,cur,ctx)
@@ -8676,37 +9460,111 @@ function rebuildPools(cc, fx, disp, plan) {
8676
9460
  })
8677
9461
  };
8678
9462
  }
8679
- function emitAssemblySource(t, prog, cfg, extraIps = []) {
8680
- const { code, k, disp, dsp, triviaLabelled } = t;
9463
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
9464
+ const { code, k, fx, disp, dsp, triviaLabelled } = t;
8681
9465
  const swapLegal = !cfg.trackLines;
8682
9466
  const hostCst = cfg.hostCst;
8683
9467
  const REC2 = prog.rec === 1 && cfg.tolerant;
8684
9468
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
8685
9469
  const roots = [...Object.values(prog.rules), ...extraIps];
9470
+ const reachable = [...reachableSites(code, roots)];
8686
9471
  const labels = computeSiteLabels(code, roots, hostCst);
8687
9472
  const scalarSpecs = /* @__PURE__ */ new Set();
9473
+ const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
9474
+ const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
9475
+ const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
9476
+ const tokenChoiceCandidates = /* @__PURE__ */ new Map();
9477
+ const tokenChoiceDispatches = /* @__PURE__ */ new Set();
9478
+ const tokenChoiceBodies = /* @__PURE__ */ new Set();
8688
9479
  if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
8689
- for (const ip of reachableSites(code, roots)) {
8690
- if (code[ip] !== OP_NODE) continue;
8691
- const child = scalarTerminalNodeChild(code, ip);
8692
- if (child >= 0) scalarSpecs.add(code[child + 1]);
9480
+ for (const ip of reachable) {
9481
+ if (code[ip] === OP_NODE) {
9482
+ const child = scalarTerminalNodeChild(code, ip);
9483
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
9484
+ continue;
9485
+ }
9486
+ if (code[ip] !== OP_CHOICE || disp[code[ip + 1]].exclusive) continue;
9487
+ const n = code[ip + 2];
9488
+ for (let i = 0; i < n; i++) {
9489
+ const armIp = code[ip + 4 + i];
9490
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
9491
+ if (n === 2 || n === 3) {
9492
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
9493
+ continue;
9494
+ }
9495
+ if (child >= 0) {
9496
+ const spec = k[code[child + 1]];
9497
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
9498
+ largeChoiceScalarSpecs.add(code[child + 1]);
9499
+ continue;
9500
+ }
9501
+ }
9502
+ const family = leadingLiteralFamily(code, k, armIp);
9503
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
9504
+ const value = k[code[terminal + 1]];
9505
+ return typeof value === "string" && value.length >= 2;
9506
+ })) {
9507
+ largeChoiceLiteralFamilies.set(armIp, family);
9508
+ }
9509
+ const sequence6 = leadingScalarSequence(code, armIp);
9510
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
9511
+ largeChoiceScalarSequences.set(armIp, sequence6);
9512
+ }
9513
+ }
9514
+ let candidate;
9515
+ let ambiguous = false;
9516
+ for (let i = 0; i < n; i++) {
9517
+ const armIp = code[ip + 4 + i];
9518
+ if (code[armIp] !== OP_XFORM) continue;
9519
+ const dispatchIp = code[armIp + 2];
9520
+ if (code[dispatchIp] !== OP_DISPATCH) continue;
9521
+ const selectorIp = code[dispatchIp + 1];
9522
+ if (code[selectorIp] !== OP_LEX_BODY) continue;
9523
+ if (candidate !== void 0) {
9524
+ ambiguous = true;
9525
+ break;
9526
+ }
9527
+ candidate = { arm: i, dispatchIp };
9528
+ }
9529
+ if (!ambiguous && candidate !== void 0) {
9530
+ tokenChoiceCandidates.set(ip, candidate);
9531
+ tokenChoiceDispatches.add(candidate.dispatchIp);
9532
+ tokenChoiceBodies.add(code[code[candidate.dispatchIp + 1] + 1]);
9533
+ }
8693
9534
  }
8694
9535
  }
8695
- const sinks = (() => {
8696
- let fd = false;
8697
- let er = REC2;
8698
- for (const ip of reachableSites(code, roots)) {
8699
- const op = code[ip];
8700
- if (op === OP_SCAN) {
8701
- fd = true;
8702
- er = true;
8703
- break;
9536
+ const needsNoRawPrelude = !hostCst && reachable.some((ip) => {
9537
+ const op = code[ip];
9538
+ return (op === OP_NODE || op === OP_NODE_TRACK) && code[ip + 1] >= 0 && code[ip + 4] < 0 && (code[ip + 3] & 2) !== 0;
9539
+ });
9540
+ const sinkSites = reachable;
9541
+ const sinkBits = /* @__PURE__ */ new Map();
9542
+ for (const ip of sinkSites) {
9543
+ const op = code[ip];
9544
+ sinkBits.set(
9545
+ ip,
9546
+ op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC2 && (op === OP_REP || op === OP_REPV) ? 2 : 0)
9547
+ );
9548
+ }
9549
+ const sinkKids = [];
9550
+ let sinkChanged = true;
9551
+ while (sinkChanged) {
9552
+ sinkChanged = false;
9553
+ for (const ip of sinkSites) {
9554
+ let bits = sinkBits.get(ip) ?? 0;
9555
+ sinkKids.length = 0;
9556
+ childSlots(code, ip, sinkKids);
9557
+ for (let i = 0; i < sinkKids.length; i++) bits |= sinkBits.get(sinkKids[i]) ?? 0;
9558
+ if (bits !== sinkBits.get(ip)) {
9559
+ sinkBits.set(ip, bits);
9560
+ sinkChanged = true;
8704
9561
  }
8705
- if (op === OP_FIELD) fd = true;
8706
- else if (op === OP_EXPECT) er = true;
8707
9562
  }
8708
- return { fd, er };
8709
- })();
9563
+ }
9564
+ const sinksAt = (ip) => {
9565
+ const bits = sinkBits.get(ip) ?? 0;
9566
+ return bits === 0 ? NO_SINKS : { fd: (bits & 1) !== 0, er: (bits & 2) !== 0 };
9567
+ };
8710
9568
  const bodies = [];
8711
9569
  const byIp = /* @__PURE__ */ new Map();
8712
9570
  const reached = /* @__PURE__ */ new Set();
@@ -8733,9 +9591,117 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
8733
9591
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
8734
9592
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
8735
9593
  const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
9594
+ const scalarSequenceRefs = /* @__PURE__ */ new Map();
9595
+ const scalarSequenceRef = (sequence6) => {
9596
+ const key = `${sequence6.trivia}:${sequence6.terminals.map((terminal) => code[terminal + 1]).join(",")}`;
9597
+ const prior = scalarSequenceRefs.get(key);
9598
+ if (prior !== void 0) return prior;
9599
+ const recognizers = sequence6.terminals.map((terminal) => recognizerRef(code[terminal + 1]));
9600
+ const expected = sequence6.terminals.map((terminal) => fxRef(code[terminal + 2]));
9601
+ const scan = sequence6.trivia < 0 ? void 0 : hoist("ts", `TRIVIASCAN[${sequence6.trivia}]`);
9602
+ const name = `_sd${scalarSequenceRefs.size}_`;
9603
+ const steps = recognizers.map((recognize, i) => `${i === 0 ? "let " : ""}at=${i === 0 ? "pos" : scan === void 0 ? "cur" : `${scan}(input,cur)`}
9604
+ ${i === 0 ? "let " : ""}cur=${recognize}(input,at)
9605
+ if(cur<0){_pfSeqEnd=at;return ${~i}}`).join("\n");
9606
+ choiceDefs.push(`function ${name}(input,pos){
9607
+ ${steps}
9608
+ return cur
9609
+ }`);
9610
+ const made = { name, expected };
9611
+ scalarSequenceRefs.set(key, made);
9612
+ return made;
9613
+ };
8736
9614
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
8737
9615
  let uid = 0;
8738
9616
  const tmp = () => `_t${uid++}_`;
9617
+ const dispatchClaim = (m) => {
9618
+ switch (m[0]) {
9619
+ case 0:
9620
+ return `key.startsWith(${q(m[1])})`;
9621
+ case 1:
9622
+ return `key.endsWith(${q(m[1])})`;
9623
+ case 3:
9624
+ return `asciiFoldKey(key).startsWith(${q(m[1])})`;
9625
+ case 4:
9626
+ return `asciiFoldKey(key).endsWith(${q(m[1])})`;
9627
+ default: {
9628
+ if (!m[2].includes("g") && !m[2].includes("y")) {
9629
+ try {
9630
+ new RegExp(m[1], m[2]);
9631
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
9632
+ } catch {
9633
+ }
9634
+ }
9635
+ return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
9636
+ }
9637
+ }
9638
+ };
9639
+ const tokenDecisionRefs = /* @__PURE__ */ new Map();
9640
+ function tokenDecisionFor(dispatchIp) {
9641
+ const prior = tokenDecisionRefs.get(dispatchIp);
9642
+ if (prior !== void 0) return prior;
9643
+ const selectorIp = code[dispatchIp + 1];
9644
+ const body = code[selectorIp + 1];
9645
+ const lineFlags = code[selectorIp + 4];
9646
+ const hasSuffix = (lineFlags & 4) !== 0;
9647
+ const di = code[dispatchIp + 2];
9648
+ const spec = dsp[di];
9649
+ const n = code[dispatchIp + 5];
9650
+ validateDispatchSpec(spec, n, code[dispatchIp + 4]);
9651
+ const recognize = hoist("lex", `LEX[${body}]`);
9652
+ const bk = hoist("bk", `DSP[${di}].byKey`);
9653
+ const expected = hoist("dx", `DSP[${di}].expected`);
9654
+ const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
9655
+ ` : "";
9656
+ const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
9657
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
9658
+ }
9659
+ `;
9660
+ const foldedEntries = [...spec.byFold.entries()];
9661
+ const fixedFunctionChoice = spec.byKey.size === 0 && foldedEntries.length === 1 && spec.match.length === 1 && spec.match[0][0] === 2 && spec.match[0][1] === "^(?!(?:url|calc)\\($).+\\($" && spec.match[0][2] === "i" && code[dispatchIp + 3] < 0;
9662
+ const foldedRangeEquals = (value) => {
9663
+ const folded = value.replace(/[A-Z]/g, (c) => c.toLowerCase());
9664
+ return `e-pos===${folded.length}&&${[...folded].map((c, i) => {
9665
+ const cc = c.charCodeAt(0);
9666
+ return `_asciiFoldCode(input.charCodeAt(pos+${i}))===${cc}`;
9667
+ }).join("&&")}`;
9668
+ };
9669
+ const classify = fixedFunctionChoice ? (() => {
9670
+ const [exact, exactArm] = foldedEntries[0];
9671
+ const genericArm = spec.match[0][3];
9672
+ return `let arm
9673
+ if(${foldedRangeEquals(exact)})arm=${exactArm}
9674
+ else if(sm&&e>pos+1){
9675
+ let clean=true
9676
+ for(let i=pos;i<e;i++){const c=input.charCodeAt(i);if(c===10||c===13||c===0x2028||c===0x2029){clean=false;break}}
9677
+ if(clean&&!(${foldedRangeEquals("url(")})&&!(${foldedRangeEquals("calc(")}))arm=${genericArm}
9678
+ }`;
9679
+ })() : `const key=input.slice(pos,e)
9680
+ let arm=${bk}.get(key)
9681
+ ${fold}${chain}`;
9682
+ const name = `_td${tokenDecisionRefs.size}_`;
9683
+ choiceDefs.push(`function ${name}(input,pos){
9684
+ const r=${recognize}(input,pos)
9685
+ if(r<0)return -1
9686
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9687
+ ${classify}
9688
+ if(arm===undefined){
9689
+ ${code[dispatchIp + 3] < 0 ? "_pfTokEnd=e;return 0" : `arm=${n}`}
9690
+ }
9691
+ ${fixedFunctionChoice ? "const key=input.slice(pos,e)" : ""}
9692
+ _pfTokInput=input
9693
+ _pfTokPos=pos
9694
+ _pfTokBody=${body}
9695
+ _pfTokPacked=r
9696
+ _pfTokValue=key
9697
+ _pfTokDispatch=${dispatchIp}
9698
+ _pfTokArm=arm
9699
+ return 1
9700
+ }`);
9701
+ const made = { name, expected };
9702
+ tokenDecisionRefs.set(dispatchIp, made);
9703
+ return made;
9704
+ }
8739
9705
  function skipFor(l) {
8740
9706
  if (l.tri < 0) return "_skipTrivia";
8741
9707
  const ki = l.tri;
@@ -8823,7 +9789,8 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8823
9789
  const op = code[ip];
8824
9790
  const head = `function ${fname}(input,pos,ctx){`;
8825
9791
  const L = labels.at(ip);
8826
- const pushLeaf = L.buf && !cfg.trackLines ? "_pushLeafBuf" : "_pushLeaf";
9792
+ const sinks = sinksAt(ip);
9793
+ const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
8827
9794
  const captureLeaf = (value) => {
8828
9795
  const call = `${pushLeaf}(ctx,${value},pos,e)`;
8829
9796
  return L.buf ? call : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${call}`;
@@ -8987,12 +9954,12 @@ return err
8987
9954
  }
8988
9955
  case OP_ROUTED: {
8989
9956
  const fb = code[ip + 1];
8990
- const fallback = fb >= 0 ? link(fb) : void 0;
9957
+ const fallback2 = fb >= 0 ? link(fb) : void 0;
8991
9958
  const push = `pushCstLeaf(ctx,{_tag:'leaf',value:it.value,span:it.span})`;
8992
9959
  return `${head}
8993
9960
  const it=ctx._routed
8994
9961
  if(it===undefined||pos!==it.span.start){
8995
- ${fallback !== void 0 ? `return ${fallback}(input,pos,ctx)` : "ctx._fe=pos;ctx._fx=ROUTED_FX;return FAIL"}
9962
+ ${fallback2 !== void 0 ? `return ${fallback2}(input,pos,ctx)` : "ctx._fe=pos;ctx._fx=ROUTED_FX;return FAIL"}
8996
9963
  }
8997
9964
  ${L.buf ? push : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${push}`}
8998
9965
  EC.e=it.span.end
@@ -9074,20 +10041,24 @@ return out
9074
10041
  }`;
9075
10042
  }
9076
10043
  case OP_LEX_BODY: {
9077
- const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
10044
+ const body = code[ip + 1];
10045
+ const recognize = hoist("lex", `LEX[${body}]`);
9078
10046
  const expected = fxRef(code[ip + 2]);
9079
10047
  const suffixExpected = fxRef(code[ip + 3]);
9080
10048
  const lineFlags = code[ip + 4];
9081
10049
  const hasSuffix = (lineFlags & 4) !== 0;
10050
+ const pending = tokenChoiceBodies.has(body);
9082
10051
  return `${head}
9083
- const r=${recognize}(input,pos)
10052
+ ${pending ? `const tp=_pfTokBody===${body}&&_pfTokInput===input&&_pfTokPos===pos
10053
+ const r=tp?_pfTokPacked:${recognize}(input,pos)` : `const r=${recognize}(input,pos)`}
9084
10054
  if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
9085
10055
  const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9086
10056
  ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
9087
10057
  ${hasSuffix ? "ctx._fc=false" : ""}
9088
10058
  ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
9089
10059
  ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
9090
- const v=input.slice(pos,e)
10060
+ const v=${pending ? "tp?_pfTokValue:" : ""}input.slice(pos,e)
10061
+ ${pending ? "if(tp){_pfTokBody=-1;_pfTokValue=undefined}" : ""}
9091
10062
  if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9092
10063
  EC.e=e
9093
10064
  return v
@@ -9143,12 +10114,13 @@ return v
9143
10114
  /* ── transaction ─────────────────────────────────────────────────────── */
9144
10115
  case OP_ATTEMPT: {
9145
10116
  const child = link(code[ip + 1]);
10117
+ const clean = !REC2 && failureRollbackClean(prog, ip);
9146
10118
  const p = tmp();
9147
10119
  return `${head}
9148
- ${emitMark(p, L.buf, sinks)}
10120
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
9149
10121
  const v=${child}(input,pos,ctx)
9150
10122
  if(v!==FAIL)return v
9151
- ${emitRollback(p, L.buf, sinks)}
10123
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
9152
10124
  if(ctx._fc===true)return FAIL
9153
10125
  ctx._fe=pos
9154
10126
  return FAIL
@@ -9171,9 +10143,9 @@ return FAIL
9171
10143
  const xf = fxRef(code[ip + 2]);
9172
10144
  const p = tmp();
9173
10145
  return `${head}
9174
- ${emitMark(p, L.buf, sinks)}
10146
+ ${emitMark(p, L.buf, L.raw, sinks)}
9175
10147
  const v=${child}(input,pos,ctx)
9176
- ${emitRollback(p, L.buf, sinks)}
10148
+ ${emitRollback(p, L.buf, L.raw, sinks)}
9177
10149
  if(v===FAIL){EC.e=pos;return null}
9178
10150
  ctx._fe=pos
9179
10151
  ctx._fx=${xf}
@@ -9185,9 +10157,9 @@ return FAIL
9185
10157
  const xf = fxRef(code[ip + 2]);
9186
10158
  const p = tmp();
9187
10159
  return `${head}
9188
- ${emitMark(p, L.buf, sinks)}
10160
+ ${emitMark(p, L.buf, L.raw, sinks)}
9189
10161
  const v=${child}(input,pos,ctx)
9190
- ${emitRollback(p, L.buf, sinks)}
10162
+ ${emitRollback(p, L.buf, L.raw, sinks)}
9191
10163
  if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9192
10164
  EC.e=pos
9193
10165
  return null
@@ -9195,14 +10167,15 @@ return null
9195
10167
  }
9196
10168
  case OP_OPT: {
9197
10169
  const child = link(code[ip + 1]);
10170
+ const clean = !REC2 && failureRollbackClean(prog, ip);
9198
10171
  const p = tmp();
9199
10172
  return `${head}
9200
- ${emitMark(p, L.buf, sinks)}
10173
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
9201
10174
  ctx._fc=false
9202
10175
  const v=${child}(input,pos,ctx)
9203
10176
  if(v===FAIL){
9204
10177
  if(ctx._fc===true)return FAIL
9205
- ${emitRollback(p, L.buf, sinks)}
10178
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
9206
10179
  EC.e=pos
9207
10180
  return null
9208
10181
  }
@@ -9301,57 +10274,193 @@ return FAIL
9301
10274
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
9302
10275
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
9303
10276
  const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
10277
+ const tokenCandidate = tokenChoiceCandidates.get(ip);
10278
+ const pretests = Array.from({ length: n }, (_, i) => {
10279
+ if (tokenCandidate?.arm === i) {
10280
+ return { token: tokenDecisionFor(tokenCandidate.dispatchIp) };
10281
+ }
10282
+ const terminal = leadingScalarTerminal(code, code[base + i], 2, true, true);
10283
+ if (terminal >= 0) {
10284
+ const spec = code[terminal + 1];
10285
+ if ((n === 2 || n === 3 ? scalarSpecs : largeChoiceScalarSpecs).has(spec)) {
10286
+ return { scalar: [recognizerRef(spec)] };
10287
+ }
10288
+ }
10289
+ const family = largeChoiceLiteralFamilies.get(code[base + i]);
10290
+ if (family !== void 0) {
10291
+ return { scalar: family.map((member) => recognizerRef(code[member + 1])) };
10292
+ }
10293
+ const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
10294
+ return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
10295
+ });
9304
10296
  const maskable = n <= 32;
9305
10297
  const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
9306
10298
  if (maskable) maskPlan.push(~di);
9307
10299
  const p = tmp();
9308
- const catchName = maskable ? `_cx${uid++}_` : "";
9309
- if (maskable) {
10300
+ const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
10301
+ const rollbackMask = REC2 ? -1 : encodedRollbackMask;
10302
+ const hasRollback = rollbackMask !== 0;
10303
+ const startFailureExact = arms.every((_arm, i) => {
10304
+ const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
10305
+ if (terminal < 0) return false;
10306
+ const op2 = code[terminal];
10307
+ const spec = k[code[terminal + 1]];
10308
+ const terminalFx = fx[code[terminal + 2]];
10309
+ const armFx = fx[code[base + n + i]];
10310
+ if (terminalFx.length !== armFx.length || terminalFx.some((expected2, at) => expected2 !== armFx[at])) return false;
10311
+ if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
10312
+ return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
10313
+ });
10314
+ const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
10315
+ if (choiceCannotCommit(prog, ip) && !startFailureExact) {
10316
+ const deepAt = Array.from({ length: n }, () => tmp());
10317
+ const deepFx = Array.from({ length: n }, () => tmp());
10318
+ const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
10319
+ const lazyArms = (ascii) => arms.map((arm, i) => {
10320
+ const pretest = pretests[i];
10321
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10322
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
10323
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10324
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10325
+ const gate2 = ascii ? `(bits&${1 << i})!==0${condition}` : `(${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}`;
10326
+ const routeMiss = pretest?.token === void 0 ? "" : `
10327
+ if(${decision}===0){
10328
+ ctx._fc=false
10329
+ {const at=_pfTokEnd
10330
+ ${remember(i, "at", pretest.token.expected)}}
10331
+ }`;
10332
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10333
+ else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
10334
+ ctx._fc=false
10335
+ {const at=_pfSeqEnd
10336
+ ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
10337
+ }`;
10338
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10339
+ `}if(${gate2}){
10340
+ ctx._fc=false
10341
+ {const v=${arm}(input,pos,ctx)
10342
+ if(v!==FAIL)return v}
10343
+ {const at=ctx._fe??pos
10344
+ ${remember(i, "at", "ctx._fx")}}
10345
+ ${rollbackFor(i)}
10346
+ }${routeMiss}${sequenceMiss}`;
10347
+ }).join("\n");
10348
+ const merge = deepAt.map((at, i) => `{const at=${at}??pos
10349
+ const ex=${at}===undefined?${expected[i]}:${deepFx[i]}
10350
+ if(at>best){best=at;acc=_accSet(ex,undefined)}
10351
+ else if(at===best)acc=_accSet(ex,acc)
10352
+ }`).join("\n");
10353
+ const finish = `let best=pos,acc
10354
+ ${merge}
10355
+ ctx._fe=pos;ctx._fx=acc??${choiceFx}
10356
+ return FAIL`;
10357
+ return `${head}
10358
+ const c=lead(input,pos)
10359
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
10360
+ ${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
10361
+ ${maskable ? `if(c<128){
10362
+ const bits=${maskName}[c<0?128:c]
10363
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10364
+ ${lazyArms(true)}
10365
+ }else{
10366
+ ${lazyArms(false)}
10367
+ }
10368
+ ` : lazyArms(false)}
10369
+ ${finish}
10370
+ }`;
10371
+ }
10372
+ const needsCatch = maskable || startFailureExact;
10373
+ const catchName = needsCatch ? `_cx${uid++}_` : "";
10374
+ if (needsCatch) {
9310
10375
  const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
9311
10376
  choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
9312
10377
  ${catchCases}
9313
10378
  }return acc}`);
9314
10379
  }
9315
10380
  const maskArms = maskable ? arms.map((arm, i) => {
9316
- return `if((bits&${1 << i})!==0){
10381
+ const pretest = pretests[i];
10382
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10383
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
10384
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10385
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10386
+ const routeMiss = pretest?.token === void 0 ? "" : `
10387
+ if(${decision}===0){
10388
+ ctx._fc=false
10389
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10390
+ prev=${i + 1}`}
10391
+ {const at=_pfTokEnd
10392
+ if(at>best){best=at;acc=undefined}
10393
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)}
10394
+ }`;
10395
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10396
+ else if((bits&${1 << i})!==0&&${decision}<0){
10397
+ ctx._fc=false
10398
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10399
+ prev=${i + 1}`}
10400
+ {const at=_pfSeqEnd
10401
+ if(at>best){best=at;acc=undefined}
10402
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)}
10403
+ }`;
10404
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10405
+ `}if((bits&${1 << i})!==0${condition}){
9317
10406
  ctx._fc=false
9318
10407
  {const v=${arm}(input,pos,ctx)
9319
10408
  if(v!==FAIL)return v}
9320
- if(best===pos)acc=${catchName}(${i},prev,acc)
9321
- prev=${i + 1}
10409
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10410
+ prev=${i + 1}`}
9322
10411
  {const at=ctx._fe??pos
9323
10412
  if(at>best){best=at;acc=undefined}
9324
- if(at===best)acc=_accSet(ctx._fx,acc)}
9325
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
9326
- ${emitRollback(p, L.buf, sinks)}
9327
- }`;
10413
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
10414
+ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
10415
+ ${rollbackFor(i)}
10416
+ }${routeMiss}${sequenceMiss}`;
9328
10417
  }).join("\n") : "";
9329
- const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
10418
+ const generalArms = arms.map((arm, i) => {
10419
+ const pretest = pretests[i];
10420
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10421
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
10422
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10423
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10424
+ const miss = pretest?.sequence !== void 0 ? `else if(${decision}<0){
10425
+ ctx._fc=false
10426
+ const at=_pfSeqEnd
10427
+ if(at>best){best=at;acc=undefined}
10428
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)
10429
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}` : pretest?.token === void 0 ? startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)` : `else if(${decision}===0){
10430
+ ctx._fc=false
10431
+ const at=_pfTokEnd
10432
+ if(at>best){best=at;acc=undefined}
10433
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)
10434
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
10435
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10436
+ `}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
9330
10437
  ctx._fc=false
9331
10438
  {const v=${arm}(input,pos,ctx)
9332
10439
  if(v!==FAIL)return v}
9333
10440
  {const at=ctx._fe??pos
9334
10441
  if(at>best){best=at;acc=undefined}
9335
- if(at===best)acc=_accSet(ctx._fx,acc)}
9336
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
9337
- ${emitRollback(p, L.buf, sinks)}
9338
- }else if(best===pos)acc=_accSet(${expected[i]},acc)`).join("\n");
10442
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
10443
+ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
10444
+ ${rollbackFor(i)}
10445
+ }${miss}`;
10446
+ }).join("\n");
9339
10447
  return `${head}
9340
10448
  const c=lead(input,pos)
9341
- ${emitMark(p, L.buf, sinks)}
10449
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
9342
10450
  let acc
9343
10451
  let best=pos
9344
10452
  ${maskable ? `if(c<128){
9345
10453
  const bits=${maskName}[c<0?128:c]
9346
- let prev=0
10454
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10455
+ ${startFailureExact ? "" : "let prev=0"}
9347
10456
  ${maskArms}
9348
- if(best===pos)acc=${catchName}(${n},prev,acc)
9349
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
10457
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
10458
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
9350
10459
  return FAIL
9351
10460
  }
9352
10461
  ` : ""}
9353
10462
  ${generalArms}
9354
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
10463
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
9355
10464
  return FAIL
9356
10465
  }`;
9357
10466
  }
@@ -9370,30 +10479,8 @@ return FAIL
9370
10479
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
9371
10480
  const bk = hoist("bk", `DSP[${di}].byKey`);
9372
10481
  const dx = hoist("dx", `DSP[${di}].expected`);
9373
- const claims = (m) => {
9374
- switch (m[0]) {
9375
- case 0:
9376
- return `key.startsWith(${q(m[1])})`;
9377
- case 1:
9378
- return `key.endsWith(${q(m[1])})`;
9379
- case 3:
9380
- return `asciiFoldKey(key).startsWith(${q(m[1])})`;
9381
- case 4:
9382
- return `asciiFoldKey(key).endsWith(${q(m[1])})`;
9383
- default: {
9384
- if (!m[2].includes("g") && !m[2].includes("y")) {
9385
- try {
9386
- new RegExp(m[1], m[2]);
9387
- return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
9388
- } catch {
9389
- }
9390
- }
9391
- return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
9392
- }
9393
- }
9394
- };
9395
10482
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
9396
- ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}`).join("\n")}
10483
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
9397
10484
  }
9398
10485
  `;
9399
10486
  const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
@@ -9401,33 +10488,43 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
9401
10488
  const m1 = tmp();
9402
10489
  const m2 = tmp();
9403
10490
  const routedCall = (target) => `{const savedRouted=ctx._routed
9404
- ${emitRollback(m1, L.buf, sinks)}
9405
- ${emitMark(m2, L.buf, sinks, false)}
10491
+ ${emitRollback(m1, L.buf, L.raw, sinks)}
10492
+ ${emitMark(m2, L.buf, L.raw, sinks, false)}
9406
10493
  ctx._routed={value:key,span:{start:pos,end:selEnd}}
9407
10494
  try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
9408
10495
  break}`;
9409
10496
  const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
9410
10497
  const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
9411
10498
  const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
10499
+ const armSelection = tokenChoiceDispatches.has(ip) ? `const tp=_pfTokDispatch===${ip}&&_pfTokInput===input&&_pfTokPos===pos
10500
+ let arm
10501
+ if(tp){
10502
+ arm=_pfTokArm
10503
+ _pfTokDispatch=-1
10504
+ _pfTokInput=undefined
10505
+ if(arm===${n})arm=undefined
10506
+ }else{
10507
+ arm=${bk}.get(key)
10508
+ ${fold}${chain}}` : `let arm=${bk}.get(key)
10509
+ ${fold}${chain}`;
9412
10510
  return `${head}
9413
- ${emitMark(m1, L.buf, sinks)}
10511
+ ${emitMark(m1, L.buf, L.raw, sinks)}
9414
10512
  const sv=${selector}(input,pos,ctx)
9415
10513
  if(sv===FAIL)return FAIL
9416
10514
  const selEnd=EC.e
9417
10515
  const key=sv
9418
- let arm=${bk}.get(key)
9419
- ${fold}${chain}
10516
+ ${armSelection}
9420
10517
  if(arm===undefined){
9421
10518
  ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
9422
10519
  }
9423
- ${emitMark(m2, L.buf, sinks)}
10520
+ ${emitMark(m2, L.buf, L.raw, sinks)}
9424
10521
  let v
9425
10522
  switch(arm){
9426
10523
  ${armCases}
9427
10524
  ${fallbackCase}
9428
10525
  }
9429
10526
  if(v===FAIL){
9430
- ${emitRollback(m2, L.buf, sinks)}
10527
+ ${emitRollback(m2, L.buf, L.raw, sinks)}
9431
10528
  ctx._fc=true
9432
10529
  return FAIL
9433
10530
  }
@@ -9463,23 +10560,25 @@ return [key,v]
9463
10560
  const skip = skipFor(L);
9464
10561
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
9465
10562
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
9466
- const pfd = sinks.fd ? `${p}fd` : "0";
10563
+ const pfd = sinks.fd ? `${p}fd` : "undefined";
9467
10564
  const per = sinks.er ? `${p}er` : "undefined";
9468
- const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
10565
+ const rbHelper = L.raw === RAW_OMIT ? "_rbNoRawBuf" : "_rbBuf";
10566
+ const rb = L.buf && L.raw !== 0 ? `${rbHelper}(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
9469
10567
  if(ctx._fields!==undefined&&ctx._fields.length!==${p}fd)ctx._fields.length=${p}fd` : ""}${sinks.er ? `
9470
- if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
10568
+ if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : L.buf ? `rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
9471
10569
  const markSinks = `${sinks.fd ? `
9472
10570
  ${p}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${sinks.er ? `
9473
10571
  ${p}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
10572
+ const markRaw = L.raw === RAW_OMIT ? `${p}raw=b.rawLen` : L.raw === RAW_CAPTURE ? `const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
9474
10573
  const markBody = L.buf ? `const b=ctx._cstBuf
9475
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
10574
+ ${markRaw}
9476
10575
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
9477
10576
  const l=b.tl;${p}tl=l!==undefined?l.length:0
9478
10577
  ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
9479
10578
  ${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}` : `if(needMark){
9480
10579
  const b=ctx._cstBuf
9481
10580
  if(b!==undefined){
9482
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
10581
+ const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
9483
10582
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
9484
10583
  const l=b.tl;${p}tl=l!==undefined?l.length:0
9485
10584
  }else{
@@ -9586,7 +10685,7 @@ const leaf={_tag:'leaf',value,span:{start:pos,end}}
9586
10685
  const kids=[leaf],rawKids=[leaf],span={start:pos,end}
9587
10686
  EC.e=end
9588
10687
  const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
9589
- ${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
10688
+ ${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,ctx._cstBuf!==undefined&&ctx._cstBuf.noRaw===true?undefined:ctx._cstBuf!==undefined||ctx._cstRawChildren!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
9590
10689
  EC.e=end
9591
10690
  return nd
9592
10691
  }`;
@@ -9608,7 +10707,22 @@ return nd
9608
10707
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
9609
10708
  const fields = flags === 18;
9610
10709
  const collapseChildren = flags === 34;
9611
- const publish = `if(sBuf!==undefined){
10710
+ const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
10711
+ if(sBuf.rawOnly!==true){
10712
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
10713
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
10714
+ else sBuf.single=nd
10715
+ }
10716
+ const rawNd=rawEntry(nd,input,pos,end)
10717
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
10718
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
10719
+ else sBuf.rawSingle=rawNd
10720
+ }else if(sCh!==undefined){
10721
+ sCh.push(nd)
10722
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
10723
+ }` : `if(sBuf!==undefined){
10724
+ if(sBuf.noRaw===true)_pushNodeNoRawBuf(ctx,nd)
10725
+ else{
9612
10726
  if(sBuf.rawOnly!==true){
9613
10727
  if(sBuf.ch!==undefined)sBuf.ch.push(nd)
9614
10728
  else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
@@ -9618,6 +10732,7 @@ const rawNd=rawEntry(nd,input,pos,end)
9618
10732
  if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
9619
10733
  else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
9620
10734
  else sBuf.rawSingle=rawNd
10735
+ }
9621
10736
  }else if(sCh!==undefined){
9622
10737
  sCh.push(nd)
9623
10738
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
@@ -9656,6 +10771,7 @@ return nd
9656
10771
  const wantFields = hasFields || hostCst;
9657
10772
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
9658
10773
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
10774
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
9659
10775
  const ty = q(type);
9660
10776
  const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
9661
10777
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
@@ -9669,7 +10785,12 @@ return nd
9669
10785
  value = `nd=_pfHost!==undefined?_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,st,${tags}):{_tag:'node',type:${ty},span,state:st??null,children:kids}`;
9670
10786
  }
9671
10787
  const collapsible = keepChildren && (hostCst || build === void 0 && proj < 0);
9672
- const openCapture = keepChildren ? `const buf={}
10788
+ const openCapture = omitsRaw ? `const buf={noRaw:true,rawLen:0}
10789
+ ctx._cstBuf=buf
10790
+ ctx._cstChildren=undefined
10791
+ ctx._cstLeaves=undefined
10792
+ ctx._cstRawChildren=undefined
10793
+ ctx._cstTriviaLog=undefined` : keepChildren ? `const buf={}
9673
10794
  ctx._cstBuf=buf
9674
10795
  ctx._cstChildren=undefined
9675
10796
  ctx._cstLeaves=undefined
@@ -9680,7 +10801,10 @@ ctx._cstChildren=undefined
9680
10801
  ctx._cstLeaves=undefined
9681
10802
  ctx._cstRawChildren=undefined
9682
10803
  ctx._cstTriviaLog=undefined`;
9683
- const finishCapture = keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
10804
+ const finishCapture = omitsRaw ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
10805
+ const hostKids=kids
10806
+ const rawKids=EMPTY_CH
10807
+ const tlog=buf.tl??EMPTY_TLOG` : keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
9684
10808
  const hostKids=kids
9685
10809
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
9686
10810
  const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
@@ -9714,7 +10838,7 @@ const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):unde
9714
10838
  let nd
9715
10839
  ${unwrap ? "if(kids.length===1)nd=unwrapChild(kids[0])\nelse " : ""}${collapse ? "if(kids.length===1)nd=kids[0]\nelse " : ""}${collapsible ? `if(_pfHost!==undefined&&_pfHost._parsemanCstCollapse!==undefined&&kids.length===1&&rawKids.length===1&&_pfHost._parsemanCstCollapse(${ty},kids[0],kids,rawKids))nd=kids[0]
9716
10840
  else ` : ""}{${value}}
9717
- ${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
10841
+ ${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,sBuf!==undefined?(sBuf.noRaw===true?undefined:rawEntry(nd,input,pos,end)):sRaw!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
9718
10842
  EC.e=end
9719
10843
  return nd
9720
10844
  }`;
@@ -9732,7 +10856,7 @@ return nd
9732
10856
  }
9733
10857
  const extra = [];
9734
10858
  for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
9735
- const source = `${RUNTIME_PRELUDE}
10859
+ const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
9736
10860
  ${prelude.join("\n")}
9737
10861
  ${skipDefs.join("\n")}
9738
10862
  ${choiceDefs.join("\n")}
@@ -9747,7 +10871,13 @@ _pfHost=host
9747
10871
  function _finish(){
9748
10872
  if(_pfDepth<=0)throw new Error('parseman emitted table assembly frame underflow')
9749
10873
  _pfDepth--
9750
- if(_pfDepth===0)return
10874
+ if(_pfDepth===0){
10875
+ _pfTokInput=undefined
10876
+ _pfTokBody=-1
10877
+ _pfTokValue=undefined
10878
+ _pfTokDispatch=-1
10879
+ return
10880
+ }
9751
10881
  const prior=_pfFrames.pop()
9752
10882
  _pfScan=prior[0]
9753
10883
  _pfHost=prior[1]
@@ -10109,6 +11239,17 @@ function assemble(t, prog, cfg) {
10109
11239
  }
10110
11240
  return recognize;
10111
11241
  }
11242
+ const labelExtraIps = [];
11243
+ for (const s of prog.scans ?? []) {
11244
+ for (const r of s.skip) labelExtraIps.push(r[0]);
11245
+ if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
11246
+ }
11247
+ for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
11248
+ const closureLabels = computeSiteLabels(
11249
+ code,
11250
+ [...Object.values(prog.rules), ...labelExtraIps],
11251
+ hostCst
11252
+ );
10112
11253
  let SCAN = null;
10113
11254
  const memo = /* @__PURE__ */ new Map();
10114
11255
  const reached = /* @__PURE__ */ new Set();
@@ -10154,12 +11295,12 @@ function assemble(t, prog, cfg) {
10154
11295
  return node2;
10155
11296
  };
10156
11297
  }
10157
- function capturedFlatChildren(children2) {
10158
- if (children2.length === 0) return EMPTY_CH;
10159
- if (children2[0] !== void 0) return children2;
11298
+ function capturedFlatChildren(children3) {
11299
+ if (children3.length === 0) return EMPTY_CH;
11300
+ if (children3[0] !== void 0) return children3;
10160
11301
  let first = 1;
10161
- while (first < children2.length && children2[first] === void 0) first++;
10162
- return first === children2.length ? EMPTY_CH : children2.slice(first);
11302
+ while (first < children3.length && children3[first] === void 0) first++;
11303
+ return first === children3.length ? EMPTY_CH : children3.slice(first);
10163
11304
  }
10164
11305
  function childrenOnlyBuildNode(child, build) {
10165
11306
  return (input, pos, ctx) => {
@@ -10354,7 +11495,7 @@ function assemble(t, prog, cfg) {
10354
11495
  const b = ctx._cstBuf;
10355
11496
  if (b !== void 0) {
10356
11497
  const raw = b.raw;
10357
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
11498
+ MRAW = b.noRaw === true ? b.rawLen ?? 0 : raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10358
11499
  const ch2 = b.ch;
10359
11500
  MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10360
11501
  const tl = b.tl;
@@ -10438,6 +11579,31 @@ function assemble(t, prog, cfg) {
10438
11579
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
10439
11580
  return cur;
10440
11581
  }
11582
+ function nextTermBuffered(child, input, cur, ctx) {
11583
+ if (ctx.trivia === void 0) {
11584
+ const v2 = child(input, cur, ctx);
11585
+ if (v2 === FAIL) return -1;
11586
+ TERMV = v2;
11587
+ return EC.e;
11588
+ }
11589
+ const before = ctx._cstBuf;
11590
+ const beforeTl = before.tl;
11591
+ const mTl = beforeTl === void 0 ? 0 : beforeTl.length;
11592
+ const mLog = ctx._triviaLog?.length ?? 0;
11593
+ const mRoot = ctx._rootTriviaLog?.length ?? 0;
11594
+ const scanEnd = skipTrivia(input, cur, ctx);
11595
+ const scanned = ctx._cstBuf;
11596
+ const scannedTl = scanned.tl;
11597
+ const scanTl = scannedTl === void 0 ? 0 : scannedTl.length;
11598
+ const scanLog = ctx._triviaLog?.length ?? 0;
11599
+ const scanRoot = ctx._rootTriviaLog?.length ?? 0;
11600
+ const v = child(input, scanEnd, ctx);
11601
+ if (v === FAIL) return -1;
11602
+ TERMV = v;
11603
+ if (EC.e > scanEnd) return EC.e;
11604
+ rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
11605
+ return cur;
11606
+ }
10441
11607
  function committed3(c) {
10442
11608
  return c._fc === true;
10443
11609
  }
@@ -10708,7 +11874,8 @@ function assemble(t, prog, cfg) {
10708
11874
  target = p;
10709
11875
  } };
10710
11876
  inFlight.set(ip, holder);
10711
- const piece = lower(ip);
11877
+ const op = code[ip];
11878
+ const piece = (op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && closureLabels.at(ip).tri === code[ip + 1] ? link(code[ip + 2]) : lower(ip);
10712
11879
  inFlight.delete(ip);
10713
11880
  holder.set(piece);
10714
11881
  memo.set(ip, piece);
@@ -11160,11 +12327,11 @@ function assemble(t, prog, cfg) {
11160
12327
  }
11161
12328
  case OP_ROUTED: {
11162
12329
  const fb = code[ip + 1];
11163
- const fallback = fb >= 0 ? link(fb) : void 0;
12330
+ const fallback2 = fb >= 0 ? link(fb) : void 0;
11164
12331
  return (input, pos, ctx) => {
11165
12332
  const item = ctx._routed;
11166
12333
  if (item === void 0 || pos !== item.span.start) {
11167
- if (fallback !== void 0) return fallback(input, pos, ctx);
12334
+ if (fallback2 !== void 0) return fallback2(input, pos, ctx);
11168
12335
  ctx._fe = pos;
11169
12336
  ctx._fx = ROUTED_FX;
11170
12337
  return FAIL;
@@ -11451,6 +12618,7 @@ function assemble(t, prog, cfg) {
11451
12618
  const reducer = fused ? code[ip + 1] : -1;
11452
12619
  const projection = reducer < 0 ? ~reducer : -1;
11453
12620
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
12621
+ const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
11454
12622
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
11455
12623
  if (count === 1) return (input, cur, ctx, values, inherited) => {
11456
12624
  cur = r0(input, cur, ctx, inherited);
@@ -11505,7 +12673,7 @@ function assemble(t, prog, cfg) {
11505
12673
  const kid = link(kidIp);
11506
12674
  return (input, cur, ctx, inherited) => {
11507
12675
  ctx._sync = sync ?? inherited;
11508
- return nextTerm(kid, input, cur, ctx);
12676
+ return step(kid, input, cur, ctx);
11509
12677
  };
11510
12678
  }
11511
12679
  const negated = code[kidIp + 1] === 1;
@@ -11590,7 +12758,7 @@ function assemble(t, prog, cfg) {
11590
12758
  const kidIp = code[base + i];
11591
12759
  if (code[kidIp] !== OP_ADJ) {
11592
12760
  const kid = link(kidIp);
11593
- return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
12761
+ return (input, cur, ctx) => step(kid, input, cur, ctx);
11594
12762
  }
11595
12763
  const negated = code[kidIp + 1] === 1;
11596
12764
  const ki = code[kidIp + 2];
@@ -11679,7 +12847,7 @@ function assemble(t, prog, cfg) {
11679
12847
  return (input, pos, ctx) => {
11680
12848
  const v0 = k0(input, pos, ctx);
11681
12849
  if (v0 === FAIL) return FAIL;
11682
- const cur = nextTerm(k1, input, EC.e, ctx);
12850
+ const cur = step(k1, input, EC.e, ctx);
11683
12851
  if (cur < 0) return FAIL;
11684
12852
  EC.e = cur;
11685
12853
  return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
@@ -11689,7 +12857,7 @@ function assemble(t, prog, cfg) {
11689
12857
  return (input, pos, ctx) => {
11690
12858
  const v0 = k0(input, pos, ctx);
11691
12859
  if (v0 === FAIL) return FAIL;
11692
- const cur = nextTerm(k1, input, EC.e, ctx);
12860
+ const cur = step(k1, input, EC.e, ctx);
11693
12861
  if (cur < 0) return FAIL;
11694
12862
  EC.e = cur;
11695
12863
  return [v0, TERMV];
@@ -11698,7 +12866,7 @@ function assemble(t, prog, cfg) {
11698
12866
  return (input, pos, ctx) => {
11699
12867
  const v0 = k0(input, pos, ctx);
11700
12868
  if (v0 === FAIL) return FAIL;
11701
- const cur = nextTerm(k1, input, EC.e, ctx);
12869
+ const cur = step(k1, input, EC.e, ctx);
11702
12870
  if (cur < 0) return FAIL;
11703
12871
  EC.e = cur;
11704
12872
  return void 0;
@@ -11710,10 +12878,10 @@ function assemble(t, prog, cfg) {
11710
12878
  return (input, pos, ctx) => {
11711
12879
  const v0 = k0(input, pos, ctx);
11712
12880
  if (v0 === FAIL) return FAIL;
11713
- let cur = nextTerm(k1, input, EC.e, ctx);
12881
+ let cur = step(k1, input, EC.e, ctx);
11714
12882
  if (cur < 0) return FAIL;
11715
12883
  const v1 = TERMV;
11716
- cur = nextTerm(k2, input, cur, ctx);
12884
+ cur = step(k2, input, cur, ctx);
11717
12885
  if (cur < 0) return FAIL;
11718
12886
  EC.e = cur;
11719
12887
  return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
@@ -11723,10 +12891,10 @@ function assemble(t, prog, cfg) {
11723
12891
  return (input, pos, ctx) => {
11724
12892
  const v0 = k0(input, pos, ctx);
11725
12893
  if (v0 === FAIL) return FAIL;
11726
- let cur = nextTerm(k1, input, EC.e, ctx);
12894
+ let cur = step(k1, input, EC.e, ctx);
11727
12895
  if (cur < 0) return FAIL;
11728
12896
  const v1 = TERMV;
11729
- cur = nextTerm(k2, input, cur, ctx);
12897
+ cur = step(k2, input, cur, ctx);
11730
12898
  if (cur < 0) return FAIL;
11731
12899
  EC.e = cur;
11732
12900
  return [v0, v1, TERMV];
@@ -11735,9 +12903,9 @@ function assemble(t, prog, cfg) {
11735
12903
  return (input, pos, ctx) => {
11736
12904
  const v0 = k0(input, pos, ctx);
11737
12905
  if (v0 === FAIL) return FAIL;
11738
- let cur = nextTerm(k1, input, EC.e, ctx);
12906
+ let cur = step(k1, input, EC.e, ctx);
11739
12907
  if (cur < 0) return FAIL;
11740
- cur = nextTerm(k2, input, cur, ctx);
12908
+ cur = step(k2, input, cur, ctx);
11741
12909
  if (cur < 0) return FAIL;
11742
12910
  EC.e = cur;
11743
12911
  return void 0;
@@ -11745,43 +12913,43 @@ function assemble(t, prog, cfg) {
11745
12913
  }
11746
12914
  const block = (count, k0, k1, k2, k3, next) => {
11747
12915
  if (count === 1) return (input, cur, ctx, values) => {
11748
- cur = nextTerm(k0, input, cur, ctx);
12916
+ cur = step(k0, input, cur, ctx);
11749
12917
  if (cur < 0) return -1;
11750
12918
  if (values !== void 0) values.push(TERMV);
11751
12919
  return next === void 0 ? cur : next(input, cur, ctx, values);
11752
12920
  };
11753
12921
  if (count === 2) return (input, cur, ctx, values) => {
11754
- cur = nextTerm(k0, input, cur, ctx);
12922
+ cur = step(k0, input, cur, ctx);
11755
12923
  if (cur < 0) return -1;
11756
12924
  if (values !== void 0) values.push(TERMV);
11757
- cur = nextTerm(k1, input, cur, ctx);
12925
+ cur = step(k1, input, cur, ctx);
11758
12926
  if (cur < 0) return -1;
11759
12927
  if (values !== void 0) values.push(TERMV);
11760
12928
  return next === void 0 ? cur : next(input, cur, ctx, values);
11761
12929
  };
11762
12930
  if (count === 3) return (input, cur, ctx, values) => {
11763
- cur = nextTerm(k0, input, cur, ctx);
12931
+ cur = step(k0, input, cur, ctx);
11764
12932
  if (cur < 0) return -1;
11765
12933
  if (values !== void 0) values.push(TERMV);
11766
- cur = nextTerm(k1, input, cur, ctx);
12934
+ cur = step(k1, input, cur, ctx);
11767
12935
  if (cur < 0) return -1;
11768
12936
  if (values !== void 0) values.push(TERMV);
11769
- cur = nextTerm(k2, input, cur, ctx);
12937
+ cur = step(k2, input, cur, ctx);
11770
12938
  if (cur < 0) return -1;
11771
12939
  if (values !== void 0) values.push(TERMV);
11772
12940
  return next === void 0 ? cur : next(input, cur, ctx, values);
11773
12941
  };
11774
12942
  return (input, cur, ctx, values) => {
11775
- cur = nextTerm(k0, input, cur, ctx);
12943
+ cur = step(k0, input, cur, ctx);
11776
12944
  if (cur < 0) return -1;
11777
12945
  if (values !== void 0) values.push(TERMV);
11778
- cur = nextTerm(k1, input, cur, ctx);
12946
+ cur = step(k1, input, cur, ctx);
11779
12947
  if (cur < 0) return -1;
11780
12948
  if (values !== void 0) values.push(TERMV);
11781
- cur = nextTerm(k2, input, cur, ctx);
12949
+ cur = step(k2, input, cur, ctx);
11782
12950
  if (cur < 0) return -1;
11783
12951
  if (values !== void 0) values.push(TERMV);
11784
- cur = nextTerm(k3, input, cur, ctx);
12952
+ cur = step(k3, input, cur, ctx);
11785
12953
  if (cur < 0) return -1;
11786
12954
  if (values !== void 0) values.push(TERMV);
11787
12955
  return next === void 0 ? cur : next(input, cur, ctx, values);
@@ -11952,6 +13120,13 @@ function assemble(t, prog, cfg) {
11952
13120
  if (n === 2 || n === 3) {
11953
13121
  const a0 = link(code[base]), a1 = link(code[base + 1]);
11954
13122
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13123
+ const predecide = !hostCst && !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13124
+ const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13125
+ const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13126
+ const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
13127
+ const p0 = p0ip < 0 ? void 0 : scalarFor(p0ip);
13128
+ const p1 = p1ip < 0 ? void 0 : scalarFor(p1ip);
13129
+ const p2 = p2ip < 0 ? void 0 : scalarFor(p2ip);
11955
13130
  const e0 = fx[code[base + n]];
11956
13131
  const e1 = fx[code[base + n + 1]];
11957
13132
  const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
@@ -11981,7 +13156,10 @@ function assemble(t, prog, cfg) {
11981
13156
  let acc;
11982
13157
  let best = pos;
11983
13158
  if (c < 128) {
11984
- const bits = mask[c < 0 ? 128 : c];
13159
+ let bits = mask[c < 0 ? 128 : c];
13160
+ if ((bits & 1) !== 0 && p0 !== void 0 && p0(input, pos) < 0) bits &= ~1;
13161
+ if ((bits & 2) !== 0 && p1 !== void 0 && p1(input, pos) < 0) bits &= ~2;
13162
+ if ((bits & 4) !== 0 && p2 !== void 0 && p2(input, pos) < 0) bits &= ~4;
11985
13163
  let prev = 0;
11986
13164
  if ((bits & 1) !== 0) {
11987
13165
  ctx._fc = false;
@@ -12044,7 +13222,7 @@ function assemble(t, prog, cfg) {
12044
13222
  ctx._fx = acc ?? choiceFx;
12045
13223
  return FAIL;
12046
13224
  }
12047
- if (g0 === null || classHas2(g0, c)) {
13225
+ if ((g0 === null || classHas2(g0, c)) && (p0 === void 0 || p0(input, pos) >= 0)) {
12048
13226
  ctx._fc = false;
12049
13227
  const v = a0(input, pos, ctx);
12050
13228
  if (v !== FAIL) return v;
@@ -12060,7 +13238,7 @@ function assemble(t, prog, cfg) {
12060
13238
  }
12061
13239
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12062
13240
  } else if (best === pos) acc = accSet(e0, acc);
12063
- if (g1 === null || classHas2(g1, c)) {
13241
+ if ((g1 === null || classHas2(g1, c)) && (p1 === void 0 || p1(input, pos) >= 0)) {
12064
13242
  ctx._fc = false;
12065
13243
  const v = a1(input, pos, ctx);
12066
13244
  if (v !== FAIL) return v;
@@ -12077,7 +13255,7 @@ function assemble(t, prog, cfg) {
12077
13255
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12078
13256
  } else if (best === pos) acc = accSet(e1, acc);
12079
13257
  if (n === 3) {
12080
- if (g2 === null || classHas2(g2, c)) {
13258
+ if ((g2 === null || classHas2(g2, c)) && (p2 === void 0 || p2(input, pos) >= 0)) {
12081
13259
  ctx._fc = false;
12082
13260
  const v = a2(input, pos, ctx);
12083
13261
  if (v !== FAIL) return v;
@@ -12650,20 +13828,14 @@ function assemble(t, prog, cfg) {
12650
13828
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
12651
13829
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
12652
13830
  const rawOnly = !keepChildren;
13831
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
12653
13832
  return (input, pos, ctx) => {
12654
13833
  const host = HOST;
12655
13834
  const sCh = ctx._cstChildren;
12656
- const sLv = ctx._cstLeaves;
12657
- const sRaw = ctx._cstRawChildren;
12658
- const sTl = ctx._cstTriviaLog;
12659
13835
  const sCap = ctx.captureTrivia;
12660
13836
  const sBuf = ctx._cstBuf;
12661
- const buf = rawOnly ? { rawOnly: true } : {};
13837
+ const buf = rawOnly ? { rawOnly: true } : omitsRaw ? { noRaw: true, rawLen: 0 } : {};
12662
13838
  ctx._cstBuf = buf;
12663
- ctx._cstChildren = void 0;
12664
- ctx._cstLeaves = void 0;
12665
- ctx._cstRawChildren = void 0;
12666
- ctx._cstTriviaLog = void 0;
12667
13839
  ctx.captureTrivia = captureWide;
12668
13840
  const savedFields = ctx._fields;
12669
13841
  ctx._fields = wantFields ? [] : void 0;
@@ -12678,13 +13850,9 @@ function assemble(t, prog, cfg) {
12678
13850
  if (structural) ctx._triviaCaptureMask = savedMask;
12679
13851
  const kids = rawOnly ? EMPTY_CH : buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
12680
13852
  const hostKids = kids;
12681
- const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
13853
+ const rawKids = omitsRaw ? EMPTY_CH : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
12682
13854
  const tlog = buf.tl ?? EMPTY_TLOG;
12683
13855
  ctx._cstBuf = sBuf;
12684
- ctx._cstChildren = sCh;
12685
- ctx._cstLeaves = sLv;
12686
- ctx._cstRawChildren = sRaw;
12687
- ctx._cstTriviaLog = sTl;
12688
13856
  ctx.captureTrivia = sCap;
12689
13857
  if (v === FAIL) return FAIL;
12690
13858
  const end = EC.e;
@@ -12775,6 +13943,34 @@ function assemble(t, prog, cfg) {
12775
13943
  rawScalarSpecs.add(code[child + 1]);
12776
13944
  scalarFor(child);
12777
13945
  }
13946
+ } else if (code[ip] === OP_CHOICE && !disp[code[ip + 1]].exclusive) {
13947
+ const n = code[ip + 2];
13948
+ for (let i = 0; i < n; i++) {
13949
+ const armIp = code[ip + 4 + i];
13950
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
13951
+ if (n === 2 || n === 3) {
13952
+ if (child >= 0) scalarFor(child);
13953
+ continue;
13954
+ }
13955
+ if (child >= 0) {
13956
+ const spec = k[code[child + 1]];
13957
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
13958
+ scalarFor(child);
13959
+ continue;
13960
+ }
13961
+ }
13962
+ const family = leadingLiteralFamily(code, k, armIp);
13963
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
13964
+ const value = k[code[terminal + 1]];
13965
+ return typeof value === "string" && value.length >= 2;
13966
+ })) {
13967
+ for (const terminal of family) scalarFor(terminal);
13968
+ }
13969
+ const sequence6 = leadingScalarSequence(code, armIp);
13970
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
13971
+ for (const terminal of sequence6.terminals) scalarFor(terminal);
13972
+ }
13973
+ }
12778
13974
  }
12779
13975
  }
12780
13976
  const notChild = scalarTerminalNotChild(code, ip);
@@ -13196,7 +14392,7 @@ function emitAssemblies(prog, cfgs) {
13196
14392
  seen.add(key);
13197
14393
  let em;
13198
14394
  try {
13199
- em = emitAssemblySource(t, prog, cfg, extraIps);
14395
+ em = emitAssemblySource(t, prog, cfg, extraIps, true);
13200
14396
  } catch (e) {
13201
14397
  if (e instanceof Unemittable) continue;
13202
14398
  throw e;
@@ -13655,10 +14851,10 @@ function boundaryMatches(boundary, ch2) {
13655
14851
  if (/\s/.test(ch2)) return true;
13656
14852
  continue;
13657
14853
  }
13658
- const range = /^(.|\\u[0-9a-f]{4})-(.|\\u[0-9a-f]{4})$/.exec(m);
13659
- if (range !== null) {
14854
+ const range2 = /^(.|\\u[0-9a-f]{4})-(.|\\u[0-9a-f]{4})$/.exec(m);
14855
+ if (range2 !== null) {
13660
14856
  const dec = (t) => t.startsWith("\\u") ? parseInt(t.slice(2), 16) : t.codePointAt(0);
13661
- if (cp >= dec(range[1]) && cp <= dec(range[2])) return true;
14857
+ if (cp >= dec(range2[1]) && cp <= dec(range2[2])) return true;
13662
14858
  continue;
13663
14859
  }
13664
14860
  if (m === ch2) return true;
@@ -14732,7 +15928,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
14732
15928
  };
14733
15929
  const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
14734
15930
  const artifact = closureArtifact(prog);
14735
- const entry = tableRules(artifact)[ENTRY];
15931
+ const entry = tableRules(prog)[ENTRY];
14736
15932
  const offered = opts.fnSources ?? mapFnSources;
14737
15933
  const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
14738
15934
  const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
@@ -14781,106 +15977,6 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
14781
15977
  };
14782
15978
  }
14783
15979
 
14784
- // src/analysis/commitment.ts
14785
- function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
14786
- if (seen.has(p)) return false;
14787
- seen.add(p);
14788
- const d = p._def;
14789
- switch (d.tag) {
14790
- case "node":
14791
- return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
14792
- case "lazy": {
14793
- try {
14794
- return hasDirectBuildDef(d.thunk(), seen);
14795
- } catch {
14796
- return false;
14797
- }
14798
- }
14799
- case "grammar":
14800
- case "trivia":
14801
- case "token":
14802
- case "leaf":
14803
- case "label":
14804
- case "field":
14805
- case "optional":
14806
- case "many":
14807
- case "oneOrMore":
14808
- case "attempt":
14809
- case "not":
14810
- case "peek":
14811
- case "withCtx":
14812
- case "expect":
14813
- case "transform":
14814
- return hasDirectBuildDef(d.parser, seen);
14815
- case "sequence":
14816
- case "choice":
14817
- return d.parsers.some((x) => hasDirectBuildDef(x, seen));
14818
- case "dispatch":
14819
- return hasDirectBuildDef(d.selector, seen) || d.cases.some((x) => hasDirectBuildDef(x.parser, seen)) || (d.matchers ? d.matchers.some((x) => hasDirectBuildDef(x.parser, seen)) : false) || (d.otherwise ? hasDirectBuildDef(d.otherwise, seen) : false);
14820
- case "sepBy":
14821
- return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
14822
- case "scanTo":
14823
- return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen));
14824
- case "recover":
14825
- return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
14826
- case "routed":
14827
- return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
14828
- default:
14829
- return false;
14830
- }
14831
- }
14832
- function hasSemanticReduction(roots, externalRefs) {
14833
- const seen = /* @__PURE__ */ new Set();
14834
- const visit = (parser2) => {
14835
- if (seen.has(parser2)) return false;
14836
- seen.add(parser2);
14837
- const def = parser2._def;
14838
- if (def.tag === "transform" && !def.recognitionOnly) return true;
14839
- if (def.tag === "choice" && def.gates.some(Boolean)) return true;
14840
- if (def.tag === "guard" || def.tag === "withCtx") return true;
14841
- if (def.tag === "node" && def.build !== void 0) return true;
14842
- if (def.tag === "lazy") {
14843
- if (externalRefs?.has(parser2)) return false;
14844
- try {
14845
- return visit(def.thunk());
14846
- } catch {
14847
- return true;
14848
- }
14849
- }
14850
- return childrenOf2(def).some(visit);
14851
- };
14852
- return roots.some(visit);
14853
- }
14854
- function classifyRuleMap(ruleMap) {
14855
- const externalRefs = /* @__PURE__ */ new Set();
14856
- const scanned = /* @__PURE__ */ new Set();
14857
- const scanExternal = (p) => {
14858
- if (scanned.has(p)) return;
14859
- scanned.add(p);
14860
- const def = p._def;
14861
- if (def.tag === "lazy") {
14862
- let resolved;
14863
- try {
14864
- resolved = def.thunk();
14865
- } catch {
14866
- resolved = void 0;
14867
- }
14868
- if (resolved === void 0) {
14869
- if (p._ruleName) externalRefs.add(p);
14870
- return;
14871
- }
14872
- scanExternal(resolved);
14873
- return;
14874
- }
14875
- for (const child of childrenOf2(def)) scanExternal(child);
14876
- };
14877
- for (const [, rule] of ruleMap) scanExternal(rule);
14878
- return {
14879
- hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
14880
- isRecognitionOnly: !hasSemanticReduction(ruleMap.map(([, rule]) => rule), externalRefs)
14881
- };
14882
- }
14883
-
14884
15980
  // src/combinators/withCtx.ts
14885
15981
  function withCtx(extra, combinator) {
14886
15982
  const meta = {
@@ -15023,7 +16119,7 @@ function evalRuleMapIR(ir) {
15023
16119
  l._def.fnSrc = src;
15024
16120
  return l;
15025
16121
  };
15026
- const _nd = (type, child, src, opts, staticError, sigSrc, buildImports) => {
16122
+ const _nd = (type, child, src, opts, staticError, sigSrc, buildImports, rawUnused) => {
15027
16123
  if (staticError !== void 0 && staticError.length > 0) {
15028
16124
  throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
15029
16125
  }
@@ -15033,6 +16129,7 @@ function evalRuleMapIR(ir) {
15033
16129
  n._def.buildSrc = src;
15034
16130
  if (staticError !== void 0) n._def.buildStaticError = staticError;
15035
16131
  if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
16132
+ if (rawUnused === true) n._def.buildRawUnused = true;
15036
16133
  if (buildImports !== void 0) n._def.buildImports = buildImports;
15037
16134
  return n;
15038
16135
  };
@@ -15425,12 +16522,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
15425
16522
  }
15426
16523
  if (def.buildSrc !== void 0) {
15427
16524
  const tail = [];
15428
- if (def.buildStaticError !== void 0 || def.buildSigSrc !== void 0 || def.buildImports !== void 0) {
16525
+ if (def.buildStaticError !== void 0 || def.buildSigSrc !== void 0 || def.buildImports !== void 0 || def.buildRawUnused === true) {
15429
16526
  if (!opts) tail.push("undefined");
15430
16527
  tail.push(def.buildStaticError === void 0 ? "undefined" : JSON.stringify(def.buildStaticError));
15431
16528
  }
15432
- if (def.buildSigSrc !== void 0 || def.buildImports !== void 0) tail.push(def.buildSigSrc === void 0 ? "undefined" : JSON.stringify(def.buildSigSrc));
15433
- if (def.buildImports !== void 0) tail.push(JSON.stringify(def.buildImports));
16529
+ if (def.buildSigSrc !== void 0 || def.buildImports !== void 0 || def.buildRawUnused === true) tail.push(def.buildSigSrc === void 0 ? "undefined" : JSON.stringify(def.buildSigSrc));
16530
+ if (def.buildImports !== void 0 || def.buildRawUnused === true) tail.push(def.buildImports === void 0 ? "undefined" : JSON.stringify(def.buildImports));
16531
+ if (def.buildRawUnused === true) tail.push("true");
15434
16532
  const trailing = tail.length > 0 ? `, ${tail.join(", ")}` : "";
15435
16533
  return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${trailing})`;
15436
16534
  }
@@ -15499,7 +16597,7 @@ function compileRuleMapRunnable(ruleMap, opts = {}) {
15499
16597
  hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
15500
16598
  reflection: collectGrammarReflection(ruleMap),
15501
16599
  ...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
15502
- rules: tableRules(artifact),
16600
+ rules: tableRules(prog),
15503
16601
  prog: artifact
15504
16602
  };
15505
16603
  }
@@ -15571,13 +16669,13 @@ function compileRuleMap(ruleMap, opts = {}) {
15571
16669
  hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
15572
16670
  reflection: collectGrammarReflection(ruleMap),
15573
16671
  ...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
15574
- rules: tableRules(artifact),
16672
+ rules: tableRules(prog),
15575
16673
  prog: artifact
15576
16674
  };
15577
16675
  }
15578
16676
 
15579
16677
  // src/version.ts
15580
- var PARSEMAN_VERSION = "0.49.0";
16678
+ var PARSEMAN_VERSION = "0.50.0";
15581
16679
 
15582
16680
  // src/compiler/compile-linkable-table.ts
15583
16681
  function isLocal(rule) {
@@ -15653,16 +16751,16 @@ function normalizeCstCollapse(collapse) {
15653
16751
  }
15654
16752
  return typeof collapse === "function" ? collapse : void 0;
15655
16753
  }
15656
- function buildCstNode(type, children2, _fields, span, _rawChildren, _triviaLog, state, tags) {
15657
- return tags !== void 0 && tags.length > 0 ? { _tag: "node", type, tags, span: { ...span }, state: state ?? null, children: [...children2] } : { _tag: "node", type, span: { ...span }, state: state ?? null, children: [...children2] };
16754
+ function buildCstNode(type, children3, _fields, span, _rawChildren, _triviaLog, state, tags) {
16755
+ return tags !== void 0 && tags.length > 0 ? { _tag: "node", type, tags, span: { ...span }, state: state ?? null, children: [...children3] } : { _tag: "node", type, span: { ...span }, state: state ?? null, children: [...children3] };
15658
16756
  }
15659
- function cstBuildHost(typeOrOptions, children2, _fields, span, rawChildren, triviaLog, state, _tags) {
16757
+ function cstBuildHost(typeOrOptions, children3, _fields, span, rawChildren, triviaLog, state, _tags) {
15660
16758
  if (typeof typeOrOptions === "string") {
15661
- return buildCstNode(typeOrOptions, children2 ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
16759
+ return buildCstNode(typeOrOptions, children3 ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
15662
16760
  }
15663
16761
  const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
15664
16762
  const materializeTags = typeOrOptions?.tags === true;
15665
- const host = (type, children3, fields, span2, rawChildren2, triviaLog2, state2, tags) => buildCstNode(type, children3 ?? [], fields, span2, rawChildren2, triviaLog2, state2, materializeTags ? tags : void 0);
16763
+ const host = (type, children4, fields, span2, rawChildren2, triviaLog2, state2, tags) => buildCstNode(type, children4 ?? [], fields, span2, rawChildren2, triviaLog2, state2, materializeTags ? tags : void 0);
15666
16764
  host._parsemanCstOutput = true;
15667
16765
  if (collapse) host._parsemanCstCollapse = collapse;
15668
16766
  return host;
@@ -15818,39 +16916,39 @@ function directBuilderBindings(src) {
15818
16916
  if (selfName?.type === "Identifier" && typeof selfName.name === "string") allowed.add(selfName.name);
15819
16917
  const structural = /* @__PURE__ */ new Set();
15820
16918
  const free = /* @__PURE__ */ new Set();
15821
- const reportUnsupportedNode = (ast) => {
15822
- structural.add(`unsupported ${ast.type}`);
16919
+ const reportUnsupportedNode = (ast2) => {
16920
+ structural.add(`unsupported ${ast2.type}`);
15823
16921
  };
15824
- const read = (ast, allowedNames) => {
15825
- if (typeof ast.name === "string" && allowedNames.has(ast.name)) return;
15826
- if (ast.name === "arguments") {
16922
+ const read = (ast2, allowedNames) => {
16923
+ if (typeof ast2.name === "string" && allowedNames.has(ast2.name)) return;
16924
+ if (ast2.name === "arguments") {
15827
16925
  structural.add("unsupported arguments");
15828
16926
  return;
15829
16927
  }
15830
- if (typeof ast.name === "string") free.add(ast.name);
16928
+ if (typeof ast2.name === "string") free.add(ast2.name);
15831
16929
  else structural.add("unsupported identifier");
15832
16930
  };
15833
16931
  const expression = (node2, allowedNames) => {
15834
- const ast = astChild(node2);
15835
- if (!ast) return;
15836
- switch (ast.type) {
16932
+ const ast2 = astChild(node2);
16933
+ if (!ast2) return;
16934
+ switch (ast2.type) {
15837
16935
  case "Literal":
15838
16936
  return;
15839
16937
  case "Identifier":
15840
- read(ast, allowedNames);
16938
+ read(ast2, allowedNames);
15841
16939
  return;
15842
16940
  case "ParenthesizedExpression":
15843
16941
  case "ChainExpression":
15844
16942
  case "TSAsExpression":
15845
16943
  case "TSTypeAssertion":
15846
16944
  case "TSNonNullExpression":
15847
- expression(ast.expression, allowedNames);
16945
+ expression(ast2.expression, allowedNames);
15848
16946
  return;
15849
16947
  case "ArrayExpression":
15850
- for (const element of astArray(ast.elements)) expression(element, allowedNames);
16948
+ for (const element of astArray(ast2.elements)) expression(element, allowedNames);
15851
16949
  return;
15852
16950
  case "ObjectExpression":
15853
- for (const property of astArray(ast.properties)) {
16951
+ for (const property of astArray(ast2.properties)) {
15854
16952
  if (property.type === "SpreadElement") {
15855
16953
  expression(property.argument, allowedNames);
15856
16954
  continue;
@@ -15864,109 +16962,109 @@ function directBuilderBindings(src) {
15864
16962
  }
15865
16963
  return;
15866
16964
  case "MemberExpression":
15867
- expression(ast.object, allowedNames);
15868
- if (ast.computed === true) expression(ast.property, allowedNames);
16965
+ expression(ast2.object, allowedNames);
16966
+ if (ast2.computed === true) expression(ast2.property, allowedNames);
15869
16967
  return;
15870
16968
  case "CallExpression":
15871
16969
  case "NewExpression":
15872
- expression(ast.callee, allowedNames);
15873
- for (const argument of astArray(ast.arguments)) expression(argument, allowedNames);
16970
+ expression(ast2.callee, allowedNames);
16971
+ for (const argument of astArray(ast2.arguments)) expression(argument, allowedNames);
15874
16972
  return;
15875
16973
  case "UnaryExpression":
15876
16974
  case "UpdateExpression":
15877
- expression(ast.argument, allowedNames);
16975
+ expression(ast2.argument, allowedNames);
15878
16976
  return;
15879
16977
  case "BinaryExpression":
15880
16978
  case "LogicalExpression":
15881
16979
  case "AssignmentExpression":
15882
- expression(ast.left, allowedNames);
15883
- expression(ast.right, allowedNames);
16980
+ expression(ast2.left, allowedNames);
16981
+ expression(ast2.right, allowedNames);
15884
16982
  return;
15885
16983
  case "ConditionalExpression":
15886
- expression(ast.test, allowedNames);
15887
- expression(ast.consequent, allowedNames);
15888
- expression(ast.alternate, allowedNames);
16984
+ expression(ast2.test, allowedNames);
16985
+ expression(ast2.consequent, allowedNames);
16986
+ expression(ast2.alternate, allowedNames);
15889
16987
  return;
15890
16988
  case "SequenceExpression":
15891
- for (const value of astArray(ast.expressions)) expression(value, allowedNames);
16989
+ for (const value of astArray(ast2.expressions)) expression(value, allowedNames);
15892
16990
  return;
15893
16991
  case "TemplateLiteral":
15894
- for (const value of astArray(ast.expressions)) expression(value, allowedNames);
16992
+ for (const value of astArray(ast2.expressions)) expression(value, allowedNames);
15895
16993
  return;
15896
16994
  case "SpreadElement":
15897
- expression(ast.argument, allowedNames);
16995
+ expression(ast2.argument, allowedNames);
15898
16996
  return;
15899
16997
  case "ArrowFunctionExpression": {
15900
16998
  const nested = new Set(allowedNames);
15901
- for (const param of astArray(ast.params)) {
16999
+ for (const param of astArray(ast2.params)) {
15902
17000
  if (param.type !== "Identifier" || typeof param.name !== "string") {
15903
17001
  reportUnsupportedNode(param);
15904
17002
  continue;
15905
17003
  }
15906
17004
  nested.add(param.name);
15907
17005
  }
15908
- const nestedBody = astChild(ast.body);
17006
+ const nestedBody = astChild(ast2.body);
15909
17007
  if (nestedBody?.type === "BlockStatement") {
15910
17008
  statement(nestedBody, nested);
15911
17009
  return;
15912
17010
  }
15913
- expression(ast.body, nested);
17011
+ expression(ast2.body, nested);
15914
17012
  return;
15915
17013
  }
15916
17014
  default:
15917
- reportUnsupportedNode(ast);
17015
+ reportUnsupportedNode(ast2);
15918
17016
  return;
15919
17017
  }
15920
17018
  };
15921
17019
  const statement = (node2, names) => {
15922
- const ast = astChild(node2);
15923
- if (!ast) return;
15924
- switch (ast.type) {
17020
+ const ast2 = astChild(node2);
17021
+ if (!ast2) return;
17022
+ switch (ast2.type) {
15925
17023
  case "VariableDeclaration":
15926
- for (const d of astArray(ast.declarations)) {
17024
+ for (const d of astArray(ast2.declarations)) {
15927
17025
  expression(d.init, names);
15928
17026
  const idAst = astChild(d.id);
15929
17027
  if (idAst?.type === "Identifier" && typeof idAst.name === "string") names.add(idAst.name);
15930
- else reportUnsupportedNode(idAst ?? ast);
17028
+ else reportUnsupportedNode(idAst ?? ast2);
15931
17029
  }
15932
17030
  return;
15933
17031
  case "ReturnStatement":
15934
- expression(ast.argument, names);
17032
+ expression(ast2.argument, names);
15935
17033
  return;
15936
17034
  case "ExpressionStatement":
15937
- expression(ast.expression, names);
17035
+ expression(ast2.expression, names);
15938
17036
  return;
15939
17037
  case "ThrowStatement":
15940
- expression(ast.argument, names);
17038
+ expression(ast2.argument, names);
15941
17039
  return;
15942
17040
  case "IfStatement":
15943
- expression(ast.test, names);
15944
- statement(ast.consequent, new Set(names));
15945
- if (ast.alternate) statement(ast.alternate, new Set(names));
17041
+ expression(ast2.test, names);
17042
+ statement(ast2.consequent, new Set(names));
17043
+ if (ast2.alternate) statement(ast2.alternate, new Set(names));
15946
17044
  return;
15947
17045
  case "ForStatement": {
15948
17046
  const inner = new Set(names);
15949
- if (ast.init) {
15950
- const initAst = astChild(ast.init);
17047
+ if (ast2.init) {
17048
+ const initAst = astChild(ast2.init);
15951
17049
  if (initAst?.type === "VariableDeclaration") statement(initAst, inner);
15952
17050
  else expression(initAst, inner);
15953
17051
  }
15954
- if (ast.test) expression(ast.test, inner);
15955
- if (ast.update) expression(ast.update, inner);
15956
- statement(ast.body, inner);
17052
+ if (ast2.test) expression(ast2.test, inner);
17053
+ if (ast2.update) expression(ast2.update, inner);
17054
+ statement(ast2.body, inner);
15957
17055
  return;
15958
17056
  }
15959
17057
  case "ForOfStatement":
15960
17058
  case "ForInStatement": {
15961
17059
  const inner = new Set(names);
15962
- statement(ast.left, inner);
15963
- expression(ast.right, names);
15964
- statement(ast.body, inner);
17060
+ statement(ast2.left, inner);
17061
+ expression(ast2.right, names);
17062
+ statement(ast2.body, inner);
15965
17063
  return;
15966
17064
  }
15967
17065
  case "BlockStatement": {
15968
17066
  const inner = new Set(names);
15969
- for (const s of astArray(ast.body)) statement(s, inner);
17067
+ for (const s of astArray(ast2.body)) statement(s, inner);
15970
17068
  return;
15971
17069
  }
15972
17070
  case "BreakStatement":
@@ -15974,7 +17072,7 @@ function directBuilderBindings(src) {
15974
17072
  case "EmptyStatement":
15975
17073
  return;
15976
17074
  default:
15977
- reportUnsupportedNode(ast);
17075
+ reportUnsupportedNode(ast2);
15978
17076
  return;
15979
17077
  }
15980
17078
  };
@@ -16413,6 +17511,7 @@ function exprToCombi(node2, scope, code, mfs) {
16413
17511
  try {
16414
17512
  const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
16415
17513
  if (combi._def.tag === "node" && buildSrc !== void 0) {
17514
+ const authorDeclaredBuildArity = opts?.buildArity !== void 0;
16416
17515
  combi._def.buildSrc = buildSrc;
16417
17516
  if (explicitType !== void 0 && firstArg.type === "Identifier") {
16418
17517
  combi._def.typeSrc = firstArg.name;
@@ -16427,6 +17526,9 @@ function exprToCombi(node2, scope, code, mfs) {
16427
17526
  if (resolved.reason !== void 0) combi._def.buildArityUnresolved = resolved.reason;
16428
17527
  }
16429
17528
  const analysisSrc = combi._def.buildSigSrc ?? buildSrc;
17529
+ if (!authorDeclaredBuildArity && confirmedBuildParamUnused(analysisSrc, 3)) {
17530
+ combi._def.buildRawUnused = true;
17531
+ }
16430
17532
  const report = directBuilderBindings(analysisSrc);
16431
17533
  const isInlineBuilder = combi._def.buildSigSrc === void 0;
16432
17534
  const carriedImports = [];
@@ -16980,8 +18082,8 @@ var SCOPE_TYPES = /* @__PURE__ */ new Set([
16980
18082
  "ClassExpression",
16981
18083
  "StaticBlock"
16982
18084
  ]);
16983
- function newScope(start, end, parent, isFunction) {
16984
- const s = { start, end, bindings: /* @__PURE__ */ new Map(), children: [], parent, isFunction };
18085
+ function newScope(start, end, parent, isFunction2) {
18086
+ const s = { start, end, bindings: /* @__PURE__ */ new Map(), children: [], parent, isFunction: isFunction2 };
16985
18087
  parent?.children.push(s);
16986
18088
  return s;
16987
18089
  }
@@ -17567,6 +18669,456 @@ function findFreeIdentifiers(code, filename) {
17567
18669
  }).map(({ name, line, column, enclosing }) => ({ name, line, column, enclosing }));
17568
18670
  }
17569
18671
 
18672
+ // src/plugin/entry-supercompiler.ts
18673
+ import { parseSync as parseSync4 } from "oxc-parser";
18674
+ var PIECE = /^_pf(\d+)$/;
18675
+ var WRAP = "function __parseman_supercompile__(){\n";
18676
+ var SUFFIX = "\n}";
18677
+ function ast(value) {
18678
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
18679
+ }
18680
+ function nodes(value) {
18681
+ return Array.isArray(value) ? value.filter((v) => ast(v) !== void 0) : [];
18682
+ }
18683
+ function nameOf(node2) {
18684
+ return node2?.type === "Identifier" && typeof node2.name === "string" ? node2.name : void 0;
18685
+ }
18686
+ function range(node2) {
18687
+ if (typeof node2.start !== "number" || typeof node2.end !== "number") throw new Error("entry supercompiler: AST node without range");
18688
+ return { start: node2.start - WRAP.length, end: node2.end - WRAP.length };
18689
+ }
18690
+ function children2(node2) {
18691
+ const out = [];
18692
+ for (const [key, value] of Object.entries(node2)) {
18693
+ if (key === "type" || key === "start" || key === "end") continue;
18694
+ if (Array.isArray(value)) {
18695
+ for (const child of value) {
18696
+ const c = ast(child);
18697
+ if (c !== void 0) out.push(c);
18698
+ }
18699
+ } else {
18700
+ const c = ast(value);
18701
+ if (c !== void 0) out.push(c);
18702
+ }
18703
+ }
18704
+ return out;
18705
+ }
18706
+ function isFunction(node2) {
18707
+ return node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression";
18708
+ }
18709
+ function isDirectCallUse(call, parent, statement) {
18710
+ if (parent === void 0) return false;
18711
+ if (parent.type === "VariableDeclarator") {
18712
+ const declarations = statement.type === "VariableDeclaration" ? nodes(statement.declarations) : [];
18713
+ return declarations.length === 1 && declarations[0] === parent && parent.init === call;
18714
+ }
18715
+ if (parent.type === "AssignmentExpression") {
18716
+ return statement.type === "ExpressionStatement" && statement.expression === parent && nameOf(ast(parent.left)) !== void 0 && parent.right === call && parent.operator === "=";
18717
+ }
18718
+ if (parent.type === "ReturnStatement") return statement === parent && parent.argument === call;
18719
+ return false;
18720
+ }
18721
+ function isListStatement(statement, parent) {
18722
+ if (parent?.type === "BlockStatement") return nodes(parent.body).includes(statement);
18723
+ if (parent?.type === "SwitchCase") return nodes(parent.consequent).includes(statement);
18724
+ return false;
18725
+ }
18726
+ function hasInlineScopeHazard(fn) {
18727
+ if (fn.node.async === true || fn.node.generator === true) return true;
18728
+ let hazard = false;
18729
+ const walk = (node2) => {
18730
+ if (hazard) return;
18731
+ if (node2.type === "Identifier" && node2.name === "arguments") hazard = true;
18732
+ else if (node2.type === "ThisExpression") hazard = true;
18733
+ else if (node2.type === "VariableDeclaration" && node2.kind === "var") hazard = true;
18734
+ else if (node2.type === "MetaProperty" && nameOf(ast(node2.meta)) === "new" && nameOf(ast(node2.property)) === "target") hazard = true;
18735
+ else for (const child of children2(node2)) walk(child);
18736
+ };
18737
+ walk(fn.body);
18738
+ return hazard;
18739
+ }
18740
+ function hasInlineSignature(fn) {
18741
+ const params = nodes(fn.node.params);
18742
+ return params.length === 3 && nameOf(params[0]) === "input" && nameOf(params[1]) === "pos" && nameOf(params[2]) === "ctx";
18743
+ }
18744
+ function render2(source, start, end, edits) {
18745
+ const ordered = [...edits].sort((a, b) => a.start - b.start || a.end - b.end);
18746
+ let at = start;
18747
+ let out = "";
18748
+ for (const edit of ordered) {
18749
+ if (edit.start < at || edit.end < edit.start || edit.start < start || edit.end > end) {
18750
+ throw new Error("entry supercompiler: overlapping or out-of-range structured edit");
18751
+ }
18752
+ out += source.slice(at, edit.start) + edit.text;
18753
+ at = edit.end;
18754
+ }
18755
+ return out + source.slice(at, end);
18756
+ }
18757
+ function recursiveMembers(fns) {
18758
+ let next = 0;
18759
+ const index = /* @__PURE__ */ new Map();
18760
+ const low = /* @__PURE__ */ new Map();
18761
+ const stack = [];
18762
+ const on = /* @__PURE__ */ new Set();
18763
+ const recursive = /* @__PURE__ */ new Set();
18764
+ const visit = (ip) => {
18765
+ index.set(ip, next);
18766
+ low.set(ip, next);
18767
+ next++;
18768
+ stack.push(ip);
18769
+ on.add(ip);
18770
+ for (const call of fns.get(ip)?.calls ?? []) {
18771
+ if (!fns.has(call.callee)) continue;
18772
+ if (!index.has(call.callee)) {
18773
+ visit(call.callee);
18774
+ low.set(ip, Math.min(low.get(ip), low.get(call.callee)));
18775
+ } else if (on.has(call.callee)) low.set(ip, Math.min(low.get(ip), index.get(call.callee)));
18776
+ }
18777
+ if (low.get(ip) !== index.get(ip)) return;
18778
+ const component = [];
18779
+ for (; ; ) {
18780
+ const member = stack.pop();
18781
+ on.delete(member);
18782
+ component.push(member);
18783
+ if (member === ip) break;
18784
+ }
18785
+ if (component.length > 1 || component.some((member) => fns.get(member).calls.some((c) => c.callee === member))) {
18786
+ for (const member of component) recursive.add(member);
18787
+ }
18788
+ };
18789
+ for (const ip of fns.keys()) if (!index.has(ip)) visit(ip);
18790
+ return recursive;
18791
+ }
18792
+ function fallback(emitted, reason, before) {
18793
+ return {
18794
+ ...emitted,
18795
+ supercompile: {
18796
+ ...before,
18797
+ activated: false,
18798
+ reason,
18799
+ functionsAfter: before.functionsBefore,
18800
+ pieceCallsAfter: before.pieceCallsBefore,
18801
+ sourceAfter: before.sourceBefore,
18802
+ regions: before.functionsBefore,
18803
+ largestRegionSource: 0,
18804
+ protocolRegions: { node: 0, repv: 0, nodeAndRepv: 0 }
18805
+ }
18806
+ };
18807
+ }
18808
+ function supercompileRuleMapReplacement(prog, replacement) {
18809
+ const cfg = defaultAssemblyCfgs(prog)[0];
18810
+ if (cfg === void 0) return replacement;
18811
+ const extraIps = [];
18812
+ for (const scan of prog.scans ?? []) {
18813
+ for (const ref2 of scan.skip) extraIps.push(ref2[0]);
18814
+ if (scan.sentinel !== void 0) extraIps.push(scan.sentinel[0]);
18815
+ }
18816
+ for (const set of prog.scanSkip ?? []) for (const ref2 of set) extraIps.push(ref2[0]);
18817
+ let canonical2;
18818
+ let candidate;
18819
+ try {
18820
+ canonical2 = emitAssemblySource(resolveTable(prog), prog, cfg, extraIps, true);
18821
+ candidate = supercompileEmittedAssembly(prog, cfg, extraIps, canonical2);
18822
+ } catch {
18823
+ return replacement;
18824
+ }
18825
+ if (!candidate.supercompile.activated) return replacement;
18826
+ const prefix = "const __parseman_macro_replacement__=";
18827
+ const parsed = parseSync4("parseman-entry-supercompile-replacement.js", prefix + replacement);
18828
+ if (parsed.errors.length > 0) return replacement;
18829
+ const program = parsed.program;
18830
+ const declaration = nodes(program.body)[0];
18831
+ const declarator = nodes(declaration?.declarations)[0];
18832
+ const call = ast(declarator?.init);
18833
+ const table = nodes(call?.arguments)[0];
18834
+ if (declaration?.type !== "VariableDeclaration" || declarator?.type !== "VariableDeclarator" || call?.type !== "CallExpression" || table?.type !== "ObjectExpression") return replacement;
18835
+ const property = (object, key) => nodes(object.properties).find((prop) => prop.type === "Property" && nameOf(ast(prop.key)) === key);
18836
+ const assembliesProp = property(table, "a");
18837
+ const assemblies = nodes(ast(assembliesProp?.value)?.elements);
18838
+ if (assembliesProp === void 0 || assemblies.length !== 1 || assemblies[0]?.type !== "ObjectExpression") return replacement;
18839
+ const factoryProp = property(assemblies[0], "factory");
18840
+ const factory = ast(factoryProp?.value);
18841
+ const body = ast(factory?.body);
18842
+ if (factory?.type !== "FunctionExpression" || body?.type !== "BlockStatement") return replacement;
18843
+ if (typeof body.start !== "number" || typeof body.end !== "number") return replacement;
18844
+ const start = body.start - prefix.length + 1;
18845
+ const end = body.end - prefix.length - 1;
18846
+ if (replacement.slice(start, end) !== canonical2.source + "\n") return replacement;
18847
+ const transformed = replacement.slice(0, start) + candidate.source + "\n" + replacement.slice(end);
18848
+ const checked = parseSync4("parseman-entry-supercompile-replacement-result.js", prefix + transformed);
18849
+ return checked.errors.length === 0 ? transformed : replacement;
18850
+ }
18851
+ function supercompileEmittedAssembly(prog, _cfg, extraIps, emitted) {
18852
+ const source = emitted.source;
18853
+ const parsed = parseSync4("parseman-entry-supercompile.js", WRAP + source + SUFFIX);
18854
+ if (parsed.errors.length > 0) {
18855
+ const zero = { functionsBefore: 0, pieceCallsBefore: 0, sourceBefore: source.length, barriers: {} };
18856
+ return fallback(emitted, "canonical emitted source did not parse", zero);
18857
+ }
18858
+ const program = parsed.program;
18859
+ const wrapper = nodes(program.body)[0];
18860
+ const wrapperBody = ast(wrapper?.body);
18861
+ if (wrapper?.type !== "FunctionDeclaration" || wrapperBody?.type !== "BlockStatement") {
18862
+ const zero = { functionsBefore: 0, pieceCallsBefore: 0, sourceBefore: source.length, barriers: {} };
18863
+ return fallback(emitted, "missing compiler wrapper", zero);
18864
+ }
18865
+ const fns = /* @__PURE__ */ new Map();
18866
+ for (const statement of nodes(wrapperBody.body)) {
18867
+ if (statement.type !== "FunctionDeclaration") continue;
18868
+ const name = nameOf(ast(statement.id));
18869
+ const hit = name === void 0 ? void 0 : PIECE.exec(name);
18870
+ const body = ast(statement.body);
18871
+ if (hit !== void 0 && hit !== null && body?.type === "BlockStatement") {
18872
+ const ip = Number(hit[1]);
18873
+ fns.set(ip, { ip, name, node: statement, body, calls: [] });
18874
+ }
18875
+ }
18876
+ const externalRefs = /* @__PURE__ */ new Set();
18877
+ let reservedCollision = false;
18878
+ const allCalls = [];
18879
+ const walk = (node2, current, parent, statement, statementParent) => {
18880
+ if (isFunction(node2) && node2 !== current?.node) {
18881
+ const own = node2.type === "FunctionDeclaration" ? nameOf(ast(node2.id)) : void 0;
18882
+ const hit = own === void 0 ? void 0 : PIECE.exec(own);
18883
+ if (hit !== void 0 && hit !== null) {
18884
+ const fn = fns.get(Number(hit[1]));
18885
+ if (fn !== void 0) {
18886
+ for (const child of children2(node2)) {
18887
+ if (child !== ast(node2.id)) walk(child, fn, node2, void 0, void 0);
18888
+ }
18889
+ return;
18890
+ }
18891
+ }
18892
+ current = void 0;
18893
+ }
18894
+ let owner2 = statement;
18895
+ let ownerParent = statementParent;
18896
+ if (parent?.type === "BlockStatement" && nodes(parent.body).includes(node2)) {
18897
+ owner2 = node2;
18898
+ ownerParent = parent;
18899
+ }
18900
+ if (parent?.type === "SwitchCase" && nodes(parent.consequent).includes(node2)) {
18901
+ owner2 = node2;
18902
+ ownerParent = parent;
18903
+ }
18904
+ if (node2.type === "CallExpression") {
18905
+ const calleeName = nameOf(ast(node2.callee));
18906
+ const hit = calleeName === void 0 ? void 0 : PIECE.exec(calleeName);
18907
+ if (hit !== void 0 && hit !== null) {
18908
+ const callee = Number(hit[1]);
18909
+ const args = nodes(node2.arguments);
18910
+ const transformable = current !== void 0 && owner2 !== void 0 && args.length === 3 && nameOf(args[0]) === "input" && nameOf(args[2]) === "ctx" && isDirectCallUse(node2, parent, owner2) && isListStatement(owner2, ownerParent);
18911
+ if (current === void 0 || owner2 === void 0) externalRefs.add(callee);
18912
+ else {
18913
+ const call = { caller: current.ip, callee, node: node2, statement: owner2, args, transformable };
18914
+ current.calls.push(call);
18915
+ allCalls.push(call);
18916
+ }
18917
+ }
18918
+ }
18919
+ if (node2.type === "Identifier") {
18920
+ if (typeof node2.name === "string" && /^_z\d/.test(node2.name)) reservedCollision = true;
18921
+ const hit = typeof node2.name === "string" ? PIECE.exec(node2.name) : null;
18922
+ if (hit !== null) {
18923
+ const isDecl = parent?.type === "FunctionDeclaration" && parent.id === node2;
18924
+ const isCall = parent?.type === "CallExpression" && parent.callee === node2;
18925
+ if (!isDecl && !isCall) externalRefs.add(Number(hit[1]));
18926
+ }
18927
+ }
18928
+ for (const child of children2(node2)) walk(child, current, node2, owner2, ownerParent);
18929
+ };
18930
+ for (const statement of nodes(wrapperBody.body)) walk(statement, void 0, wrapperBody, void 0, void 0);
18931
+ if (reservedCollision) {
18932
+ const before2 = { functionsBefore: fns.size, pieceCallsBefore: allCalls.length, sourceBefore: source.length, barriers: { name: 1 } };
18933
+ return fallback(emitted, "canonical source uses the reserved _z<N> supercompiler prefix", before2);
18934
+ }
18935
+ const pieceCallsBefore = allCalls.length;
18936
+ const recursive = recursiveMembers(fns);
18937
+ const incoming = /* @__PURE__ */ new Map();
18938
+ for (const call of allCalls) {
18939
+ const list = incoming.get(call.callee) ?? [];
18940
+ list.push(call);
18941
+ incoming.set(call.callee, list);
18942
+ }
18943
+ const publicRoots = /* @__PURE__ */ new Set([...Object.values(prog.rules), ...extraIps]);
18944
+ const barrier = /* @__PURE__ */ new Map();
18945
+ for (const ip of fns.keys()) {
18946
+ if (publicRoots.has(ip) || externalRefs.has(ip)) barrier.set(ip, "public");
18947
+ else if (recursive.has(ip)) barrier.set(ip, "recursive");
18948
+ else if (prog.code[ip] === OP_ATTEMPT || prog.code[ip] === OP_SCAN) barrier.set(ip, "effect");
18949
+ else if (hasInlineScopeHazard(fns.get(ip))) barrier.set(ip, "scope");
18950
+ else if (!hasInlineSignature(fns.get(ip))) barrier.set(ip, "shape");
18951
+ else if ((incoming.get(ip)?.length ?? 0) !== 1) barrier.set(ip, "shared");
18952
+ else if (!incoming.get(ip)[0].transformable) barrier.set(ip, "shape");
18953
+ }
18954
+ const roots = [...fns.keys()].filter((ip) => barrier.has(ip));
18955
+ const owner = /* @__PURE__ */ new Map();
18956
+ const absorb = (ip, root) => {
18957
+ if (owner.has(ip)) return;
18958
+ owner.set(ip, root);
18959
+ for (const call of fns.get(ip)?.calls ?? []) {
18960
+ if (!fns.has(call.callee) || barrier.has(call.callee) || !call.transformable) continue;
18961
+ absorb(call.callee, root);
18962
+ }
18963
+ };
18964
+ for (const root of roots) absorb(root, root);
18965
+ for (const ip of fns.keys()) if (!owner.has(ip)) {
18966
+ barrier.set(ip, "shared");
18967
+ absorb(ip, ip);
18968
+ }
18969
+ let serial = 0;
18970
+ const src = (node2) => {
18971
+ const r = range(node2);
18972
+ return source.slice(r.start, r.end);
18973
+ };
18974
+ const renderBody = (ip, embedded) => {
18975
+ const fn = fns.get(ip);
18976
+ const bodyRange = range(fn.body);
18977
+ const start = bodyRange.start + 1;
18978
+ const end = bodyRange.end - 1;
18979
+ const edits = [];
18980
+ const callsByStatement = /* @__PURE__ */ new Map();
18981
+ for (const call of fn.calls) {
18982
+ if (owner.get(call.callee) !== owner.get(ip) || barrier.has(call.callee) || !call.transformable) continue;
18983
+ const list = callsByStatement.get(call.statement) ?? [];
18984
+ list.push(call);
18985
+ callsByStatement.set(call.statement, list);
18986
+ }
18987
+ const returns = [];
18988
+ const collectReturns = (node2) => {
18989
+ if (node2 !== fn.body && isFunction(node2)) return;
18990
+ if (node2.type === "ReturnStatement") returns.push(node2);
18991
+ for (const child of children2(node2)) collectReturns(child);
18992
+ };
18993
+ if (embedded !== void 0) collectReturns(fn.body);
18994
+ const callPrefix = (call) => {
18995
+ const id = serial++;
18996
+ const result = `_z${id}r`;
18997
+ const label2 = `_z${id}`;
18998
+ const at = `_z${id}p`;
18999
+ const nested = renderBody(call.callee, { result, label: label2 });
19000
+ return {
19001
+ value: result,
19002
+ prefix: `let ${result},${at}=${src(call.args[1])}
19003
+ ${label2}:{let pos=${at}
19004
+ ${nested}
19005
+ }
19006
+ `
19007
+ };
19008
+ };
19009
+ for (const [statement, calls] of callsByStatement) {
19010
+ let prefix = "";
19011
+ const replacements = [];
19012
+ for (const call of calls) {
19013
+ const made = callPrefix(call);
19014
+ prefix += made.prefix;
19015
+ const cr = range(call.node);
19016
+ replacements.push({ start: cr.start, end: cr.end, text: made.value });
19017
+ }
19018
+ if (statement.type === "ReturnStatement" && embedded !== void 0) {
19019
+ const sr = range(statement);
19020
+ const arg = ast(statement.argument);
19021
+ const value = arg === void 0 ? "undefined" : render2(source, range(arg).start, range(arg).end, replacements);
19022
+ edits.push({ start: sr.start, end: sr.end, text: `{${prefix}${embedded.result}=${value};break ${embedded.label}}` });
19023
+ } else {
19024
+ const sr = range(statement);
19025
+ edits.push({ start: sr.start, end: sr.start, text: prefix });
19026
+ edits.push(...replacements);
19027
+ }
19028
+ }
19029
+ if (embedded !== void 0) {
19030
+ for (const statement of returns) {
19031
+ if (callsByStatement.has(statement)) continue;
19032
+ const sr = range(statement);
19033
+ const arg = ast(statement.argument);
19034
+ edits.push({
19035
+ start: sr.start,
19036
+ end: sr.end,
19037
+ text: `{${embedded.result}=${arg === void 0 ? "undefined" : src(arg)};break ${embedded.label}}`
19038
+ });
19039
+ }
19040
+ }
19041
+ return render2(source, start, end, edits);
19042
+ };
19043
+ const regionSizes = /* @__PURE__ */ new Map();
19044
+ const regionProtocol = /* @__PURE__ */ new Map();
19045
+ for (const [ip, root] of owner) {
19046
+ const r = range(fns.get(ip).node);
19047
+ regionSizes.set(root, (regionSizes.get(root) ?? 0) + r.end - r.start);
19048
+ const op = prog.code[ip];
19049
+ const bits = (op === OP_NODE || op === OP_NODE_TRACK ? 1 : 0) | (op === OP_REPV ? 2 : 0);
19050
+ regionProtocol.set(root, (regionProtocol.get(root) ?? 0) | bits);
19051
+ }
19052
+ const oversized = /* @__PURE__ */ new Set();
19053
+ for (const [ip, size] of regionSizes) if (size > 18e4) oversized.add(ip);
19054
+ if (oversized.size > 0) {
19055
+ const counts2 = Object.fromEntries([...barrier.values()].map((k) => [k, 0]));
19056
+ for (const kind of barrier.values()) counts2[kind] = (counts2[kind] ?? 0) + 1;
19057
+ const before2 = { functionsBefore: fns.size, pieceCallsBefore, sourceBefore: source.length, barriers: counts2 };
19058
+ return fallback(emitted, "a region exceeded the 180KB source cap", before2);
19059
+ }
19060
+ const topEdits = [];
19061
+ for (const [ip, fn] of fns) {
19062
+ if (owner.get(ip) === ip) {
19063
+ const br = range(fn.body);
19064
+ topEdits.push({ start: br.start + 1, end: br.end - 1, text: renderBody(ip, void 0) });
19065
+ } else {
19066
+ const fr = range(fn.node);
19067
+ topEdits.push({ start: fr.start, end: fr.end, text: "" });
19068
+ }
19069
+ }
19070
+ const candidate = render2(source, 0, source.length, topEdits);
19071
+ const counts = {};
19072
+ for (const kind of barrier.values()) counts[kind] = (counts[kind] ?? 0) + 1;
19073
+ const before = { functionsBefore: fns.size, pieceCallsBefore, sourceBefore: source.length, barriers: counts };
19074
+ if (candidate.length > Math.ceil(source.length * 1.05)) {
19075
+ return fallback(emitted, `candidate exceeded the 5% total source cap (${candidate.length} > ${Math.ceil(source.length * 1.05)})`, before);
19076
+ }
19077
+ const functionsAfter = roots.length;
19078
+ const removed = fns.size - functionsAfter;
19079
+ const checked = parseSync4("parseman-entry-supercompile-result.js", WRAP + candidate + SUFFIX);
19080
+ if (checked.errors.length > 0) return fallback(emitted, "structured candidate did not parse", before);
19081
+ const declared = /* @__PURE__ */ new Set();
19082
+ const referenced = /* @__PURE__ */ new Set();
19083
+ const checkRefs = (node2, parent) => {
19084
+ if (node2.type === "FunctionDeclaration") {
19085
+ const name = nameOf(ast(node2.id));
19086
+ if (name !== void 0 && PIECE.test(name)) declared.add(name);
19087
+ }
19088
+ if (node2.type === "Identifier" && typeof node2.name === "string" && PIECE.test(node2.name)) {
19089
+ const isDeclaration = parent?.type === "FunctionDeclaration" && parent.id === node2;
19090
+ if (!isDeclaration) referenced.add(node2.name);
19091
+ }
19092
+ for (const child of children2(node2)) checkRefs(child, node2);
19093
+ };
19094
+ checkRefs(checked.program);
19095
+ if (declared.size !== functionsAfter || [...referenced].some((name) => !declared.has(name))) {
19096
+ return fallback(emitted, "deleted piece body remains reachable after structured relinking", before);
19097
+ }
19098
+ const largestRegion = [...regionSizes].sort((a, b) => b[1] - a[1])[0];
19099
+ const protocolRegions = {
19100
+ node: [...regionProtocol.values()].filter((bits) => (bits & 1) !== 0).length,
19101
+ repv: [...regionProtocol.values()].filter((bits) => (bits & 2) !== 0).length,
19102
+ nodeAndRepv: [...regionProtocol.values()].filter((bits) => bits === 3).length
19103
+ };
19104
+ return {
19105
+ ...emitted,
19106
+ source: candidate,
19107
+ supercompile: {
19108
+ ...before,
19109
+ activated: removed > 0,
19110
+ ...removed > 0 ? {} : { reason: "no uniquely-owned region bodies" },
19111
+ functionsAfter,
19112
+ pieceCallsAfter: pieceCallsBefore - removed,
19113
+ sourceAfter: candidate.length,
19114
+ regions: roots.length,
19115
+ largestRegionSource: Math.max(0, ...regionSizes.values()),
19116
+ ...largestRegion === void 0 ? {} : { largestRegionIp: largestRegion[0] },
19117
+ protocolRegions
19118
+ }
19119
+ };
19120
+ }
19121
+
17570
19122
  // src/plugin/index.ts
17571
19123
  import { createHash } from "node:crypto";
17572
19124
  var TABLE_RUNTIME_SPECIFIER = "parseman/table";
@@ -17669,7 +19221,7 @@ function parseModuleCached(filePath) {
17669
19221
  let parsed = null;
17670
19222
  try {
17671
19223
  const src = fs2.readFileSync(filePath, "utf8");
17672
- const r = parseSync4(filePath, src);
19224
+ const r = parseSync5(filePath, src);
17673
19225
  if (r.errors.length === 0) parsed = { body: r.program.body, src };
17674
19226
  } catch {
17675
19227
  }
@@ -17818,7 +19370,7 @@ function lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recov
17818
19370
  const source = fs2.readFileSync(file, "utf8");
17819
19371
  const transformed = transformMacro(source, file, moduleAliases, warnUnloweredRegex, recovery);
17820
19372
  if (!transformed || transformed.warnings.length > 0) return null;
17821
- const parsed = parseSync4(file, transformed.code);
19373
+ const parsed = parseSync5(file, transformed.code);
17822
19374
  parsedModule = parsed.errors.length === 0 ? { body: parsed.program.body, src: transformed.code } : null;
17823
19375
  return parsedModule;
17824
19376
  } catch {
@@ -17841,7 +19393,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
17841
19393
  function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage) {
17842
19394
  let result;
17843
19395
  try {
17844
- result = parseSync4(id, code);
19396
+ result = parseSync5(id, code);
17845
19397
  } catch {
17846
19398
  return null;
17847
19399
  }
@@ -18462,9 +20014,12 @@ function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recover
18462
20014
  if (compiled !== null) {
18463
20015
  usedTableRuntime = true;
18464
20016
  return {
18465
- replacement: compiled.replacementWithMetadata(
18466
- staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
18467
- { precompileDefault: true }
20017
+ replacement: supercompileRuleMapReplacement(
20018
+ compiled.prog,
20019
+ compiled.replacementWithMetadata(
20020
+ staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
20021
+ { precompileDefault: true }
20022
+ )
18468
20023
  ),
18469
20024
  ...importedFactories.length ? { importedFactories } : {}
18470
20025
  };