parseman 0.49.0 → 0.50.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +1824 -737
  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 +1252 -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 +1365 -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 +1957 -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 +1315 -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 +152 -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,25 @@ 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();
6543
+ /**
6544
+ * `hasSideWriter` memo for `failureNeedsRollback`, shared across every call
6545
+ * for the lifetime of this `Encoder`. A cached entry is written only when
6546
+ * `complete` is true, which means the answer is a path-independent fact
6547
+ * about that combinator node — it does not depend on which root's traversal
6548
+ * asked, only on the node's own reachable subgraph. Scoping the memo per call
6549
+ * (as a local inside `failureNeedsRollback`) was correct but discarded that
6550
+ * fact after every arm, so a grammar with many ordered-choice arms / optional
6551
+ * / attempt sites re-walked the SAME shared rule graph from scratch for each
6552
+ * site — O(sites × graph size) instead of O(graph size). Measured on the
6553
+ * scss-parser grammar (composed CSS-base superset, the deepest/largest of the
6554
+ * four grammars): 47-50s for one `compileRuleMap` with the per-call memo,
6555
+ * versus the whole macro transform completing in under a second once this
6556
+ * memo is hoisted here.
6557
+ */
6558
+ sideWriterMemo = /* @__PURE__ */ new Map();
6073
6559
  labels = void 0;
6074
6560
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
6075
6561
  activeTrivia = void 0;
@@ -6480,6 +6966,72 @@ var Encoder = class {
6480
6966
  const w = this.winners;
6481
6967
  return w === void 0 ? void 0 : (name) => w[name];
6482
6968
  }
6969
+ /**
6970
+ * Whether a failed ordered-choice arm can leave state that the enclosing
6971
+ * choice must restore before trying its successor.
6972
+ *
6973
+ * `mayLeavePartialCapture` is the existing sound CST/trivia proof. The extra
6974
+ * writer census covers the side sinks that proof deliberately does not model:
6975
+ * fields, recovered errors, and interpreted scanners. Strict assemblies do
6976
+ * not run repeat recovery, but these rows can still publish through a caller's
6977
+ * context. Cycles are safe to stop: revisiting the same combinator cannot
6978
+ * discover a writer the first traversal did not already reach.
6979
+ */
6980
+ failureNeedsRollback(p, autoNot) {
6981
+ const refName = p._ruleName;
6982
+ const winner = refName === void 0 ? void 0 : this.winners?.[refName];
6983
+ const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
6984
+ const sideWriterMemo = this.sideWriterMemo;
6985
+ const seen = /* @__PURE__ */ new Set();
6986
+ const hasSideWriter = (current) => {
6987
+ const cached = sideWriterMemo.get(current);
6988
+ if (cached !== void 0) return { found: cached, complete: true };
6989
+ if (seen.has(current)) return { found: false, complete: false };
6990
+ seen.add(current);
6991
+ const def = current._def;
6992
+ let result;
6993
+ switch (def.tag) {
6994
+ case "field":
6995
+ case "expect":
6996
+ case "recover":
6997
+ case "scanTo":
6998
+ case "unknown":
6999
+ result = { found: true, complete: true };
7000
+ break;
7001
+ case "lazy": {
7002
+ const name = current._ruleName;
7003
+ const resolvedWinner = name === void 0 ? void 0 : this.winners?.[name];
7004
+ if (resolvedWinner !== void 0 && !winnerWrapsReference2(resolvedWinner, current)) {
7005
+ result = hasSideWriter(resolvedWinner);
7006
+ break;
7007
+ }
7008
+ try {
7009
+ result = hasSideWriter(def.thunk());
7010
+ } catch {
7011
+ result = { found: true, complete: true };
7012
+ }
7013
+ break;
7014
+ }
7015
+ default: {
7016
+ let complete = true;
7017
+ result = { found: false, complete: true };
7018
+ for (const child of childrenOf2(def)) {
7019
+ const childResult = hasSideWriter(child);
7020
+ if (childResult.found) {
7021
+ result = { found: true, complete: true };
7022
+ break;
7023
+ }
7024
+ complete &&= childResult.complete;
7025
+ }
7026
+ if (!result.found) result = { found: false, complete };
7027
+ }
7028
+ }
7029
+ seen.delete(current);
7030
+ if (result.found || result.complete) sideWriterMemo.set(current, result.found);
7031
+ return result;
7032
+ };
7033
+ return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || hasSideWriter(root).found || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
7034
+ }
6483
7035
  /** A first set becomes a char class string, or −1 for `any`. */
6484
7036
  charClass(fs3) {
6485
7037
  if (fs3.kind !== "ranges" || fs3.ranges.length === 0) return -1;
@@ -6765,9 +7317,39 @@ var Encoder = class {
6765
7317
  });
6766
7318
  const rr = this.refResolver();
6767
7319
  const finalChoice = classifyFinalChoice(arms, rr);
6768
- const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
7320
+ const transactionalFirst = arms.map((arm, i) => {
7321
+ if (!finalChoice.nullable[i]) return void 0;
7322
+ const def = arm._def;
7323
+ if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
7324
+ return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr);
7325
+ });
7326
+ const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
7327
+ const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
7328
+ if (transactionalFirst.some((first) => first !== void 0) && classes.every((cls) => cls >= 0)) {
7329
+ let overlap = false;
7330
+ for (let i = 0; i < gateFirst.length && !overlap; i++) {
7331
+ for (let j = i + 1; j < gateFirst.length; j++) {
7332
+ if (intersects(gateFirst[i], gateFirst[j])) {
7333
+ overlap = true;
7334
+ break;
7335
+ }
7336
+ }
7337
+ }
7338
+ if (!overlap) for (let i = 0; i < classes.length; i++) {
7339
+ if (transactionalFirst[i] !== void 0) classes[i] = -1;
7340
+ }
7341
+ }
6769
7342
  const dispIdx = this.disp.length;
6770
7343
  this.disp.push(classes);
7344
+ let rollbackMask = kids.length > 31 ? -1 : 0;
7345
+ if (rollbackMask === 0) {
7346
+ for (let i = 0; i < arms.length; i++) {
7347
+ const src = order[i];
7348
+ if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
7349
+ rollbackMask |= 1 << i;
7350
+ }
7351
+ }
7352
+ }
6771
7353
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
6772
7354
  this.code[head + 1] = dispIdx;
6773
7355
  this.code[head + 2] = kids.length;
@@ -6776,6 +7358,10 @@ var Encoder = class {
6776
7358
  this.code[head + 4 + i] = kids[i];
6777
7359
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
6778
7360
  }
7361
+ this.choiceRollbackMasks.set(head, rollbackMask);
7362
+ if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
7363
+ this.nonCommittingChoiceSites.add(head);
7364
+ }
6779
7365
  return head;
6780
7366
  }
6781
7367
  case "many":
@@ -6805,8 +7391,11 @@ var Encoder = class {
6805
7391
  }
6806
7392
  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
7393
  }
6808
- case "optional":
6809
- return this.emit(OP_OPT, this.node(d.parser).ip);
7394
+ case "optional": {
7395
+ const head = this.emit(OP_OPT, this.node(d.parser).ip);
7396
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
7397
+ return head;
7398
+ }
6810
7399
  case "transform": {
6811
7400
  const inner = d.parser._def;
6812
7401
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
@@ -6965,6 +7554,7 @@ var Encoder = class {
6965
7554
  // lowering was correct only for a choice arm.
6966
7555
  case "attempt": {
6967
7556
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
7557
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
6968
7558
  const fs3 = d.parser._meta.firstSet;
6969
7559
  if (fs3.kind === "any" || matchesEmpty(d.parser)) return inner;
6970
7560
  const cls = this.charClass(fs3);
@@ -7133,6 +7723,10 @@ var Encoder = class {
7133
7723
  ...this.rec ? { rec: 1 } : {},
7134
7724
  ...this.cov === void 0 ? {} : { cov: this.cov },
7135
7725
  lines: this.track ? 1 : 0
7726
+ }, void 0, {
7727
+ choiceRollbackMasks: this.choiceRollbackMasks,
7728
+ failureRollbackCleanSites: this.failureRollbackCleanSites,
7729
+ nonCommittingChoiceSites: this.nonCommittingChoiceSites
7136
7730
  });
7137
7731
  }
7138
7732
  };
@@ -7177,7 +7771,6 @@ function encodeTableProgram(ruleMap, settings = {}) {
7177
7771
  const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
7178
7772
  const resolveLexical = (name) => ruleMap[name];
7179
7773
  const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
7180
- assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
7181
7774
  const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
7182
7775
  enc.winners = ruleMap;
7183
7776
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
@@ -8310,13 +8903,17 @@ var TRI_NONE = -1;
8310
8903
  var CAP_UNKNOWN = 0;
8311
8904
  var CAP_OFF = 1;
8312
8905
  var CAP_ON = 2;
8313
- var TOP = { tri: TRI_UNKNOWN, buf: false, cap: CAP_UNKNOWN };
8906
+ var RAW_UNKNOWN = 0;
8907
+ var RAW_CAPTURE = 1;
8908
+ var RAW_OMIT = 2;
8909
+ var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
8314
8910
  function meet(a, b) {
8315
8911
  const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
8316
8912
  const buf = a.buf && b.buf;
8913
+ const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
8317
8914
  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 };
8915
+ if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
8916
+ return { tri, buf, raw, cap };
8320
8917
  }
8321
8918
  function reachableSites(code, roots) {
8322
8919
  const seen = /* @__PURE__ */ new Set();
@@ -8339,25 +8936,26 @@ function transfer(code, ip, at, hostCst) {
8339
8936
  const tri = ki < 0 ? TRI_NONE : ki;
8340
8937
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
8341
8938
  if (tri === at.tri && cap === at.cap) return at;
8342
- return { tri, buf: at.buf, cap };
8939
+ return { tri, buf: at.buf, raw: at.raw, cap };
8343
8940
  }
8344
8941
  if (op === OP_NODE || op === OP_NODE_TRACK) {
8345
8942
  const flags = code[ip + 3];
8346
8943
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
8347
8944
  if (directChildren) {
8348
- return { tri: at.tri, buf: false, cap: CAP_OFF };
8945
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
8349
8946
  }
8350
8947
  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 };
8948
+ const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
8949
+ if (at.buf && raw === at.raw && cap === at.cap) return at;
8950
+ return { tri: at.tri, buf: true, raw, cap };
8353
8951
  }
8354
8952
  if (op === OP_TOKEN) {
8355
8953
  if (at.tri === TRI_NONE && !at.buf) return at;
8356
- return { tri: TRI_NONE, buf: false, cap: at.cap };
8954
+ return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
8357
8955
  }
8358
8956
  if (op === OP_LEAF) {
8359
8957
  if (!at.buf) return at;
8360
- return { tri: at.tri, buf: false, cap: at.cap };
8958
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
8361
8959
  }
8362
8960
  return at;
8363
8961
  }
@@ -8424,6 +9022,162 @@ function scalarTerminalNotChild(code, ip) {
8424
9022
  const op = code[child];
8425
9023
  return op === OP_RX || op === OP_LIT ? child : -1;
8426
9024
  }
9025
+ function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
9026
+ const seen = /* @__PURE__ */ new Set();
9027
+ let at = ip;
9028
+ let depth = 0;
9029
+ while (!seen.has(at)) {
9030
+ seen.add(at);
9031
+ const op = code[at];
9032
+ if (op === OP_LIT || op === OP_RX) return depth >= minDepth ? at : -1;
9033
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || throughAttempt && op === OP_ATTEMPT) {
9034
+ at = code[at + 1];
9035
+ depth++;
9036
+ continue;
9037
+ }
9038
+ if (throughPeek && op === OP_PEEK) {
9039
+ at = code[at + 1];
9040
+ depth++;
9041
+ continue;
9042
+ }
9043
+ 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) {
9044
+ at = code[at + 2];
9045
+ depth++;
9046
+ continue;
9047
+ }
9048
+ if (op === OP_SEQ || op === OP_SEQV) {
9049
+ if (code[at + 1] < 1) return -1;
9050
+ at = code[at + 2];
9051
+ depth++;
9052
+ continue;
9053
+ }
9054
+ if (op === OP_SEQX) {
9055
+ if (code[at + 2] < 1) return -1;
9056
+ at = code[at + 3];
9057
+ depth++;
9058
+ continue;
9059
+ }
9060
+ return -1;
9061
+ }
9062
+ return -1;
9063
+ }
9064
+ function leadingScalarSequence(code, ip) {
9065
+ const wholeScalar = (start) => {
9066
+ const seen2 = /* @__PURE__ */ new Set();
9067
+ let at2 = start;
9068
+ while (!seen2.has(at2)) {
9069
+ seen2.add(at2);
9070
+ const op = code[at2];
9071
+ if (op === OP_LIT || op === OP_RX) return at2;
9072
+ if (op === OP_RULE || op === OP_TOKEN || op === OP_ATTEMPT) {
9073
+ at2 = code[at2 + 1];
9074
+ continue;
9075
+ }
9076
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9077
+ at2 = code[at2 + 2];
9078
+ continue;
9079
+ }
9080
+ if (op === OP_SEQ || op === OP_SEQV) {
9081
+ if (code[at2 + 1] !== 1) return -1;
9082
+ at2 = code[at2 + 2];
9083
+ continue;
9084
+ }
9085
+ if (op === OP_SEQX) {
9086
+ if (code[at2 + 2] !== 1) return -1;
9087
+ at2 = code[at2 + 3];
9088
+ continue;
9089
+ }
9090
+ return -1;
9091
+ }
9092
+ return -1;
9093
+ };
9094
+ const seen = /* @__PURE__ */ new Set();
9095
+ let at = ip;
9096
+ let ambientTrivia;
9097
+ while (!seen.has(at)) {
9098
+ seen.add(at);
9099
+ const op = code[at];
9100
+ if (op === OP_RULE) {
9101
+ at = code[at + 1];
9102
+ continue;
9103
+ }
9104
+ if (op === OP_SCOPE_PLAIN) {
9105
+ ambientTrivia = code[at + 1];
9106
+ at = code[at + 2];
9107
+ continue;
9108
+ }
9109
+ if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9110
+ at = code[at + 2];
9111
+ continue;
9112
+ }
9113
+ const n = op === OP_SEQ || op === OP_SEQV ? code[at + 1] : op === OP_SEQX ? code[at + 2] : 0;
9114
+ if (n < 3 || ambientTrivia === void 0) return void 0;
9115
+ const base = op === OP_SEQX ? at + 3 : at + 2;
9116
+ const terminals = [
9117
+ wholeScalar(code[base]),
9118
+ wholeScalar(code[base + 1]),
9119
+ wholeScalar(code[base + 2])
9120
+ ];
9121
+ return terminals.every((terminal) => terminal >= 0) ? { terminals, trivia: ambientTrivia } : void 0;
9122
+ }
9123
+ return void 0;
9124
+ }
9125
+ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
9126
+ const active = /* @__PURE__ */ new Set();
9127
+ const walk = (at, depth) => {
9128
+ if (active.has(at)) return void 0;
9129
+ active.add(at);
9130
+ try {
9131
+ const op = code[at];
9132
+ if (op === OP_LIT) {
9133
+ const value = constants[code[at + 1]];
9134
+ return depth >= minDepth && typeof value === "string" && value.length > 0 ? [at] : void 0;
9135
+ }
9136
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
9137
+ return walk(code[at + 1], depth + 1);
9138
+ }
9139
+ 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) {
9140
+ return walk(code[at + 2], depth + 1);
9141
+ }
9142
+ if (op === OP_SEQ || op === OP_SEQV) {
9143
+ return code[at + 1] < 1 ? void 0 : walk(code[at + 2], depth + 1);
9144
+ }
9145
+ if (op === OP_SEQX) {
9146
+ return code[at + 2] < 1 ? void 0 : walk(code[at + 3], depth + 1);
9147
+ }
9148
+ if (op !== OP_CHOICE) return void 0;
9149
+ const n = code[at + 2];
9150
+ if (n < 1) return void 0;
9151
+ const out = [];
9152
+ for (let i = 0; i < n; i++) {
9153
+ const branch = walk(code[at + 4 + i], depth + 1);
9154
+ if (branch === void 0) return void 0;
9155
+ for (const terminal of branch) {
9156
+ const value = constants[code[terminal + 1]];
9157
+ let covered = false;
9158
+ for (let j = 0; j < out.length; j++) {
9159
+ const prior = constants[code[out[j] + 1]];
9160
+ if (value.startsWith(prior)) {
9161
+ covered = true;
9162
+ break;
9163
+ }
9164
+ }
9165
+ if (covered) continue;
9166
+ for (let j = out.length - 1; j >= 0; j--) {
9167
+ const prior = constants[code[out[j] + 1]];
9168
+ if (prior.startsWith(value)) out.splice(j, 1);
9169
+ }
9170
+ out.push(terminal);
9171
+ if (out.length > limit) return void 0;
9172
+ }
9173
+ }
9174
+ return out;
9175
+ } finally {
9176
+ active.delete(at);
9177
+ }
9178
+ };
9179
+ return walk(ip, 0);
9180
+ }
8427
9181
 
8428
9182
  // src/table/emit-assembly.ts
8429
9183
  var Unemittable = class extends Error {
@@ -8505,6 +9259,16 @@ let _pfScan=null
8505
9259
  let _pfHost
8506
9260
  let _pfDepth=0
8507
9261
  const _pfFrames=[]
9262
+ let _pfTokInput
9263
+ let _pfTokPos=-1
9264
+ let _pfTokBody=-1
9265
+ let _pfTokPacked=-1
9266
+ let _pfTokValue
9267
+ let _pfTokDispatch=-1
9268
+ let _pfTokArm=-1
9269
+ let _pfTokEnd=-1
9270
+ let _pfSeqEnd=-1
9271
+ function _asciiFoldCode(c){return c>=65&&c<=90?c+32:c}
8508
9272
  function _skipTrivia(input,cur,ctx){
8509
9273
  const s=_pfScan
8510
9274
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
@@ -8570,6 +9334,40 @@ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=
8570
9334
  if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
8571
9335
  }
8572
9336
  `;
9337
+ var NO_RAW_RUNTIME_PRELUDE = `
9338
+ function _pushLeafNoRawBuf(ctx,value,s,e){
9339
+ const l={_tag:'leaf',value,span:{start:s,end:e}}
9340
+ const b=ctx._cstBuf
9341
+ if(b.ch!==undefined)b.ch.push(l)
9342
+ else if(b.single!==undefined){b.ch=[b.single,l];b.single=undefined}
9343
+ else b.single=l
9344
+ b.rawLen++
9345
+ }
9346
+ function _pushNodeNoRawBuf(ctx,value){
9347
+ const b=ctx._cstBuf
9348
+ if(b.ch!==undefined)b.ch.push(value)
9349
+ else if(b.single!==undefined){b.ch=[b.single,value];b.single=undefined}
9350
+ else b.single=value
9351
+ b.rawLen++
9352
+ }
9353
+ function _rbNoRawBuf(ctx,raw,tl,lv,lg,rt){
9354
+ const b=ctx._cstBuf
9355
+ if(b.rawLen!==raw)b.rawLen=raw
9356
+ const ch=b.ch
9357
+ if(ch!==undefined){
9358
+ if(lv===0)b.ch=undefined
9359
+ else if(lv===1){b.single=ch[0];b.ch=undefined}
9360
+ else if(ch.length!==lv)ch.length=lv
9361
+ }else if(lv===0)b.single=undefined
9362
+ const bt=b.tl
9363
+ if(bt!==undefined){
9364
+ if(tl===0)b.tl=undefined
9365
+ else if(bt.length!==tl)bt.length=tl
9366
+ }
9367
+ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=lg
9368
+ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
9369
+ }
9370
+ `;
8573
9371
  function q(s) {
8574
9372
  return JSON.stringify(s);
8575
9373
  }
@@ -8582,11 +9380,12 @@ function sinkReads(t, s) {
8582
9380
  ${t}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${s.er ? `
8583
9381
  ${t}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
8584
9382
  }
8585
- function emitMark(t, buf, s = NO_SINKS, decl = true) {
9383
+ function emitMark(t, buf, rawMode, s = NO_SINKS, decl = true) {
8586
9384
  if (buf) {
9385
+ 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
9386
  return `${decl ? `let ${t}raw=0,${t}tl=0,${t}lv=0,${t}lg=0,${t}rt=0${sinkSlots(t, s)}
8588
9387
  ` : ""}{const b=ctx._cstBuf
8589
- const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9388
+ ${raw}
8590
9389
  const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
8591
9390
  const l=b.tl;${t}tl=l!==undefined?l.length:0
8592
9391
  ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
@@ -8596,7 +9395,7 @@ ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t,
8596
9395
  ` : `${t}n=false
8597
9396
  `}{const b=ctx._cstBuf
8598
9397
  if(b!==undefined){
8599
- const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9398
+ const r=b.raw;${t}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
8600
9399
  const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
8601
9400
  const l=b.tl;${t}tl=l!==undefined?l.length:0
8602
9401
  ${t}n=true
@@ -8611,14 +9410,16 @@ ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
8611
9410
  ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t, s)}
8612
9411
  }}`;
8613
9412
  }
8614
- function emitRollback(t, buf, s = NO_SINKS) {
9413
+ function emitRollback(t, buf, rawMode, s = NO_SINKS) {
8615
9414
  const fd = s.fd ? `
8616
9415
  if(ctx._fields!==undefined&&ctx._fields.length!==${t}fd)ctx._fields.length=${t}fd` : "";
8617
9416
  const er = s.er ? `
8618
9417
  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)}`;
9418
+ if (buf && rawMode === RAW_OMIT) return `_rbNoRawBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
9419
+ if (buf && rawMode === RAW_CAPTURE) return `_rbBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
9420
+ 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)`;
9421
+ if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,undefined,undefined,${t}lg,${t}rt)`;
9422
+ 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
9423
  }
8623
9424
  function emitTerm(callee, dst, t, l, skip) {
8624
9425
  const fast = `const ${t}v=${callee}(input,cur,ctx)
@@ -8676,37 +9477,111 @@ function rebuildPools(cc, fx, disp, plan) {
8676
9477
  })
8677
9478
  };
8678
9479
  }
8679
- function emitAssemblySource(t, prog, cfg, extraIps = []) {
8680
- const { code, k, disp, dsp, triviaLabelled } = t;
9480
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
9481
+ const { code, k, fx, disp, dsp, triviaLabelled } = t;
8681
9482
  const swapLegal = !cfg.trackLines;
8682
9483
  const hostCst = cfg.hostCst;
8683
9484
  const REC2 = prog.rec === 1 && cfg.tolerant;
8684
9485
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
8685
9486
  const roots = [...Object.values(prog.rules), ...extraIps];
9487
+ const reachable = [...reachableSites(code, roots)];
8686
9488
  const labels = computeSiteLabels(code, roots, hostCst);
8687
9489
  const scalarSpecs = /* @__PURE__ */ new Set();
9490
+ const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
9491
+ const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
9492
+ const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
9493
+ const tokenChoiceCandidates = /* @__PURE__ */ new Map();
9494
+ const tokenChoiceDispatches = /* @__PURE__ */ new Set();
9495
+ const tokenChoiceBodies = /* @__PURE__ */ new Set();
8688
9496
  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]);
9497
+ for (const ip of reachable) {
9498
+ if (code[ip] === OP_NODE) {
9499
+ const child = scalarTerminalNodeChild(code, ip);
9500
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
9501
+ continue;
9502
+ }
9503
+ if (code[ip] !== OP_CHOICE || disp[code[ip + 1]].exclusive) continue;
9504
+ const n = code[ip + 2];
9505
+ for (let i = 0; i < n; i++) {
9506
+ const armIp = code[ip + 4 + i];
9507
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
9508
+ if (n === 2 || n === 3) {
9509
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
9510
+ continue;
9511
+ }
9512
+ if (child >= 0) {
9513
+ const spec = k[code[child + 1]];
9514
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
9515
+ largeChoiceScalarSpecs.add(code[child + 1]);
9516
+ continue;
9517
+ }
9518
+ }
9519
+ const family = leadingLiteralFamily(code, k, armIp);
9520
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
9521
+ const value = k[code[terminal + 1]];
9522
+ return typeof value === "string" && value.length >= 2;
9523
+ })) {
9524
+ largeChoiceLiteralFamilies.set(armIp, family);
9525
+ }
9526
+ const sequence6 = leadingScalarSequence(code, armIp);
9527
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
9528
+ largeChoiceScalarSequences.set(armIp, sequence6);
9529
+ }
9530
+ }
9531
+ let candidate;
9532
+ let ambiguous = false;
9533
+ for (let i = 0; i < n; i++) {
9534
+ const armIp = code[ip + 4 + i];
9535
+ if (code[armIp] !== OP_XFORM) continue;
9536
+ const dispatchIp = code[armIp + 2];
9537
+ if (code[dispatchIp] !== OP_DISPATCH) continue;
9538
+ const selectorIp = code[dispatchIp + 1];
9539
+ if (code[selectorIp] !== OP_LEX_BODY) continue;
9540
+ if (candidate !== void 0) {
9541
+ ambiguous = true;
9542
+ break;
9543
+ }
9544
+ candidate = { arm: i, dispatchIp };
9545
+ }
9546
+ if (!ambiguous && candidate !== void 0) {
9547
+ tokenChoiceCandidates.set(ip, candidate);
9548
+ tokenChoiceDispatches.add(candidate.dispatchIp);
9549
+ tokenChoiceBodies.add(code[code[candidate.dispatchIp + 1] + 1]);
9550
+ }
8693
9551
  }
8694
9552
  }
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;
9553
+ const needsNoRawPrelude = !hostCst && reachable.some((ip) => {
9554
+ const op = code[ip];
9555
+ return (op === OP_NODE || op === OP_NODE_TRACK) && code[ip + 1] >= 0 && code[ip + 4] < 0 && (code[ip + 3] & 2) !== 0;
9556
+ });
9557
+ const sinkSites = reachable;
9558
+ const sinkBits = /* @__PURE__ */ new Map();
9559
+ for (const ip of sinkSites) {
9560
+ const op = code[ip];
9561
+ sinkBits.set(
9562
+ ip,
9563
+ op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC2 && (op === OP_REP || op === OP_REPV) ? 2 : 0)
9564
+ );
9565
+ }
9566
+ const sinkKids = [];
9567
+ let sinkChanged = true;
9568
+ while (sinkChanged) {
9569
+ sinkChanged = false;
9570
+ for (const ip of sinkSites) {
9571
+ let bits = sinkBits.get(ip) ?? 0;
9572
+ sinkKids.length = 0;
9573
+ childSlots(code, ip, sinkKids);
9574
+ for (let i = 0; i < sinkKids.length; i++) bits |= sinkBits.get(sinkKids[i]) ?? 0;
9575
+ if (bits !== sinkBits.get(ip)) {
9576
+ sinkBits.set(ip, bits);
9577
+ sinkChanged = true;
8704
9578
  }
8705
- if (op === OP_FIELD) fd = true;
8706
- else if (op === OP_EXPECT) er = true;
8707
9579
  }
8708
- return { fd, er };
8709
- })();
9580
+ }
9581
+ const sinksAt = (ip) => {
9582
+ const bits = sinkBits.get(ip) ?? 0;
9583
+ return bits === 0 ? NO_SINKS : { fd: (bits & 1) !== 0, er: (bits & 2) !== 0 };
9584
+ };
8710
9585
  const bodies = [];
8711
9586
  const byIp = /* @__PURE__ */ new Map();
8712
9587
  const reached = /* @__PURE__ */ new Set();
@@ -8733,9 +9608,117 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
8733
9608
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
8734
9609
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
8735
9610
  const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
9611
+ const scalarSequenceRefs = /* @__PURE__ */ new Map();
9612
+ const scalarSequenceRef = (sequence6) => {
9613
+ const key = `${sequence6.trivia}:${sequence6.terminals.map((terminal) => code[terminal + 1]).join(",")}`;
9614
+ const prior = scalarSequenceRefs.get(key);
9615
+ if (prior !== void 0) return prior;
9616
+ const recognizers = sequence6.terminals.map((terminal) => recognizerRef(code[terminal + 1]));
9617
+ const expected = sequence6.terminals.map((terminal) => fxRef(code[terminal + 2]));
9618
+ const scan = sequence6.trivia < 0 ? void 0 : hoist("ts", `TRIVIASCAN[${sequence6.trivia}]`);
9619
+ const name = `_sd${scalarSequenceRefs.size}_`;
9620
+ const steps = recognizers.map((recognize, i) => `${i === 0 ? "let " : ""}at=${i === 0 ? "pos" : scan === void 0 ? "cur" : `${scan}(input,cur)`}
9621
+ ${i === 0 ? "let " : ""}cur=${recognize}(input,at)
9622
+ if(cur<0){_pfSeqEnd=at;return ${~i}}`).join("\n");
9623
+ choiceDefs.push(`function ${name}(input,pos){
9624
+ ${steps}
9625
+ return cur
9626
+ }`);
9627
+ const made = { name, expected };
9628
+ scalarSequenceRefs.set(key, made);
9629
+ return made;
9630
+ };
8736
9631
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
8737
9632
  let uid = 0;
8738
9633
  const tmp = () => `_t${uid++}_`;
9634
+ const dispatchClaim = (m) => {
9635
+ switch (m[0]) {
9636
+ case 0:
9637
+ return `key.startsWith(${q(m[1])})`;
9638
+ case 1:
9639
+ return `key.endsWith(${q(m[1])})`;
9640
+ case 3:
9641
+ return `asciiFoldKey(key).startsWith(${q(m[1])})`;
9642
+ case 4:
9643
+ return `asciiFoldKey(key).endsWith(${q(m[1])})`;
9644
+ default: {
9645
+ if (!m[2].includes("g") && !m[2].includes("y")) {
9646
+ try {
9647
+ new RegExp(m[1], m[2]);
9648
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
9649
+ } catch {
9650
+ }
9651
+ }
9652
+ return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
9653
+ }
9654
+ }
9655
+ };
9656
+ const tokenDecisionRefs = /* @__PURE__ */ new Map();
9657
+ function tokenDecisionFor(dispatchIp) {
9658
+ const prior = tokenDecisionRefs.get(dispatchIp);
9659
+ if (prior !== void 0) return prior;
9660
+ const selectorIp = code[dispatchIp + 1];
9661
+ const body = code[selectorIp + 1];
9662
+ const lineFlags = code[selectorIp + 4];
9663
+ const hasSuffix = (lineFlags & 4) !== 0;
9664
+ const di = code[dispatchIp + 2];
9665
+ const spec = dsp[di];
9666
+ const n = code[dispatchIp + 5];
9667
+ validateDispatchSpec(spec, n, code[dispatchIp + 4]);
9668
+ const recognize = hoist("lex", `LEX[${body}]`);
9669
+ const bk = hoist("bk", `DSP[${di}].byKey`);
9670
+ const expected = hoist("dx", `DSP[${di}].expected`);
9671
+ const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
9672
+ ` : "";
9673
+ const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
9674
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
9675
+ }
9676
+ `;
9677
+ const foldedEntries = [...spec.byFold.entries()];
9678
+ 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;
9679
+ const foldedRangeEquals = (value) => {
9680
+ const folded = value.replace(/[A-Z]/g, (c) => c.toLowerCase());
9681
+ return `e-pos===${folded.length}&&${[...folded].map((c, i) => {
9682
+ const cc = c.charCodeAt(0);
9683
+ return `_asciiFoldCode(input.charCodeAt(pos+${i}))===${cc}`;
9684
+ }).join("&&")}`;
9685
+ };
9686
+ const classify = fixedFunctionChoice ? (() => {
9687
+ const [exact, exactArm] = foldedEntries[0];
9688
+ const genericArm = spec.match[0][3];
9689
+ return `let arm
9690
+ if(${foldedRangeEquals(exact)})arm=${exactArm}
9691
+ else if(sm&&e>pos+1){
9692
+ let clean=true
9693
+ for(let i=pos;i<e;i++){const c=input.charCodeAt(i);if(c===10||c===13||c===0x2028||c===0x2029){clean=false;break}}
9694
+ if(clean&&!(${foldedRangeEquals("url(")})&&!(${foldedRangeEquals("calc(")}))arm=${genericArm}
9695
+ }`;
9696
+ })() : `const key=input.slice(pos,e)
9697
+ let arm=${bk}.get(key)
9698
+ ${fold}${chain}`;
9699
+ const name = `_td${tokenDecisionRefs.size}_`;
9700
+ choiceDefs.push(`function ${name}(input,pos){
9701
+ const r=${recognize}(input,pos)
9702
+ if(r<0)return -1
9703
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9704
+ ${classify}
9705
+ if(arm===undefined){
9706
+ ${code[dispatchIp + 3] < 0 ? "_pfTokEnd=e;return 0" : `arm=${n}`}
9707
+ }
9708
+ ${fixedFunctionChoice ? "const key=input.slice(pos,e)" : ""}
9709
+ _pfTokInput=input
9710
+ _pfTokPos=pos
9711
+ _pfTokBody=${body}
9712
+ _pfTokPacked=r
9713
+ _pfTokValue=key
9714
+ _pfTokDispatch=${dispatchIp}
9715
+ _pfTokArm=arm
9716
+ return 1
9717
+ }`);
9718
+ const made = { name, expected };
9719
+ tokenDecisionRefs.set(dispatchIp, made);
9720
+ return made;
9721
+ }
8739
9722
  function skipFor(l) {
8740
9723
  if (l.tri < 0) return "_skipTrivia";
8741
9724
  const ki = l.tri;
@@ -8823,7 +9806,8 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
8823
9806
  const op = code[ip];
8824
9807
  const head = `function ${fname}(input,pos,ctx){`;
8825
9808
  const L = labels.at(ip);
8826
- const pushLeaf = L.buf && !cfg.trackLines ? "_pushLeafBuf" : "_pushLeaf";
9809
+ const sinks = sinksAt(ip);
9810
+ const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
8827
9811
  const captureLeaf = (value) => {
8828
9812
  const call = `${pushLeaf}(ctx,${value},pos,e)`;
8829
9813
  return L.buf ? call : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${call}`;
@@ -8987,12 +9971,12 @@ return err
8987
9971
  }
8988
9972
  case OP_ROUTED: {
8989
9973
  const fb = code[ip + 1];
8990
- const fallback = fb >= 0 ? link(fb) : void 0;
9974
+ const fallback2 = fb >= 0 ? link(fb) : void 0;
8991
9975
  const push = `pushCstLeaf(ctx,{_tag:'leaf',value:it.value,span:it.span})`;
8992
9976
  return `${head}
8993
9977
  const it=ctx._routed
8994
9978
  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"}
9979
+ ${fallback2 !== void 0 ? `return ${fallback2}(input,pos,ctx)` : "ctx._fe=pos;ctx._fx=ROUTED_FX;return FAIL"}
8996
9980
  }
8997
9981
  ${L.buf ? push : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${push}`}
8998
9982
  EC.e=it.span.end
@@ -9074,20 +10058,24 @@ return out
9074
10058
  }`;
9075
10059
  }
9076
10060
  case OP_LEX_BODY: {
9077
- const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
10061
+ const body = code[ip + 1];
10062
+ const recognize = hoist("lex", `LEX[${body}]`);
9078
10063
  const expected = fxRef(code[ip + 2]);
9079
10064
  const suffixExpected = fxRef(code[ip + 3]);
9080
10065
  const lineFlags = code[ip + 4];
9081
10066
  const hasSuffix = (lineFlags & 4) !== 0;
10067
+ const pending = tokenChoiceBodies.has(body);
9082
10068
  return `${head}
9083
- const r=${recognize}(input,pos)
10069
+ ${pending ? `const tp=_pfTokBody===${body}&&_pfTokInput===input&&_pfTokPos===pos
10070
+ const r=tp?_pfTokPacked:${recognize}(input,pos)` : `const r=${recognize}(input,pos)`}
9084
10071
  if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
9085
10072
  const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9086
10073
  ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
9087
10074
  ${hasSuffix ? "ctx._fc=false" : ""}
9088
10075
  ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
9089
10076
  ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
9090
- const v=input.slice(pos,e)
10077
+ const v=${pending ? "tp?_pfTokValue:" : ""}input.slice(pos,e)
10078
+ ${pending ? "if(tp){_pfTokBody=-1;_pfTokValue=undefined}" : ""}
9091
10079
  if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9092
10080
  EC.e=e
9093
10081
  return v
@@ -9143,12 +10131,13 @@ return v
9143
10131
  /* ── transaction ─────────────────────────────────────────────────────── */
9144
10132
  case OP_ATTEMPT: {
9145
10133
  const child = link(code[ip + 1]);
10134
+ const clean = !REC2 && failureRollbackClean(prog, ip);
9146
10135
  const p = tmp();
9147
10136
  return `${head}
9148
- ${emitMark(p, L.buf, sinks)}
10137
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
9149
10138
  const v=${child}(input,pos,ctx)
9150
10139
  if(v!==FAIL)return v
9151
- ${emitRollback(p, L.buf, sinks)}
10140
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
9152
10141
  if(ctx._fc===true)return FAIL
9153
10142
  ctx._fe=pos
9154
10143
  return FAIL
@@ -9171,9 +10160,9 @@ return FAIL
9171
10160
  const xf = fxRef(code[ip + 2]);
9172
10161
  const p = tmp();
9173
10162
  return `${head}
9174
- ${emitMark(p, L.buf, sinks)}
10163
+ ${emitMark(p, L.buf, L.raw, sinks)}
9175
10164
  const v=${child}(input,pos,ctx)
9176
- ${emitRollback(p, L.buf, sinks)}
10165
+ ${emitRollback(p, L.buf, L.raw, sinks)}
9177
10166
  if(v===FAIL){EC.e=pos;return null}
9178
10167
  ctx._fe=pos
9179
10168
  ctx._fx=${xf}
@@ -9185,9 +10174,9 @@ return FAIL
9185
10174
  const xf = fxRef(code[ip + 2]);
9186
10175
  const p = tmp();
9187
10176
  return `${head}
9188
- ${emitMark(p, L.buf, sinks)}
10177
+ ${emitMark(p, L.buf, L.raw, sinks)}
9189
10178
  const v=${child}(input,pos,ctx)
9190
- ${emitRollback(p, L.buf, sinks)}
10179
+ ${emitRollback(p, L.buf, L.raw, sinks)}
9191
10180
  if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9192
10181
  EC.e=pos
9193
10182
  return null
@@ -9195,14 +10184,15 @@ return null
9195
10184
  }
9196
10185
  case OP_OPT: {
9197
10186
  const child = link(code[ip + 1]);
10187
+ const clean = !REC2 && failureRollbackClean(prog, ip);
9198
10188
  const p = tmp();
9199
10189
  return `${head}
9200
- ${emitMark(p, L.buf, sinks)}
10190
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
9201
10191
  ctx._fc=false
9202
10192
  const v=${child}(input,pos,ctx)
9203
10193
  if(v===FAIL){
9204
10194
  if(ctx._fc===true)return FAIL
9205
- ${emitRollback(p, L.buf, sinks)}
10195
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
9206
10196
  EC.e=pos
9207
10197
  return null
9208
10198
  }
@@ -9301,57 +10291,193 @@ return FAIL
9301
10291
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
9302
10292
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
9303
10293
  const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
10294
+ const tokenCandidate = tokenChoiceCandidates.get(ip);
10295
+ const pretests = Array.from({ length: n }, (_, i) => {
10296
+ if (tokenCandidate?.arm === i) {
10297
+ return { token: tokenDecisionFor(tokenCandidate.dispatchIp) };
10298
+ }
10299
+ const terminal = leadingScalarTerminal(code, code[base + i], 2, true, true);
10300
+ if (terminal >= 0) {
10301
+ const spec = code[terminal + 1];
10302
+ if ((n === 2 || n === 3 ? scalarSpecs : largeChoiceScalarSpecs).has(spec)) {
10303
+ return { scalar: [recognizerRef(spec)] };
10304
+ }
10305
+ }
10306
+ const family = largeChoiceLiteralFamilies.get(code[base + i]);
10307
+ if (family !== void 0) {
10308
+ return { scalar: family.map((member) => recognizerRef(code[member + 1])) };
10309
+ }
10310
+ const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
10311
+ return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
10312
+ });
9304
10313
  const maskable = n <= 32;
9305
10314
  const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
9306
10315
  if (maskable) maskPlan.push(~di);
9307
10316
  const p = tmp();
9308
- const catchName = maskable ? `_cx${uid++}_` : "";
9309
- if (maskable) {
10317
+ const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
10318
+ const rollbackMask = REC2 ? -1 : encodedRollbackMask;
10319
+ const hasRollback = rollbackMask !== 0;
10320
+ const startFailureExact = arms.every((_arm, i) => {
10321
+ const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
10322
+ if (terminal < 0) return false;
10323
+ const op2 = code[terminal];
10324
+ const spec = k[code[terminal + 1]];
10325
+ const terminalFx = fx[code[terminal + 2]];
10326
+ const armFx = fx[code[base + n + i]];
10327
+ if (terminalFx.length !== armFx.length || terminalFx.some((expected2, at) => expected2 !== armFx[at])) return false;
10328
+ if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
10329
+ return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
10330
+ });
10331
+ const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
10332
+ if (choiceCannotCommit(prog, ip) && !startFailureExact) {
10333
+ const deepAt = Array.from({ length: n }, () => tmp());
10334
+ const deepFx = Array.from({ length: n }, () => tmp());
10335
+ const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
10336
+ const lazyArms = (ascii) => arms.map((arm, i) => {
10337
+ const pretest = pretests[i];
10338
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10339
+ 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("||")})`;
10340
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10341
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10342
+ const gate2 = ascii ? `(bits&${1 << i})!==0${condition}` : `(${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}`;
10343
+ const routeMiss = pretest?.token === void 0 ? "" : `
10344
+ if(${decision}===0){
10345
+ ctx._fc=false
10346
+ {const at=_pfTokEnd
10347
+ ${remember(i, "at", pretest.token.expected)}}
10348
+ }`;
10349
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10350
+ else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
10351
+ ctx._fc=false
10352
+ {const at=_pfSeqEnd
10353
+ ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
10354
+ }`;
10355
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10356
+ `}if(${gate2}){
10357
+ ctx._fc=false
10358
+ {const v=${arm}(input,pos,ctx)
10359
+ if(v!==FAIL)return v}
10360
+ {const at=ctx._fe??pos
10361
+ ${remember(i, "at", "ctx._fx")}}
10362
+ ${rollbackFor(i)}
10363
+ }${routeMiss}${sequenceMiss}`;
10364
+ }).join("\n");
10365
+ const merge = deepAt.map((at, i) => `{const at=${at}??pos
10366
+ const ex=${at}===undefined?${expected[i]}:${deepFx[i]}
10367
+ if(at>best){best=at;acc=_accSet(ex,undefined)}
10368
+ else if(at===best)acc=_accSet(ex,acc)
10369
+ }`).join("\n");
10370
+ const finish = `let best=pos,acc
10371
+ ${merge}
10372
+ ctx._fe=pos;ctx._fx=acc??${choiceFx}
10373
+ return FAIL`;
10374
+ return `${head}
10375
+ const c=lead(input,pos)
10376
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
10377
+ ${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
10378
+ ${maskable ? `if(c<128){
10379
+ const bits=${maskName}[c<0?128:c]
10380
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10381
+ ${lazyArms(true)}
10382
+ }else{
10383
+ ${lazyArms(false)}
10384
+ }
10385
+ ` : lazyArms(false)}
10386
+ ${finish}
10387
+ }`;
10388
+ }
10389
+ const needsCatch = maskable || startFailureExact;
10390
+ const catchName = needsCatch ? `_cx${uid++}_` : "";
10391
+ if (needsCatch) {
9310
10392
  const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
9311
10393
  choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
9312
10394
  ${catchCases}
9313
10395
  }return acc}`);
9314
10396
  }
9315
10397
  const maskArms = maskable ? arms.map((arm, i) => {
9316
- return `if((bits&${1 << i})!==0){
10398
+ const pretest = pretests[i];
10399
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10400
+ 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("||")})`;
10401
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10402
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10403
+ const routeMiss = pretest?.token === void 0 ? "" : `
10404
+ if(${decision}===0){
10405
+ ctx._fc=false
10406
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10407
+ prev=${i + 1}`}
10408
+ {const at=_pfTokEnd
10409
+ if(at>best){best=at;acc=undefined}
10410
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)}
10411
+ }`;
10412
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10413
+ else if((bits&${1 << i})!==0&&${decision}<0){
10414
+ ctx._fc=false
10415
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10416
+ prev=${i + 1}`}
10417
+ {const at=_pfSeqEnd
10418
+ if(at>best){best=at;acc=undefined}
10419
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)}
10420
+ }`;
10421
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10422
+ `}if((bits&${1 << i})!==0${condition}){
9317
10423
  ctx._fc=false
9318
10424
  {const v=${arm}(input,pos,ctx)
9319
10425
  if(v!==FAIL)return v}
9320
- if(best===pos)acc=${catchName}(${i},prev,acc)
9321
- prev=${i + 1}
10426
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10427
+ prev=${i + 1}`}
9322
10428
  {const at=ctx._fe??pos
9323
10429
  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
- }`;
10430
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
10431
+ 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}
10432
+ ${rollbackFor(i)}
10433
+ }${routeMiss}${sequenceMiss}`;
9328
10434
  }).join("\n") : "";
9329
- const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
10435
+ const generalArms = arms.map((arm, i) => {
10436
+ const pretest = pretests[i];
10437
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10438
+ 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("||")})`;
10439
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10440
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10441
+ const miss = pretest?.sequence !== void 0 ? `else if(${decision}<0){
10442
+ ctx._fc=false
10443
+ const at=_pfSeqEnd
10444
+ if(at>best){best=at;acc=undefined}
10445
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)
10446
+ }${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){
10447
+ ctx._fc=false
10448
+ const at=_pfTokEnd
10449
+ if(at>best){best=at;acc=undefined}
10450
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)
10451
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
10452
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10453
+ `}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
9330
10454
  ctx._fc=false
9331
10455
  {const v=${arm}(input,pos,ctx)
9332
10456
  if(v!==FAIL)return v}
9333
10457
  {const at=ctx._fe??pos
9334
10458
  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");
10459
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
10460
+ 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}
10461
+ ${rollbackFor(i)}
10462
+ }${miss}`;
10463
+ }).join("\n");
9339
10464
  return `${head}
9340
10465
  const c=lead(input,pos)
9341
- ${emitMark(p, L.buf, sinks)}
10466
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
9342
10467
  let acc
9343
10468
  let best=pos
9344
10469
  ${maskable ? `if(c<128){
9345
10470
  const bits=${maskName}[c<0?128:c]
9346
- let prev=0
10471
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10472
+ ${startFailureExact ? "" : "let prev=0"}
9347
10473
  ${maskArms}
9348
- if(best===pos)acc=${catchName}(${n},prev,acc)
9349
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
10474
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
10475
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
9350
10476
  return FAIL
9351
10477
  }
9352
10478
  ` : ""}
9353
10479
  ${generalArms}
9354
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
10480
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
9355
10481
  return FAIL
9356
10482
  }`;
9357
10483
  }
@@ -9370,30 +10496,8 @@ return FAIL
9370
10496
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
9371
10497
  const bk = hoist("bk", `DSP[${di}].byKey`);
9372
10498
  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
10499
  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")}
10500
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
9397
10501
  }
9398
10502
  `;
9399
10503
  const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
@@ -9401,33 +10505,43 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
9401
10505
  const m1 = tmp();
9402
10506
  const m2 = tmp();
9403
10507
  const routedCall = (target) => `{const savedRouted=ctx._routed
9404
- ${emitRollback(m1, L.buf, sinks)}
9405
- ${emitMark(m2, L.buf, sinks, false)}
10508
+ ${emitRollback(m1, L.buf, L.raw, sinks)}
10509
+ ${emitMark(m2, L.buf, L.raw, sinks, false)}
9406
10510
  ctx._routed={value:key,span:{start:pos,end:selEnd}}
9407
10511
  try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
9408
10512
  break}`;
9409
10513
  const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
9410
10514
  const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
9411
10515
  const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
10516
+ const armSelection = tokenChoiceDispatches.has(ip) ? `const tp=_pfTokDispatch===${ip}&&_pfTokInput===input&&_pfTokPos===pos
10517
+ let arm
10518
+ if(tp){
10519
+ arm=_pfTokArm
10520
+ _pfTokDispatch=-1
10521
+ _pfTokInput=undefined
10522
+ if(arm===${n})arm=undefined
10523
+ }else{
10524
+ arm=${bk}.get(key)
10525
+ ${fold}${chain}}` : `let arm=${bk}.get(key)
10526
+ ${fold}${chain}`;
9412
10527
  return `${head}
9413
- ${emitMark(m1, L.buf, sinks)}
10528
+ ${emitMark(m1, L.buf, L.raw, sinks)}
9414
10529
  const sv=${selector}(input,pos,ctx)
9415
10530
  if(sv===FAIL)return FAIL
9416
10531
  const selEnd=EC.e
9417
10532
  const key=sv
9418
- let arm=${bk}.get(key)
9419
- ${fold}${chain}
10533
+ ${armSelection}
9420
10534
  if(arm===undefined){
9421
10535
  ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
9422
10536
  }
9423
- ${emitMark(m2, L.buf, sinks)}
10537
+ ${emitMark(m2, L.buf, L.raw, sinks)}
9424
10538
  let v
9425
10539
  switch(arm){
9426
10540
  ${armCases}
9427
10541
  ${fallbackCase}
9428
10542
  }
9429
10543
  if(v===FAIL){
9430
- ${emitRollback(m2, L.buf, sinks)}
10544
+ ${emitRollback(m2, L.buf, L.raw, sinks)}
9431
10545
  ctx._fc=true
9432
10546
  return FAIL
9433
10547
  }
@@ -9463,23 +10577,25 @@ return [key,v]
9463
10577
  const skip = skipFor(L);
9464
10578
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
9465
10579
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
9466
- const pfd = sinks.fd ? `${p}fd` : "0";
10580
+ const pfd = sinks.fd ? `${p}fd` : "undefined";
9467
10581
  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 ? `
10582
+ const rbHelper = L.raw === RAW_OMIT ? "_rbNoRawBuf" : "_rbBuf";
10583
+ const rb = L.buf && L.raw !== 0 ? `${rbHelper}(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
9469
10584
  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)`;
10585
+ 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
10586
  const markSinks = `${sinks.fd ? `
9472
10587
  ${p}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${sinks.er ? `
9473
10588
  ${p}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
10589
+ 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
10590
  const markBody = L.buf ? `const b=ctx._cstBuf
9475
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
10591
+ ${markRaw}
9476
10592
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
9477
10593
  const l=b.tl;${p}tl=l!==undefined?l.length:0
9478
10594
  ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
9479
10595
  ${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}` : `if(needMark){
9480
10596
  const b=ctx._cstBuf
9481
10597
  if(b!==undefined){
9482
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
10598
+ const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
9483
10599
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
9484
10600
  const l=b.tl;${p}tl=l!==undefined?l.length:0
9485
10601
  }else{
@@ -9586,7 +10702,7 @@ const leaf={_tag:'leaf',value,span:{start:pos,end}}
9586
10702
  const kids=[leaf],rawKids=[leaf],span={start:pos,end}
9587
10703
  EC.e=end
9588
10704
  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))"}
10705
+ ${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
10706
  EC.e=end
9591
10707
  return nd
9592
10708
  }`;
@@ -9608,7 +10724,22 @@ return nd
9608
10724
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
9609
10725
  const fields = flags === 18;
9610
10726
  const collapseChildren = flags === 34;
9611
- const publish = `if(sBuf!==undefined){
10727
+ const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
10728
+ if(sBuf.rawOnly!==true){
10729
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
10730
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
10731
+ else sBuf.single=nd
10732
+ }
10733
+ const rawNd=rawEntry(nd,input,pos,end)
10734
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
10735
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
10736
+ else sBuf.rawSingle=rawNd
10737
+ }else if(sCh!==undefined){
10738
+ sCh.push(nd)
10739
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
10740
+ }` : `if(sBuf!==undefined){
10741
+ if(sBuf.noRaw===true)_pushNodeNoRawBuf(ctx,nd)
10742
+ else{
9612
10743
  if(sBuf.rawOnly!==true){
9613
10744
  if(sBuf.ch!==undefined)sBuf.ch.push(nd)
9614
10745
  else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
@@ -9618,6 +10749,7 @@ const rawNd=rawEntry(nd,input,pos,end)
9618
10749
  if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
9619
10750
  else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
9620
10751
  else sBuf.rawSingle=rawNd
10752
+ }
9621
10753
  }else if(sCh!==undefined){
9622
10754
  sCh.push(nd)
9623
10755
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
@@ -9656,6 +10788,7 @@ return nd
9656
10788
  const wantFields = hasFields || hostCst;
9657
10789
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
9658
10790
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
10791
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
9659
10792
  const ty = q(type);
9660
10793
  const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
9661
10794
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
@@ -9669,7 +10802,12 @@ return nd
9669
10802
  value = `nd=_pfHost!==undefined?_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,st,${tags}):{_tag:'node',type:${ty},span,state:st??null,children:kids}`;
9670
10803
  }
9671
10804
  const collapsible = keepChildren && (hostCst || build === void 0 && proj < 0);
9672
- const openCapture = keepChildren ? `const buf={}
10805
+ const openCapture = omitsRaw ? `const buf={noRaw:true,rawLen:0}
10806
+ ctx._cstBuf=buf
10807
+ ctx._cstChildren=undefined
10808
+ ctx._cstLeaves=undefined
10809
+ ctx._cstRawChildren=undefined
10810
+ ctx._cstTriviaLog=undefined` : keepChildren ? `const buf={}
9673
10811
  ctx._cstBuf=buf
9674
10812
  ctx._cstChildren=undefined
9675
10813
  ctx._cstLeaves=undefined
@@ -9680,7 +10818,10 @@ ctx._cstChildren=undefined
9680
10818
  ctx._cstLeaves=undefined
9681
10819
  ctx._cstRawChildren=undefined
9682
10820
  ctx._cstTriviaLog=undefined`;
9683
- const finishCapture = keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
10821
+ const finishCapture = omitsRaw ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
10822
+ const hostKids=kids
10823
+ const rawKids=EMPTY_CH
10824
+ const tlog=buf.tl??EMPTY_TLOG` : keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
9684
10825
  const hostKids=kids
9685
10826
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
9686
10827
  const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
@@ -9714,7 +10855,7 @@ const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):unde
9714
10855
  let nd
9715
10856
  ${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
10857
  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))"}
10858
+ ${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
10859
  EC.e=end
9719
10860
  return nd
9720
10861
  }`;
@@ -9732,7 +10873,7 @@ return nd
9732
10873
  }
9733
10874
  const extra = [];
9734
10875
  for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
9735
- const source = `${RUNTIME_PRELUDE}
10876
+ const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
9736
10877
  ${prelude.join("\n")}
9737
10878
  ${skipDefs.join("\n")}
9738
10879
  ${choiceDefs.join("\n")}
@@ -9747,7 +10888,13 @@ _pfHost=host
9747
10888
  function _finish(){
9748
10889
  if(_pfDepth<=0)throw new Error('parseman emitted table assembly frame underflow')
9749
10890
  _pfDepth--
9750
- if(_pfDepth===0)return
10891
+ if(_pfDepth===0){
10892
+ _pfTokInput=undefined
10893
+ _pfTokBody=-1
10894
+ _pfTokValue=undefined
10895
+ _pfTokDispatch=-1
10896
+ return
10897
+ }
9751
10898
  const prior=_pfFrames.pop()
9752
10899
  _pfScan=prior[0]
9753
10900
  _pfHost=prior[1]
@@ -10109,6 +11256,17 @@ function assemble(t, prog, cfg) {
10109
11256
  }
10110
11257
  return recognize;
10111
11258
  }
11259
+ const labelExtraIps = [];
11260
+ for (const s of prog.scans ?? []) {
11261
+ for (const r of s.skip) labelExtraIps.push(r[0]);
11262
+ if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
11263
+ }
11264
+ for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
11265
+ const closureLabels = computeSiteLabels(
11266
+ code,
11267
+ [...Object.values(prog.rules), ...labelExtraIps],
11268
+ hostCst
11269
+ );
10112
11270
  let SCAN = null;
10113
11271
  const memo = /* @__PURE__ */ new Map();
10114
11272
  const reached = /* @__PURE__ */ new Set();
@@ -10154,12 +11312,12 @@ function assemble(t, prog, cfg) {
10154
11312
  return node2;
10155
11313
  };
10156
11314
  }
10157
- function capturedFlatChildren(children2) {
10158
- if (children2.length === 0) return EMPTY_CH;
10159
- if (children2[0] !== void 0) return children2;
11315
+ function capturedFlatChildren(children3) {
11316
+ if (children3.length === 0) return EMPTY_CH;
11317
+ if (children3[0] !== void 0) return children3;
10160
11318
  let first = 1;
10161
- while (first < children2.length && children2[first] === void 0) first++;
10162
- return first === children2.length ? EMPTY_CH : children2.slice(first);
11319
+ while (first < children3.length && children3[first] === void 0) first++;
11320
+ return first === children3.length ? EMPTY_CH : children3.slice(first);
10163
11321
  }
10164
11322
  function childrenOnlyBuildNode(child, build) {
10165
11323
  return (input, pos, ctx) => {
@@ -10354,7 +11512,7 @@ function assemble(t, prog, cfg) {
10354
11512
  const b = ctx._cstBuf;
10355
11513
  if (b !== void 0) {
10356
11514
  const raw = b.raw;
10357
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
11515
+ MRAW = b.noRaw === true ? b.rawLen ?? 0 : raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10358
11516
  const ch2 = b.ch;
10359
11517
  MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10360
11518
  const tl = b.tl;
@@ -10438,6 +11596,31 @@ function assemble(t, prog, cfg) {
10438
11596
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
10439
11597
  return cur;
10440
11598
  }
11599
+ function nextTermBuffered(child, input, cur, ctx) {
11600
+ if (ctx.trivia === void 0) {
11601
+ const v2 = child(input, cur, ctx);
11602
+ if (v2 === FAIL) return -1;
11603
+ TERMV = v2;
11604
+ return EC.e;
11605
+ }
11606
+ const before = ctx._cstBuf;
11607
+ const beforeTl = before.tl;
11608
+ const mTl = beforeTl === void 0 ? 0 : beforeTl.length;
11609
+ const mLog = ctx._triviaLog?.length ?? 0;
11610
+ const mRoot = ctx._rootTriviaLog?.length ?? 0;
11611
+ const scanEnd = skipTrivia(input, cur, ctx);
11612
+ const scanned = ctx._cstBuf;
11613
+ const scannedTl = scanned.tl;
11614
+ const scanTl = scannedTl === void 0 ? 0 : scannedTl.length;
11615
+ const scanLog = ctx._triviaLog?.length ?? 0;
11616
+ const scanRoot = ctx._rootTriviaLog?.length ?? 0;
11617
+ const v = child(input, scanEnd, ctx);
11618
+ if (v === FAIL) return -1;
11619
+ TERMV = v;
11620
+ if (EC.e > scanEnd) return EC.e;
11621
+ rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
11622
+ return cur;
11623
+ }
10441
11624
  function committed3(c) {
10442
11625
  return c._fc === true;
10443
11626
  }
@@ -10708,7 +11891,8 @@ function assemble(t, prog, cfg) {
10708
11891
  target = p;
10709
11892
  } };
10710
11893
  inFlight.set(ip, holder);
10711
- const piece = lower(ip);
11894
+ const op = code[ip];
11895
+ 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
11896
  inFlight.delete(ip);
10713
11897
  holder.set(piece);
10714
11898
  memo.set(ip, piece);
@@ -11160,11 +12344,11 @@ function assemble(t, prog, cfg) {
11160
12344
  }
11161
12345
  case OP_ROUTED: {
11162
12346
  const fb = code[ip + 1];
11163
- const fallback = fb >= 0 ? link(fb) : void 0;
12347
+ const fallback2 = fb >= 0 ? link(fb) : void 0;
11164
12348
  return (input, pos, ctx) => {
11165
12349
  const item = ctx._routed;
11166
12350
  if (item === void 0 || pos !== item.span.start) {
11167
- if (fallback !== void 0) return fallback(input, pos, ctx);
12351
+ if (fallback2 !== void 0) return fallback2(input, pos, ctx);
11168
12352
  ctx._fe = pos;
11169
12353
  ctx._fx = ROUTED_FX;
11170
12354
  return FAIL;
@@ -11451,6 +12635,7 @@ function assemble(t, prog, cfg) {
11451
12635
  const reducer = fused ? code[ip + 1] : -1;
11452
12636
  const projection = reducer < 0 ? ~reducer : -1;
11453
12637
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
12638
+ const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
11454
12639
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
11455
12640
  if (count === 1) return (input, cur, ctx, values, inherited) => {
11456
12641
  cur = r0(input, cur, ctx, inherited);
@@ -11505,7 +12690,7 @@ function assemble(t, prog, cfg) {
11505
12690
  const kid = link(kidIp);
11506
12691
  return (input, cur, ctx, inherited) => {
11507
12692
  ctx._sync = sync ?? inherited;
11508
- return nextTerm(kid, input, cur, ctx);
12693
+ return step(kid, input, cur, ctx);
11509
12694
  };
11510
12695
  }
11511
12696
  const negated = code[kidIp + 1] === 1;
@@ -11590,7 +12775,7 @@ function assemble(t, prog, cfg) {
11590
12775
  const kidIp = code[base + i];
11591
12776
  if (code[kidIp] !== OP_ADJ) {
11592
12777
  const kid = link(kidIp);
11593
- return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
12778
+ return (input, cur, ctx) => step(kid, input, cur, ctx);
11594
12779
  }
11595
12780
  const negated = code[kidIp + 1] === 1;
11596
12781
  const ki = code[kidIp + 2];
@@ -11679,7 +12864,7 @@ function assemble(t, prog, cfg) {
11679
12864
  return (input, pos, ctx) => {
11680
12865
  const v0 = k0(input, pos, ctx);
11681
12866
  if (v0 === FAIL) return FAIL;
11682
- const cur = nextTerm(k1, input, EC.e, ctx);
12867
+ const cur = step(k1, input, EC.e, ctx);
11683
12868
  if (cur < 0) return FAIL;
11684
12869
  EC.e = cur;
11685
12870
  return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
@@ -11689,7 +12874,7 @@ function assemble(t, prog, cfg) {
11689
12874
  return (input, pos, ctx) => {
11690
12875
  const v0 = k0(input, pos, ctx);
11691
12876
  if (v0 === FAIL) return FAIL;
11692
- const cur = nextTerm(k1, input, EC.e, ctx);
12877
+ const cur = step(k1, input, EC.e, ctx);
11693
12878
  if (cur < 0) return FAIL;
11694
12879
  EC.e = cur;
11695
12880
  return [v0, TERMV];
@@ -11698,7 +12883,7 @@ function assemble(t, prog, cfg) {
11698
12883
  return (input, pos, ctx) => {
11699
12884
  const v0 = k0(input, pos, ctx);
11700
12885
  if (v0 === FAIL) return FAIL;
11701
- const cur = nextTerm(k1, input, EC.e, ctx);
12886
+ const cur = step(k1, input, EC.e, ctx);
11702
12887
  if (cur < 0) return FAIL;
11703
12888
  EC.e = cur;
11704
12889
  return void 0;
@@ -11710,10 +12895,10 @@ function assemble(t, prog, cfg) {
11710
12895
  return (input, pos, ctx) => {
11711
12896
  const v0 = k0(input, pos, ctx);
11712
12897
  if (v0 === FAIL) return FAIL;
11713
- let cur = nextTerm(k1, input, EC.e, ctx);
12898
+ let cur = step(k1, input, EC.e, ctx);
11714
12899
  if (cur < 0) return FAIL;
11715
12900
  const v1 = TERMV;
11716
- cur = nextTerm(k2, input, cur, ctx);
12901
+ cur = step(k2, input, cur, ctx);
11717
12902
  if (cur < 0) return FAIL;
11718
12903
  EC.e = cur;
11719
12904
  return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
@@ -11723,10 +12908,10 @@ function assemble(t, prog, cfg) {
11723
12908
  return (input, pos, ctx) => {
11724
12909
  const v0 = k0(input, pos, ctx);
11725
12910
  if (v0 === FAIL) return FAIL;
11726
- let cur = nextTerm(k1, input, EC.e, ctx);
12911
+ let cur = step(k1, input, EC.e, ctx);
11727
12912
  if (cur < 0) return FAIL;
11728
12913
  const v1 = TERMV;
11729
- cur = nextTerm(k2, input, cur, ctx);
12914
+ cur = step(k2, input, cur, ctx);
11730
12915
  if (cur < 0) return FAIL;
11731
12916
  EC.e = cur;
11732
12917
  return [v0, v1, TERMV];
@@ -11735,9 +12920,9 @@ function assemble(t, prog, cfg) {
11735
12920
  return (input, pos, ctx) => {
11736
12921
  const v0 = k0(input, pos, ctx);
11737
12922
  if (v0 === FAIL) return FAIL;
11738
- let cur = nextTerm(k1, input, EC.e, ctx);
12923
+ let cur = step(k1, input, EC.e, ctx);
11739
12924
  if (cur < 0) return FAIL;
11740
- cur = nextTerm(k2, input, cur, ctx);
12925
+ cur = step(k2, input, cur, ctx);
11741
12926
  if (cur < 0) return FAIL;
11742
12927
  EC.e = cur;
11743
12928
  return void 0;
@@ -11745,43 +12930,43 @@ function assemble(t, prog, cfg) {
11745
12930
  }
11746
12931
  const block = (count, k0, k1, k2, k3, next) => {
11747
12932
  if (count === 1) return (input, cur, ctx, values) => {
11748
- cur = nextTerm(k0, input, cur, ctx);
12933
+ cur = step(k0, input, cur, ctx);
11749
12934
  if (cur < 0) return -1;
11750
12935
  if (values !== void 0) values.push(TERMV);
11751
12936
  return next === void 0 ? cur : next(input, cur, ctx, values);
11752
12937
  };
11753
12938
  if (count === 2) return (input, cur, ctx, values) => {
11754
- cur = nextTerm(k0, input, cur, ctx);
12939
+ cur = step(k0, input, cur, ctx);
11755
12940
  if (cur < 0) return -1;
11756
12941
  if (values !== void 0) values.push(TERMV);
11757
- cur = nextTerm(k1, input, cur, ctx);
12942
+ cur = step(k1, input, cur, ctx);
11758
12943
  if (cur < 0) return -1;
11759
12944
  if (values !== void 0) values.push(TERMV);
11760
12945
  return next === void 0 ? cur : next(input, cur, ctx, values);
11761
12946
  };
11762
12947
  if (count === 3) return (input, cur, ctx, values) => {
11763
- cur = nextTerm(k0, input, cur, ctx);
12948
+ cur = step(k0, input, cur, ctx);
11764
12949
  if (cur < 0) return -1;
11765
12950
  if (values !== void 0) values.push(TERMV);
11766
- cur = nextTerm(k1, input, cur, ctx);
12951
+ cur = step(k1, input, cur, ctx);
11767
12952
  if (cur < 0) return -1;
11768
12953
  if (values !== void 0) values.push(TERMV);
11769
- cur = nextTerm(k2, input, cur, ctx);
12954
+ cur = step(k2, input, cur, ctx);
11770
12955
  if (cur < 0) return -1;
11771
12956
  if (values !== void 0) values.push(TERMV);
11772
12957
  return next === void 0 ? cur : next(input, cur, ctx, values);
11773
12958
  };
11774
12959
  return (input, cur, ctx, values) => {
11775
- cur = nextTerm(k0, input, cur, ctx);
12960
+ cur = step(k0, input, cur, ctx);
11776
12961
  if (cur < 0) return -1;
11777
12962
  if (values !== void 0) values.push(TERMV);
11778
- cur = nextTerm(k1, input, cur, ctx);
12963
+ cur = step(k1, input, cur, ctx);
11779
12964
  if (cur < 0) return -1;
11780
12965
  if (values !== void 0) values.push(TERMV);
11781
- cur = nextTerm(k2, input, cur, ctx);
12966
+ cur = step(k2, input, cur, ctx);
11782
12967
  if (cur < 0) return -1;
11783
12968
  if (values !== void 0) values.push(TERMV);
11784
- cur = nextTerm(k3, input, cur, ctx);
12969
+ cur = step(k3, input, cur, ctx);
11785
12970
  if (cur < 0) return -1;
11786
12971
  if (values !== void 0) values.push(TERMV);
11787
12972
  return next === void 0 ? cur : next(input, cur, ctx, values);
@@ -11952,6 +13137,13 @@ function assemble(t, prog, cfg) {
11952
13137
  if (n === 2 || n === 3) {
11953
13138
  const a0 = link(code[base]), a1 = link(code[base + 1]);
11954
13139
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13140
+ const predecide = !hostCst && !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13141
+ const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13142
+ const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13143
+ const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
13144
+ const p0 = p0ip < 0 ? void 0 : scalarFor(p0ip);
13145
+ const p1 = p1ip < 0 ? void 0 : scalarFor(p1ip);
13146
+ const p2 = p2ip < 0 ? void 0 : scalarFor(p2ip);
11955
13147
  const e0 = fx[code[base + n]];
11956
13148
  const e1 = fx[code[base + n + 1]];
11957
13149
  const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
@@ -11981,7 +13173,10 @@ function assemble(t, prog, cfg) {
11981
13173
  let acc;
11982
13174
  let best = pos;
11983
13175
  if (c < 128) {
11984
- const bits = mask[c < 0 ? 128 : c];
13176
+ let bits = mask[c < 0 ? 128 : c];
13177
+ if ((bits & 1) !== 0 && p0 !== void 0 && p0(input, pos) < 0) bits &= ~1;
13178
+ if ((bits & 2) !== 0 && p1 !== void 0 && p1(input, pos) < 0) bits &= ~2;
13179
+ if ((bits & 4) !== 0 && p2 !== void 0 && p2(input, pos) < 0) bits &= ~4;
11985
13180
  let prev = 0;
11986
13181
  if ((bits & 1) !== 0) {
11987
13182
  ctx._fc = false;
@@ -12044,7 +13239,7 @@ function assemble(t, prog, cfg) {
12044
13239
  ctx._fx = acc ?? choiceFx;
12045
13240
  return FAIL;
12046
13241
  }
12047
- if (g0 === null || classHas2(g0, c)) {
13242
+ if ((g0 === null || classHas2(g0, c)) && (p0 === void 0 || p0(input, pos) >= 0)) {
12048
13243
  ctx._fc = false;
12049
13244
  const v = a0(input, pos, ctx);
12050
13245
  if (v !== FAIL) return v;
@@ -12060,7 +13255,7 @@ function assemble(t, prog, cfg) {
12060
13255
  }
12061
13256
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12062
13257
  } else if (best === pos) acc = accSet(e0, acc);
12063
- if (g1 === null || classHas2(g1, c)) {
13258
+ if ((g1 === null || classHas2(g1, c)) && (p1 === void 0 || p1(input, pos) >= 0)) {
12064
13259
  ctx._fc = false;
12065
13260
  const v = a1(input, pos, ctx);
12066
13261
  if (v !== FAIL) return v;
@@ -12077,7 +13272,7 @@ function assemble(t, prog, cfg) {
12077
13272
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12078
13273
  } else if (best === pos) acc = accSet(e1, acc);
12079
13274
  if (n === 3) {
12080
- if (g2 === null || classHas2(g2, c)) {
13275
+ if ((g2 === null || classHas2(g2, c)) && (p2 === void 0 || p2(input, pos) >= 0)) {
12081
13276
  ctx._fc = false;
12082
13277
  const v = a2(input, pos, ctx);
12083
13278
  if (v !== FAIL) return v;
@@ -12650,20 +13845,14 @@ function assemble(t, prog, cfg) {
12650
13845
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
12651
13846
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
12652
13847
  const rawOnly = !keepChildren;
13848
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
12653
13849
  return (input, pos, ctx) => {
12654
13850
  const host = HOST;
12655
13851
  const sCh = ctx._cstChildren;
12656
- const sLv = ctx._cstLeaves;
12657
- const sRaw = ctx._cstRawChildren;
12658
- const sTl = ctx._cstTriviaLog;
12659
13852
  const sCap = ctx.captureTrivia;
12660
13853
  const sBuf = ctx._cstBuf;
12661
- const buf = rawOnly ? { rawOnly: true } : {};
13854
+ const buf = rawOnly ? { rawOnly: true } : omitsRaw ? { noRaw: true, rawLen: 0 } : {};
12662
13855
  ctx._cstBuf = buf;
12663
- ctx._cstChildren = void 0;
12664
- ctx._cstLeaves = void 0;
12665
- ctx._cstRawChildren = void 0;
12666
- ctx._cstTriviaLog = void 0;
12667
13856
  ctx.captureTrivia = captureWide;
12668
13857
  const savedFields = ctx._fields;
12669
13858
  ctx._fields = wantFields ? [] : void 0;
@@ -12678,13 +13867,9 @@ function assemble(t, prog, cfg) {
12678
13867
  if (structural) ctx._triviaCaptureMask = savedMask;
12679
13868
  const kids = rawOnly ? EMPTY_CH : buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
12680
13869
  const hostKids = kids;
12681
- const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
13870
+ const rawKids = omitsRaw ? EMPTY_CH : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
12682
13871
  const tlog = buf.tl ?? EMPTY_TLOG;
12683
13872
  ctx._cstBuf = sBuf;
12684
- ctx._cstChildren = sCh;
12685
- ctx._cstLeaves = sLv;
12686
- ctx._cstRawChildren = sRaw;
12687
- ctx._cstTriviaLog = sTl;
12688
13873
  ctx.captureTrivia = sCap;
12689
13874
  if (v === FAIL) return FAIL;
12690
13875
  const end = EC.e;
@@ -12775,6 +13960,34 @@ function assemble(t, prog, cfg) {
12775
13960
  rawScalarSpecs.add(code[child + 1]);
12776
13961
  scalarFor(child);
12777
13962
  }
13963
+ } else if (code[ip] === OP_CHOICE && !disp[code[ip + 1]].exclusive) {
13964
+ const n = code[ip + 2];
13965
+ for (let i = 0; i < n; i++) {
13966
+ const armIp = code[ip + 4 + i];
13967
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
13968
+ if (n === 2 || n === 3) {
13969
+ if (child >= 0) scalarFor(child);
13970
+ continue;
13971
+ }
13972
+ if (child >= 0) {
13973
+ const spec = k[code[child + 1]];
13974
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
13975
+ scalarFor(child);
13976
+ continue;
13977
+ }
13978
+ }
13979
+ const family = leadingLiteralFamily(code, k, armIp);
13980
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
13981
+ const value = k[code[terminal + 1]];
13982
+ return typeof value === "string" && value.length >= 2;
13983
+ })) {
13984
+ for (const terminal of family) scalarFor(terminal);
13985
+ }
13986
+ const sequence6 = leadingScalarSequence(code, armIp);
13987
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
13988
+ for (const terminal of sequence6.terminals) scalarFor(terminal);
13989
+ }
13990
+ }
12778
13991
  }
12779
13992
  }
12780
13993
  const notChild = scalarTerminalNotChild(code, ip);
@@ -13196,7 +14409,7 @@ function emitAssemblies(prog, cfgs) {
13196
14409
  seen.add(key);
13197
14410
  let em;
13198
14411
  try {
13199
- em = emitAssemblySource(t, prog, cfg, extraIps);
14412
+ em = emitAssemblySource(t, prog, cfg, extraIps, true);
13200
14413
  } catch (e) {
13201
14414
  if (e instanceof Unemittable) continue;
13202
14415
  throw e;
@@ -13655,10 +14868,10 @@ function boundaryMatches(boundary, ch2) {
13655
14868
  if (/\s/.test(ch2)) return true;
13656
14869
  continue;
13657
14870
  }
13658
- const range = /^(.|\\u[0-9a-f]{4})-(.|\\u[0-9a-f]{4})$/.exec(m);
13659
- if (range !== null) {
14871
+ const range2 = /^(.|\\u[0-9a-f]{4})-(.|\\u[0-9a-f]{4})$/.exec(m);
14872
+ if (range2 !== null) {
13660
14873
  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;
14874
+ if (cp >= dec(range2[1]) && cp <= dec(range2[2])) return true;
13662
14875
  continue;
13663
14876
  }
13664
14877
  if (m === ch2) return true;
@@ -14732,7 +15945,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
14732
15945
  };
14733
15946
  const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
14734
15947
  const artifact = closureArtifact(prog);
14735
- const entry = tableRules(artifact)[ENTRY];
15948
+ const entry = tableRules(prog)[ENTRY];
14736
15949
  const offered = opts.fnSources ?? mapFnSources;
14737
15950
  const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
14738
15951
  const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
@@ -14781,106 +15994,6 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
14781
15994
  };
14782
15995
  }
14783
15996
 
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
15997
  // src/combinators/withCtx.ts
14885
15998
  function withCtx(extra, combinator) {
14886
15999
  const meta = {
@@ -15023,7 +16136,7 @@ function evalRuleMapIR(ir) {
15023
16136
  l._def.fnSrc = src;
15024
16137
  return l;
15025
16138
  };
15026
- const _nd = (type, child, src, opts, staticError, sigSrc, buildImports) => {
16139
+ const _nd = (type, child, src, opts, staticError, sigSrc, buildImports, rawUnused) => {
15027
16140
  if (staticError !== void 0 && staticError.length > 0) {
15028
16141
  throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
15029
16142
  }
@@ -15033,6 +16146,7 @@ function evalRuleMapIR(ir) {
15033
16146
  n._def.buildSrc = src;
15034
16147
  if (staticError !== void 0) n._def.buildStaticError = staticError;
15035
16148
  if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
16149
+ if (rawUnused === true) n._def.buildRawUnused = true;
15036
16150
  if (buildImports !== void 0) n._def.buildImports = buildImports;
15037
16151
  return n;
15038
16152
  };
@@ -15425,12 +16539,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
15425
16539
  }
15426
16540
  if (def.buildSrc !== void 0) {
15427
16541
  const tail = [];
15428
- if (def.buildStaticError !== void 0 || def.buildSigSrc !== void 0 || def.buildImports !== void 0) {
16542
+ if (def.buildStaticError !== void 0 || def.buildSigSrc !== void 0 || def.buildImports !== void 0 || def.buildRawUnused === true) {
15429
16543
  if (!opts) tail.push("undefined");
15430
16544
  tail.push(def.buildStaticError === void 0 ? "undefined" : JSON.stringify(def.buildStaticError));
15431
16545
  }
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));
16546
+ if (def.buildSigSrc !== void 0 || def.buildImports !== void 0 || def.buildRawUnused === true) tail.push(def.buildSigSrc === void 0 ? "undefined" : JSON.stringify(def.buildSigSrc));
16547
+ if (def.buildImports !== void 0 || def.buildRawUnused === true) tail.push(def.buildImports === void 0 ? "undefined" : JSON.stringify(def.buildImports));
16548
+ if (def.buildRawUnused === true) tail.push("true");
15434
16549
  const trailing = tail.length > 0 ? `, ${tail.join(", ")}` : "";
15435
16550
  return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${trailing})`;
15436
16551
  }
@@ -15499,7 +16614,7 @@ function compileRuleMapRunnable(ruleMap, opts = {}) {
15499
16614
  hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
15500
16615
  reflection: collectGrammarReflection(ruleMap),
15501
16616
  ...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
15502
- rules: tableRules(artifact),
16617
+ rules: tableRules(prog),
15503
16618
  prog: artifact
15504
16619
  };
15505
16620
  }
@@ -15571,13 +16686,13 @@ function compileRuleMap(ruleMap, opts = {}) {
15571
16686
  hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
15572
16687
  reflection: collectGrammarReflection(ruleMap),
15573
16688
  ...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
15574
- rules: tableRules(artifact),
16689
+ rules: tableRules(prog),
15575
16690
  prog: artifact
15576
16691
  };
15577
16692
  }
15578
16693
 
15579
16694
  // src/version.ts
15580
- var PARSEMAN_VERSION = "0.49.0";
16695
+ var PARSEMAN_VERSION = "0.50.1";
15581
16696
 
15582
16697
  // src/compiler/compile-linkable-table.ts
15583
16698
  function isLocal(rule) {
@@ -15653,16 +16768,16 @@ function normalizeCstCollapse(collapse) {
15653
16768
  }
15654
16769
  return typeof collapse === "function" ? collapse : void 0;
15655
16770
  }
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] };
16771
+ function buildCstNode(type, children3, _fields, span, _rawChildren, _triviaLog, state, tags) {
16772
+ 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
16773
  }
15659
- function cstBuildHost(typeOrOptions, children2, _fields, span, rawChildren, triviaLog, state, _tags) {
16774
+ function cstBuildHost(typeOrOptions, children3, _fields, span, rawChildren, triviaLog, state, _tags) {
15660
16775
  if (typeof typeOrOptions === "string") {
15661
- return buildCstNode(typeOrOptions, children2 ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
16776
+ return buildCstNode(typeOrOptions, children3 ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
15662
16777
  }
15663
16778
  const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
15664
16779
  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);
16780
+ const host = (type, children4, fields, span2, rawChildren2, triviaLog2, state2, tags) => buildCstNode(type, children4 ?? [], fields, span2, rawChildren2, triviaLog2, state2, materializeTags ? tags : void 0);
15666
16781
  host._parsemanCstOutput = true;
15667
16782
  if (collapse) host._parsemanCstCollapse = collapse;
15668
16783
  return host;
@@ -15818,39 +16933,39 @@ function directBuilderBindings(src) {
15818
16933
  if (selfName?.type === "Identifier" && typeof selfName.name === "string") allowed.add(selfName.name);
15819
16934
  const structural = /* @__PURE__ */ new Set();
15820
16935
  const free = /* @__PURE__ */ new Set();
15821
- const reportUnsupportedNode = (ast) => {
15822
- structural.add(`unsupported ${ast.type}`);
16936
+ const reportUnsupportedNode = (ast2) => {
16937
+ structural.add(`unsupported ${ast2.type}`);
15823
16938
  };
15824
- const read = (ast, allowedNames) => {
15825
- if (typeof ast.name === "string" && allowedNames.has(ast.name)) return;
15826
- if (ast.name === "arguments") {
16939
+ const read = (ast2, allowedNames) => {
16940
+ if (typeof ast2.name === "string" && allowedNames.has(ast2.name)) return;
16941
+ if (ast2.name === "arguments") {
15827
16942
  structural.add("unsupported arguments");
15828
16943
  return;
15829
16944
  }
15830
- if (typeof ast.name === "string") free.add(ast.name);
16945
+ if (typeof ast2.name === "string") free.add(ast2.name);
15831
16946
  else structural.add("unsupported identifier");
15832
16947
  };
15833
16948
  const expression = (node2, allowedNames) => {
15834
- const ast = astChild(node2);
15835
- if (!ast) return;
15836
- switch (ast.type) {
16949
+ const ast2 = astChild(node2);
16950
+ if (!ast2) return;
16951
+ switch (ast2.type) {
15837
16952
  case "Literal":
15838
16953
  return;
15839
16954
  case "Identifier":
15840
- read(ast, allowedNames);
16955
+ read(ast2, allowedNames);
15841
16956
  return;
15842
16957
  case "ParenthesizedExpression":
15843
16958
  case "ChainExpression":
15844
16959
  case "TSAsExpression":
15845
16960
  case "TSTypeAssertion":
15846
16961
  case "TSNonNullExpression":
15847
- expression(ast.expression, allowedNames);
16962
+ expression(ast2.expression, allowedNames);
15848
16963
  return;
15849
16964
  case "ArrayExpression":
15850
- for (const element of astArray(ast.elements)) expression(element, allowedNames);
16965
+ for (const element of astArray(ast2.elements)) expression(element, allowedNames);
15851
16966
  return;
15852
16967
  case "ObjectExpression":
15853
- for (const property of astArray(ast.properties)) {
16968
+ for (const property of astArray(ast2.properties)) {
15854
16969
  if (property.type === "SpreadElement") {
15855
16970
  expression(property.argument, allowedNames);
15856
16971
  continue;
@@ -15864,109 +16979,109 @@ function directBuilderBindings(src) {
15864
16979
  }
15865
16980
  return;
15866
16981
  case "MemberExpression":
15867
- expression(ast.object, allowedNames);
15868
- if (ast.computed === true) expression(ast.property, allowedNames);
16982
+ expression(ast2.object, allowedNames);
16983
+ if (ast2.computed === true) expression(ast2.property, allowedNames);
15869
16984
  return;
15870
16985
  case "CallExpression":
15871
16986
  case "NewExpression":
15872
- expression(ast.callee, allowedNames);
15873
- for (const argument of astArray(ast.arguments)) expression(argument, allowedNames);
16987
+ expression(ast2.callee, allowedNames);
16988
+ for (const argument of astArray(ast2.arguments)) expression(argument, allowedNames);
15874
16989
  return;
15875
16990
  case "UnaryExpression":
15876
16991
  case "UpdateExpression":
15877
- expression(ast.argument, allowedNames);
16992
+ expression(ast2.argument, allowedNames);
15878
16993
  return;
15879
16994
  case "BinaryExpression":
15880
16995
  case "LogicalExpression":
15881
16996
  case "AssignmentExpression":
15882
- expression(ast.left, allowedNames);
15883
- expression(ast.right, allowedNames);
16997
+ expression(ast2.left, allowedNames);
16998
+ expression(ast2.right, allowedNames);
15884
16999
  return;
15885
17000
  case "ConditionalExpression":
15886
- expression(ast.test, allowedNames);
15887
- expression(ast.consequent, allowedNames);
15888
- expression(ast.alternate, allowedNames);
17001
+ expression(ast2.test, allowedNames);
17002
+ expression(ast2.consequent, allowedNames);
17003
+ expression(ast2.alternate, allowedNames);
15889
17004
  return;
15890
17005
  case "SequenceExpression":
15891
- for (const value of astArray(ast.expressions)) expression(value, allowedNames);
17006
+ for (const value of astArray(ast2.expressions)) expression(value, allowedNames);
15892
17007
  return;
15893
17008
  case "TemplateLiteral":
15894
- for (const value of astArray(ast.expressions)) expression(value, allowedNames);
17009
+ for (const value of astArray(ast2.expressions)) expression(value, allowedNames);
15895
17010
  return;
15896
17011
  case "SpreadElement":
15897
- expression(ast.argument, allowedNames);
17012
+ expression(ast2.argument, allowedNames);
15898
17013
  return;
15899
17014
  case "ArrowFunctionExpression": {
15900
17015
  const nested = new Set(allowedNames);
15901
- for (const param of astArray(ast.params)) {
17016
+ for (const param of astArray(ast2.params)) {
15902
17017
  if (param.type !== "Identifier" || typeof param.name !== "string") {
15903
17018
  reportUnsupportedNode(param);
15904
17019
  continue;
15905
17020
  }
15906
17021
  nested.add(param.name);
15907
17022
  }
15908
- const nestedBody = astChild(ast.body);
17023
+ const nestedBody = astChild(ast2.body);
15909
17024
  if (nestedBody?.type === "BlockStatement") {
15910
17025
  statement(nestedBody, nested);
15911
17026
  return;
15912
17027
  }
15913
- expression(ast.body, nested);
17028
+ expression(ast2.body, nested);
15914
17029
  return;
15915
17030
  }
15916
17031
  default:
15917
- reportUnsupportedNode(ast);
17032
+ reportUnsupportedNode(ast2);
15918
17033
  return;
15919
17034
  }
15920
17035
  };
15921
17036
  const statement = (node2, names) => {
15922
- const ast = astChild(node2);
15923
- if (!ast) return;
15924
- switch (ast.type) {
17037
+ const ast2 = astChild(node2);
17038
+ if (!ast2) return;
17039
+ switch (ast2.type) {
15925
17040
  case "VariableDeclaration":
15926
- for (const d of astArray(ast.declarations)) {
17041
+ for (const d of astArray(ast2.declarations)) {
15927
17042
  expression(d.init, names);
15928
17043
  const idAst = astChild(d.id);
15929
17044
  if (idAst?.type === "Identifier" && typeof idAst.name === "string") names.add(idAst.name);
15930
- else reportUnsupportedNode(idAst ?? ast);
17045
+ else reportUnsupportedNode(idAst ?? ast2);
15931
17046
  }
15932
17047
  return;
15933
17048
  case "ReturnStatement":
15934
- expression(ast.argument, names);
17049
+ expression(ast2.argument, names);
15935
17050
  return;
15936
17051
  case "ExpressionStatement":
15937
- expression(ast.expression, names);
17052
+ expression(ast2.expression, names);
15938
17053
  return;
15939
17054
  case "ThrowStatement":
15940
- expression(ast.argument, names);
17055
+ expression(ast2.argument, names);
15941
17056
  return;
15942
17057
  case "IfStatement":
15943
- expression(ast.test, names);
15944
- statement(ast.consequent, new Set(names));
15945
- if (ast.alternate) statement(ast.alternate, new Set(names));
17058
+ expression(ast2.test, names);
17059
+ statement(ast2.consequent, new Set(names));
17060
+ if (ast2.alternate) statement(ast2.alternate, new Set(names));
15946
17061
  return;
15947
17062
  case "ForStatement": {
15948
17063
  const inner = new Set(names);
15949
- if (ast.init) {
15950
- const initAst = astChild(ast.init);
17064
+ if (ast2.init) {
17065
+ const initAst = astChild(ast2.init);
15951
17066
  if (initAst?.type === "VariableDeclaration") statement(initAst, inner);
15952
17067
  else expression(initAst, inner);
15953
17068
  }
15954
- if (ast.test) expression(ast.test, inner);
15955
- if (ast.update) expression(ast.update, inner);
15956
- statement(ast.body, inner);
17069
+ if (ast2.test) expression(ast2.test, inner);
17070
+ if (ast2.update) expression(ast2.update, inner);
17071
+ statement(ast2.body, inner);
15957
17072
  return;
15958
17073
  }
15959
17074
  case "ForOfStatement":
15960
17075
  case "ForInStatement": {
15961
17076
  const inner = new Set(names);
15962
- statement(ast.left, inner);
15963
- expression(ast.right, names);
15964
- statement(ast.body, inner);
17077
+ statement(ast2.left, inner);
17078
+ expression(ast2.right, names);
17079
+ statement(ast2.body, inner);
15965
17080
  return;
15966
17081
  }
15967
17082
  case "BlockStatement": {
15968
17083
  const inner = new Set(names);
15969
- for (const s of astArray(ast.body)) statement(s, inner);
17084
+ for (const s of astArray(ast2.body)) statement(s, inner);
15970
17085
  return;
15971
17086
  }
15972
17087
  case "BreakStatement":
@@ -15974,7 +17089,7 @@ function directBuilderBindings(src) {
15974
17089
  case "EmptyStatement":
15975
17090
  return;
15976
17091
  default:
15977
- reportUnsupportedNode(ast);
17092
+ reportUnsupportedNode(ast2);
15978
17093
  return;
15979
17094
  }
15980
17095
  };
@@ -16413,6 +17528,7 @@ function exprToCombi(node2, scope, code, mfs) {
16413
17528
  try {
16414
17529
  const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
16415
17530
  if (combi._def.tag === "node" && buildSrc !== void 0) {
17531
+ const authorDeclaredBuildArity = opts?.buildArity !== void 0;
16416
17532
  combi._def.buildSrc = buildSrc;
16417
17533
  if (explicitType !== void 0 && firstArg.type === "Identifier") {
16418
17534
  combi._def.typeSrc = firstArg.name;
@@ -16427,6 +17543,9 @@ function exprToCombi(node2, scope, code, mfs) {
16427
17543
  if (resolved.reason !== void 0) combi._def.buildArityUnresolved = resolved.reason;
16428
17544
  }
16429
17545
  const analysisSrc = combi._def.buildSigSrc ?? buildSrc;
17546
+ if (!authorDeclaredBuildArity && confirmedBuildParamUnused(analysisSrc, 3)) {
17547
+ combi._def.buildRawUnused = true;
17548
+ }
16430
17549
  const report = directBuilderBindings(analysisSrc);
16431
17550
  const isInlineBuilder = combi._def.buildSigSrc === void 0;
16432
17551
  const carriedImports = [];
@@ -16980,8 +18099,8 @@ var SCOPE_TYPES = /* @__PURE__ */ new Set([
16980
18099
  "ClassExpression",
16981
18100
  "StaticBlock"
16982
18101
  ]);
16983
- function newScope(start, end, parent, isFunction) {
16984
- const s = { start, end, bindings: /* @__PURE__ */ new Map(), children: [], parent, isFunction };
18102
+ function newScope(start, end, parent, isFunction2) {
18103
+ const s = { start, end, bindings: /* @__PURE__ */ new Map(), children: [], parent, isFunction: isFunction2 };
16985
18104
  parent?.children.push(s);
16986
18105
  return s;
16987
18106
  }
@@ -17567,6 +18686,456 @@ function findFreeIdentifiers(code, filename) {
17567
18686
  }).map(({ name, line, column, enclosing }) => ({ name, line, column, enclosing }));
17568
18687
  }
17569
18688
 
18689
+ // src/plugin/entry-supercompiler.ts
18690
+ import { parseSync as parseSync4 } from "oxc-parser";
18691
+ var PIECE = /^_pf(\d+)$/;
18692
+ var WRAP = "function __parseman_supercompile__(){\n";
18693
+ var SUFFIX = "\n}";
18694
+ function ast(value) {
18695
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
18696
+ }
18697
+ function nodes(value) {
18698
+ return Array.isArray(value) ? value.filter((v) => ast(v) !== void 0) : [];
18699
+ }
18700
+ function nameOf(node2) {
18701
+ return node2?.type === "Identifier" && typeof node2.name === "string" ? node2.name : void 0;
18702
+ }
18703
+ function range(node2) {
18704
+ if (typeof node2.start !== "number" || typeof node2.end !== "number") throw new Error("entry supercompiler: AST node without range");
18705
+ return { start: node2.start - WRAP.length, end: node2.end - WRAP.length };
18706
+ }
18707
+ function children2(node2) {
18708
+ const out = [];
18709
+ for (const [key, value] of Object.entries(node2)) {
18710
+ if (key === "type" || key === "start" || key === "end") continue;
18711
+ if (Array.isArray(value)) {
18712
+ for (const child of value) {
18713
+ const c = ast(child);
18714
+ if (c !== void 0) out.push(c);
18715
+ }
18716
+ } else {
18717
+ const c = ast(value);
18718
+ if (c !== void 0) out.push(c);
18719
+ }
18720
+ }
18721
+ return out;
18722
+ }
18723
+ function isFunction(node2) {
18724
+ return node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression";
18725
+ }
18726
+ function isDirectCallUse(call, parent, statement) {
18727
+ if (parent === void 0) return false;
18728
+ if (parent.type === "VariableDeclarator") {
18729
+ const declarations = statement.type === "VariableDeclaration" ? nodes(statement.declarations) : [];
18730
+ return declarations.length === 1 && declarations[0] === parent && parent.init === call;
18731
+ }
18732
+ if (parent.type === "AssignmentExpression") {
18733
+ return statement.type === "ExpressionStatement" && statement.expression === parent && nameOf(ast(parent.left)) !== void 0 && parent.right === call && parent.operator === "=";
18734
+ }
18735
+ if (parent.type === "ReturnStatement") return statement === parent && parent.argument === call;
18736
+ return false;
18737
+ }
18738
+ function isListStatement(statement, parent) {
18739
+ if (parent?.type === "BlockStatement") return nodes(parent.body).includes(statement);
18740
+ if (parent?.type === "SwitchCase") return nodes(parent.consequent).includes(statement);
18741
+ return false;
18742
+ }
18743
+ function hasInlineScopeHazard(fn) {
18744
+ if (fn.node.async === true || fn.node.generator === true) return true;
18745
+ let hazard = false;
18746
+ const walk = (node2) => {
18747
+ if (hazard) return;
18748
+ if (node2.type === "Identifier" && node2.name === "arguments") hazard = true;
18749
+ else if (node2.type === "ThisExpression") hazard = true;
18750
+ else if (node2.type === "VariableDeclaration" && node2.kind === "var") hazard = true;
18751
+ else if (node2.type === "MetaProperty" && nameOf(ast(node2.meta)) === "new" && nameOf(ast(node2.property)) === "target") hazard = true;
18752
+ else for (const child of children2(node2)) walk(child);
18753
+ };
18754
+ walk(fn.body);
18755
+ return hazard;
18756
+ }
18757
+ function hasInlineSignature(fn) {
18758
+ const params = nodes(fn.node.params);
18759
+ return params.length === 3 && nameOf(params[0]) === "input" && nameOf(params[1]) === "pos" && nameOf(params[2]) === "ctx";
18760
+ }
18761
+ function render2(source, start, end, edits) {
18762
+ const ordered = [...edits].sort((a, b) => a.start - b.start || a.end - b.end);
18763
+ let at = start;
18764
+ let out = "";
18765
+ for (const edit of ordered) {
18766
+ if (edit.start < at || edit.end < edit.start || edit.start < start || edit.end > end) {
18767
+ throw new Error("entry supercompiler: overlapping or out-of-range structured edit");
18768
+ }
18769
+ out += source.slice(at, edit.start) + edit.text;
18770
+ at = edit.end;
18771
+ }
18772
+ return out + source.slice(at, end);
18773
+ }
18774
+ function recursiveMembers(fns) {
18775
+ let next = 0;
18776
+ const index = /* @__PURE__ */ new Map();
18777
+ const low = /* @__PURE__ */ new Map();
18778
+ const stack = [];
18779
+ const on = /* @__PURE__ */ new Set();
18780
+ const recursive = /* @__PURE__ */ new Set();
18781
+ const visit = (ip) => {
18782
+ index.set(ip, next);
18783
+ low.set(ip, next);
18784
+ next++;
18785
+ stack.push(ip);
18786
+ on.add(ip);
18787
+ for (const call of fns.get(ip)?.calls ?? []) {
18788
+ if (!fns.has(call.callee)) continue;
18789
+ if (!index.has(call.callee)) {
18790
+ visit(call.callee);
18791
+ low.set(ip, Math.min(low.get(ip), low.get(call.callee)));
18792
+ } else if (on.has(call.callee)) low.set(ip, Math.min(low.get(ip), index.get(call.callee)));
18793
+ }
18794
+ if (low.get(ip) !== index.get(ip)) return;
18795
+ const component = [];
18796
+ for (; ; ) {
18797
+ const member = stack.pop();
18798
+ on.delete(member);
18799
+ component.push(member);
18800
+ if (member === ip) break;
18801
+ }
18802
+ if (component.length > 1 || component.some((member) => fns.get(member).calls.some((c) => c.callee === member))) {
18803
+ for (const member of component) recursive.add(member);
18804
+ }
18805
+ };
18806
+ for (const ip of fns.keys()) if (!index.has(ip)) visit(ip);
18807
+ return recursive;
18808
+ }
18809
+ function fallback(emitted, reason, before) {
18810
+ return {
18811
+ ...emitted,
18812
+ supercompile: {
18813
+ ...before,
18814
+ activated: false,
18815
+ reason,
18816
+ functionsAfter: before.functionsBefore,
18817
+ pieceCallsAfter: before.pieceCallsBefore,
18818
+ sourceAfter: before.sourceBefore,
18819
+ regions: before.functionsBefore,
18820
+ largestRegionSource: 0,
18821
+ protocolRegions: { node: 0, repv: 0, nodeAndRepv: 0 }
18822
+ }
18823
+ };
18824
+ }
18825
+ function supercompileRuleMapReplacement(prog, replacement) {
18826
+ const cfg = defaultAssemblyCfgs(prog)[0];
18827
+ if (cfg === void 0) return replacement;
18828
+ const extraIps = [];
18829
+ for (const scan of prog.scans ?? []) {
18830
+ for (const ref2 of scan.skip) extraIps.push(ref2[0]);
18831
+ if (scan.sentinel !== void 0) extraIps.push(scan.sentinel[0]);
18832
+ }
18833
+ for (const set of prog.scanSkip ?? []) for (const ref2 of set) extraIps.push(ref2[0]);
18834
+ let canonical2;
18835
+ let candidate;
18836
+ try {
18837
+ canonical2 = emitAssemblySource(resolveTable(prog), prog, cfg, extraIps, true);
18838
+ candidate = supercompileEmittedAssembly(prog, cfg, extraIps, canonical2);
18839
+ } catch {
18840
+ return replacement;
18841
+ }
18842
+ if (!candidate.supercompile.activated) return replacement;
18843
+ const prefix = "const __parseman_macro_replacement__=";
18844
+ const parsed = parseSync4("parseman-entry-supercompile-replacement.js", prefix + replacement);
18845
+ if (parsed.errors.length > 0) return replacement;
18846
+ const program = parsed.program;
18847
+ const declaration = nodes(program.body)[0];
18848
+ const declarator = nodes(declaration?.declarations)[0];
18849
+ const call = ast(declarator?.init);
18850
+ const table = nodes(call?.arguments)[0];
18851
+ if (declaration?.type !== "VariableDeclaration" || declarator?.type !== "VariableDeclarator" || call?.type !== "CallExpression" || table?.type !== "ObjectExpression") return replacement;
18852
+ const property = (object, key) => nodes(object.properties).find((prop) => prop.type === "Property" && nameOf(ast(prop.key)) === key);
18853
+ const assembliesProp = property(table, "a");
18854
+ const assemblies = nodes(ast(assembliesProp?.value)?.elements);
18855
+ if (assembliesProp === void 0 || assemblies.length !== 1 || assemblies[0]?.type !== "ObjectExpression") return replacement;
18856
+ const factoryProp = property(assemblies[0], "factory");
18857
+ const factory = ast(factoryProp?.value);
18858
+ const body = ast(factory?.body);
18859
+ if (factory?.type !== "FunctionExpression" || body?.type !== "BlockStatement") return replacement;
18860
+ if (typeof body.start !== "number" || typeof body.end !== "number") return replacement;
18861
+ const start = body.start - prefix.length + 1;
18862
+ const end = body.end - prefix.length - 1;
18863
+ if (replacement.slice(start, end) !== canonical2.source + "\n") return replacement;
18864
+ const transformed = replacement.slice(0, start) + candidate.source + "\n" + replacement.slice(end);
18865
+ const checked = parseSync4("parseman-entry-supercompile-replacement-result.js", prefix + transformed);
18866
+ return checked.errors.length === 0 ? transformed : replacement;
18867
+ }
18868
+ function supercompileEmittedAssembly(prog, _cfg, extraIps, emitted) {
18869
+ const source = emitted.source;
18870
+ const parsed = parseSync4("parseman-entry-supercompile.js", WRAP + source + SUFFIX);
18871
+ if (parsed.errors.length > 0) {
18872
+ const zero = { functionsBefore: 0, pieceCallsBefore: 0, sourceBefore: source.length, barriers: {} };
18873
+ return fallback(emitted, "canonical emitted source did not parse", zero);
18874
+ }
18875
+ const program = parsed.program;
18876
+ const wrapper = nodes(program.body)[0];
18877
+ const wrapperBody = ast(wrapper?.body);
18878
+ if (wrapper?.type !== "FunctionDeclaration" || wrapperBody?.type !== "BlockStatement") {
18879
+ const zero = { functionsBefore: 0, pieceCallsBefore: 0, sourceBefore: source.length, barriers: {} };
18880
+ return fallback(emitted, "missing compiler wrapper", zero);
18881
+ }
18882
+ const fns = /* @__PURE__ */ new Map();
18883
+ for (const statement of nodes(wrapperBody.body)) {
18884
+ if (statement.type !== "FunctionDeclaration") continue;
18885
+ const name = nameOf(ast(statement.id));
18886
+ const hit = name === void 0 ? void 0 : PIECE.exec(name);
18887
+ const body = ast(statement.body);
18888
+ if (hit !== void 0 && hit !== null && body?.type === "BlockStatement") {
18889
+ const ip = Number(hit[1]);
18890
+ fns.set(ip, { ip, name, node: statement, body, calls: [] });
18891
+ }
18892
+ }
18893
+ const externalRefs = /* @__PURE__ */ new Set();
18894
+ let reservedCollision = false;
18895
+ const allCalls = [];
18896
+ const walk = (node2, current, parent, statement, statementParent) => {
18897
+ if (isFunction(node2) && node2 !== current?.node) {
18898
+ const own = node2.type === "FunctionDeclaration" ? nameOf(ast(node2.id)) : void 0;
18899
+ const hit = own === void 0 ? void 0 : PIECE.exec(own);
18900
+ if (hit !== void 0 && hit !== null) {
18901
+ const fn = fns.get(Number(hit[1]));
18902
+ if (fn !== void 0) {
18903
+ for (const child of children2(node2)) {
18904
+ if (child !== ast(node2.id)) walk(child, fn, node2, void 0, void 0);
18905
+ }
18906
+ return;
18907
+ }
18908
+ }
18909
+ current = void 0;
18910
+ }
18911
+ let owner2 = statement;
18912
+ let ownerParent = statementParent;
18913
+ if (parent?.type === "BlockStatement" && nodes(parent.body).includes(node2)) {
18914
+ owner2 = node2;
18915
+ ownerParent = parent;
18916
+ }
18917
+ if (parent?.type === "SwitchCase" && nodes(parent.consequent).includes(node2)) {
18918
+ owner2 = node2;
18919
+ ownerParent = parent;
18920
+ }
18921
+ if (node2.type === "CallExpression") {
18922
+ const calleeName = nameOf(ast(node2.callee));
18923
+ const hit = calleeName === void 0 ? void 0 : PIECE.exec(calleeName);
18924
+ if (hit !== void 0 && hit !== null) {
18925
+ const callee = Number(hit[1]);
18926
+ const args = nodes(node2.arguments);
18927
+ 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);
18928
+ if (current === void 0 || owner2 === void 0) externalRefs.add(callee);
18929
+ else {
18930
+ const call = { caller: current.ip, callee, node: node2, statement: owner2, args, transformable };
18931
+ current.calls.push(call);
18932
+ allCalls.push(call);
18933
+ }
18934
+ }
18935
+ }
18936
+ if (node2.type === "Identifier") {
18937
+ if (typeof node2.name === "string" && /^_z\d/.test(node2.name)) reservedCollision = true;
18938
+ const hit = typeof node2.name === "string" ? PIECE.exec(node2.name) : null;
18939
+ if (hit !== null) {
18940
+ const isDecl = parent?.type === "FunctionDeclaration" && parent.id === node2;
18941
+ const isCall = parent?.type === "CallExpression" && parent.callee === node2;
18942
+ if (!isDecl && !isCall) externalRefs.add(Number(hit[1]));
18943
+ }
18944
+ }
18945
+ for (const child of children2(node2)) walk(child, current, node2, owner2, ownerParent);
18946
+ };
18947
+ for (const statement of nodes(wrapperBody.body)) walk(statement, void 0, wrapperBody, void 0, void 0);
18948
+ if (reservedCollision) {
18949
+ const before2 = { functionsBefore: fns.size, pieceCallsBefore: allCalls.length, sourceBefore: source.length, barriers: { name: 1 } };
18950
+ return fallback(emitted, "canonical source uses the reserved _z<N> supercompiler prefix", before2);
18951
+ }
18952
+ const pieceCallsBefore = allCalls.length;
18953
+ const recursive = recursiveMembers(fns);
18954
+ const incoming = /* @__PURE__ */ new Map();
18955
+ for (const call of allCalls) {
18956
+ const list = incoming.get(call.callee) ?? [];
18957
+ list.push(call);
18958
+ incoming.set(call.callee, list);
18959
+ }
18960
+ const publicRoots = /* @__PURE__ */ new Set([...Object.values(prog.rules), ...extraIps]);
18961
+ const barrier = /* @__PURE__ */ new Map();
18962
+ for (const ip of fns.keys()) {
18963
+ if (publicRoots.has(ip) || externalRefs.has(ip)) barrier.set(ip, "public");
18964
+ else if (recursive.has(ip)) barrier.set(ip, "recursive");
18965
+ else if (prog.code[ip] === OP_ATTEMPT || prog.code[ip] === OP_SCAN) barrier.set(ip, "effect");
18966
+ else if (hasInlineScopeHazard(fns.get(ip))) barrier.set(ip, "scope");
18967
+ else if (!hasInlineSignature(fns.get(ip))) barrier.set(ip, "shape");
18968
+ else if ((incoming.get(ip)?.length ?? 0) !== 1) barrier.set(ip, "shared");
18969
+ else if (!incoming.get(ip)[0].transformable) barrier.set(ip, "shape");
18970
+ }
18971
+ const roots = [...fns.keys()].filter((ip) => barrier.has(ip));
18972
+ const owner = /* @__PURE__ */ new Map();
18973
+ const absorb = (ip, root) => {
18974
+ if (owner.has(ip)) return;
18975
+ owner.set(ip, root);
18976
+ for (const call of fns.get(ip)?.calls ?? []) {
18977
+ if (!fns.has(call.callee) || barrier.has(call.callee) || !call.transformable) continue;
18978
+ absorb(call.callee, root);
18979
+ }
18980
+ };
18981
+ for (const root of roots) absorb(root, root);
18982
+ for (const ip of fns.keys()) if (!owner.has(ip)) {
18983
+ barrier.set(ip, "shared");
18984
+ absorb(ip, ip);
18985
+ }
18986
+ let serial = 0;
18987
+ const src = (node2) => {
18988
+ const r = range(node2);
18989
+ return source.slice(r.start, r.end);
18990
+ };
18991
+ const renderBody = (ip, embedded) => {
18992
+ const fn = fns.get(ip);
18993
+ const bodyRange = range(fn.body);
18994
+ const start = bodyRange.start + 1;
18995
+ const end = bodyRange.end - 1;
18996
+ const edits = [];
18997
+ const callsByStatement = /* @__PURE__ */ new Map();
18998
+ for (const call of fn.calls) {
18999
+ if (owner.get(call.callee) !== owner.get(ip) || barrier.has(call.callee) || !call.transformable) continue;
19000
+ const list = callsByStatement.get(call.statement) ?? [];
19001
+ list.push(call);
19002
+ callsByStatement.set(call.statement, list);
19003
+ }
19004
+ const returns = [];
19005
+ const collectReturns = (node2) => {
19006
+ if (node2 !== fn.body && isFunction(node2)) return;
19007
+ if (node2.type === "ReturnStatement") returns.push(node2);
19008
+ for (const child of children2(node2)) collectReturns(child);
19009
+ };
19010
+ if (embedded !== void 0) collectReturns(fn.body);
19011
+ const callPrefix = (call) => {
19012
+ const id = serial++;
19013
+ const result = `_z${id}r`;
19014
+ const label2 = `_z${id}`;
19015
+ const at = `_z${id}p`;
19016
+ const nested = renderBody(call.callee, { result, label: label2 });
19017
+ return {
19018
+ value: result,
19019
+ prefix: `let ${result},${at}=${src(call.args[1])}
19020
+ ${label2}:{let pos=${at}
19021
+ ${nested}
19022
+ }
19023
+ `
19024
+ };
19025
+ };
19026
+ for (const [statement, calls] of callsByStatement) {
19027
+ let prefix = "";
19028
+ const replacements = [];
19029
+ for (const call of calls) {
19030
+ const made = callPrefix(call);
19031
+ prefix += made.prefix;
19032
+ const cr = range(call.node);
19033
+ replacements.push({ start: cr.start, end: cr.end, text: made.value });
19034
+ }
19035
+ if (statement.type === "ReturnStatement" && embedded !== void 0) {
19036
+ const sr = range(statement);
19037
+ const arg = ast(statement.argument);
19038
+ const value = arg === void 0 ? "undefined" : render2(source, range(arg).start, range(arg).end, replacements);
19039
+ edits.push({ start: sr.start, end: sr.end, text: `{${prefix}${embedded.result}=${value};break ${embedded.label}}` });
19040
+ } else {
19041
+ const sr = range(statement);
19042
+ edits.push({ start: sr.start, end: sr.start, text: prefix });
19043
+ edits.push(...replacements);
19044
+ }
19045
+ }
19046
+ if (embedded !== void 0) {
19047
+ for (const statement of returns) {
19048
+ if (callsByStatement.has(statement)) continue;
19049
+ const sr = range(statement);
19050
+ const arg = ast(statement.argument);
19051
+ edits.push({
19052
+ start: sr.start,
19053
+ end: sr.end,
19054
+ text: `{${embedded.result}=${arg === void 0 ? "undefined" : src(arg)};break ${embedded.label}}`
19055
+ });
19056
+ }
19057
+ }
19058
+ return render2(source, start, end, edits);
19059
+ };
19060
+ const regionSizes = /* @__PURE__ */ new Map();
19061
+ const regionProtocol = /* @__PURE__ */ new Map();
19062
+ for (const [ip, root] of owner) {
19063
+ const r = range(fns.get(ip).node);
19064
+ regionSizes.set(root, (regionSizes.get(root) ?? 0) + r.end - r.start);
19065
+ const op = prog.code[ip];
19066
+ const bits = (op === OP_NODE || op === OP_NODE_TRACK ? 1 : 0) | (op === OP_REPV ? 2 : 0);
19067
+ regionProtocol.set(root, (regionProtocol.get(root) ?? 0) | bits);
19068
+ }
19069
+ const oversized = /* @__PURE__ */ new Set();
19070
+ for (const [ip, size] of regionSizes) if (size > 18e4) oversized.add(ip);
19071
+ if (oversized.size > 0) {
19072
+ const counts2 = Object.fromEntries([...barrier.values()].map((k) => [k, 0]));
19073
+ for (const kind of barrier.values()) counts2[kind] = (counts2[kind] ?? 0) + 1;
19074
+ const before2 = { functionsBefore: fns.size, pieceCallsBefore, sourceBefore: source.length, barriers: counts2 };
19075
+ return fallback(emitted, "a region exceeded the 180KB source cap", before2);
19076
+ }
19077
+ const topEdits = [];
19078
+ for (const [ip, fn] of fns) {
19079
+ if (owner.get(ip) === ip) {
19080
+ const br = range(fn.body);
19081
+ topEdits.push({ start: br.start + 1, end: br.end - 1, text: renderBody(ip, void 0) });
19082
+ } else {
19083
+ const fr = range(fn.node);
19084
+ topEdits.push({ start: fr.start, end: fr.end, text: "" });
19085
+ }
19086
+ }
19087
+ const candidate = render2(source, 0, source.length, topEdits);
19088
+ const counts = {};
19089
+ for (const kind of barrier.values()) counts[kind] = (counts[kind] ?? 0) + 1;
19090
+ const before = { functionsBefore: fns.size, pieceCallsBefore, sourceBefore: source.length, barriers: counts };
19091
+ if (candidate.length > Math.ceil(source.length * 1.05)) {
19092
+ return fallback(emitted, `candidate exceeded the 5% total source cap (${candidate.length} > ${Math.ceil(source.length * 1.05)})`, before);
19093
+ }
19094
+ const functionsAfter = roots.length;
19095
+ const removed = fns.size - functionsAfter;
19096
+ const checked = parseSync4("parseman-entry-supercompile-result.js", WRAP + candidate + SUFFIX);
19097
+ if (checked.errors.length > 0) return fallback(emitted, "structured candidate did not parse", before);
19098
+ const declared = /* @__PURE__ */ new Set();
19099
+ const referenced = /* @__PURE__ */ new Set();
19100
+ const checkRefs = (node2, parent) => {
19101
+ if (node2.type === "FunctionDeclaration") {
19102
+ const name = nameOf(ast(node2.id));
19103
+ if (name !== void 0 && PIECE.test(name)) declared.add(name);
19104
+ }
19105
+ if (node2.type === "Identifier" && typeof node2.name === "string" && PIECE.test(node2.name)) {
19106
+ const isDeclaration = parent?.type === "FunctionDeclaration" && parent.id === node2;
19107
+ if (!isDeclaration) referenced.add(node2.name);
19108
+ }
19109
+ for (const child of children2(node2)) checkRefs(child, node2);
19110
+ };
19111
+ checkRefs(checked.program);
19112
+ if (declared.size !== functionsAfter || [...referenced].some((name) => !declared.has(name))) {
19113
+ return fallback(emitted, "deleted piece body remains reachable after structured relinking", before);
19114
+ }
19115
+ const largestRegion = [...regionSizes].sort((a, b) => b[1] - a[1])[0];
19116
+ const protocolRegions = {
19117
+ node: [...regionProtocol.values()].filter((bits) => (bits & 1) !== 0).length,
19118
+ repv: [...regionProtocol.values()].filter((bits) => (bits & 2) !== 0).length,
19119
+ nodeAndRepv: [...regionProtocol.values()].filter((bits) => bits === 3).length
19120
+ };
19121
+ return {
19122
+ ...emitted,
19123
+ source: candidate,
19124
+ supercompile: {
19125
+ ...before,
19126
+ activated: removed > 0,
19127
+ ...removed > 0 ? {} : { reason: "no uniquely-owned region bodies" },
19128
+ functionsAfter,
19129
+ pieceCallsAfter: pieceCallsBefore - removed,
19130
+ sourceAfter: candidate.length,
19131
+ regions: roots.length,
19132
+ largestRegionSource: Math.max(0, ...regionSizes.values()),
19133
+ ...largestRegion === void 0 ? {} : { largestRegionIp: largestRegion[0] },
19134
+ protocolRegions
19135
+ }
19136
+ };
19137
+ }
19138
+
17570
19139
  // src/plugin/index.ts
17571
19140
  import { createHash } from "node:crypto";
17572
19141
  var TABLE_RUNTIME_SPECIFIER = "parseman/table";
@@ -17669,7 +19238,7 @@ function parseModuleCached(filePath) {
17669
19238
  let parsed = null;
17670
19239
  try {
17671
19240
  const src = fs2.readFileSync(filePath, "utf8");
17672
- const r = parseSync4(filePath, src);
19241
+ const r = parseSync5(filePath, src);
17673
19242
  if (r.errors.length === 0) parsed = { body: r.program.body, src };
17674
19243
  } catch {
17675
19244
  }
@@ -17818,7 +19387,7 @@ function lowerPrivateSourceModule(file, moduleAliases, warnUnloweredRegex, recov
17818
19387
  const source = fs2.readFileSync(file, "utf8");
17819
19388
  const transformed = transformMacro(source, file, moduleAliases, warnUnloweredRegex, recovery);
17820
19389
  if (!transformed || transformed.warnings.length > 0) return null;
17821
- const parsed = parseSync4(file, transformed.code);
19390
+ const parsed = parseSync5(file, transformed.code);
17822
19391
  parsedModule = parsed.errors.length === 0 ? { body: parsed.program.body, src: transformed.code } : null;
17823
19392
  return parsedModule;
17824
19393
  } catch {
@@ -17841,7 +19410,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
17841
19410
  function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recovery, grammarCoverage) {
17842
19411
  let result;
17843
19412
  try {
17844
- result = parseSync4(id, code);
19413
+ result = parseSync5(id, code);
17845
19414
  } catch {
17846
19415
  return null;
17847
19416
  }
@@ -18462,9 +20031,12 @@ function transformMacroImpl(code, id, moduleAliases, warnUnloweredRegex, recover
18462
20031
  if (compiled !== null) {
18463
20032
  usedTableRuntime = true;
18464
20033
  return {
18465
- replacement: compiled.replacementWithMetadata(
18466
- staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
18467
- { precompileDefault: true }
20034
+ replacement: supercompileRuleMapReplacement(
20035
+ compiled.prog,
20036
+ compiled.replacementWithMetadata(
20037
+ staticTableMetadataSource({ reflection: compiled.reflection, leaf: true }),
20038
+ { precompileDefault: true }
20039
+ )
18468
20040
  ),
18469
20041
  ...importedFactories.length ? { importedFactories } : {}
18470
20042
  };