parseman 0.18.2 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/combinators/map.d.ts +5 -0
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +14 -13
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/combinators/parser.d.ts.map +1 -1
- package/dist/combinators/ref.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts +1 -0
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +3 -3
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/fields.d.ts +16 -0
- package/dist/compiler/fields.d.ts.map +1 -0
- package/dist/compiler/inline-build.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +17 -3
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/compiler/value-usage.d.ts.map +1 -1
- package/dist/cst/capture-buffer.d.ts +1 -0
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/index.cjs +255 -45
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +255 -45
- package/dist/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +255 -53
- package/dist/plugin/index.cjs.map +3 -3
- package/dist/plugin/index.js +255 -53
- package/dist/plugin/index.js.map +3 -3
- package/dist/types.d.ts +31 -8
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -49,6 +49,7 @@ __export(index_exports, {
|
|
|
49
49
|
createVisitor: () => createVisitor,
|
|
50
50
|
cstBuildHost: () => cstBuildHost,
|
|
51
51
|
expect: () => expect,
|
|
52
|
+
field: () => field,
|
|
52
53
|
gapIsSignificant: () => gapIsSignificant,
|
|
53
54
|
gapText: () => gapText,
|
|
54
55
|
guard: () => guard,
|
|
@@ -349,7 +350,8 @@ function saveCstMark(ctx) {
|
|
|
349
350
|
return {
|
|
350
351
|
raw: cstRawLen(ctx),
|
|
351
352
|
tlog: cstTlLen(ctx),
|
|
352
|
-
leaves: cstLeavesLen(ctx)
|
|
353
|
+
leaves: cstLeavesLen(ctx),
|
|
354
|
+
fields: ctx._fields?.length ?? 0
|
|
353
355
|
};
|
|
354
356
|
}
|
|
355
357
|
function rollbackBufList(b, keyMulti, keySingle, len) {
|
|
@@ -373,11 +375,13 @@ function rollbackCstCapture(ctx, mark) {
|
|
|
373
375
|
if (mark.tlog === 0) b.tl = void 0;
|
|
374
376
|
else b.tl.length = mark.tlog;
|
|
375
377
|
}
|
|
378
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
376
379
|
return;
|
|
377
380
|
}
|
|
378
381
|
if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
|
|
379
382
|
if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
|
|
380
383
|
if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
|
|
384
|
+
if (ctx._fields) ctx._fields.length = mark.fields;
|
|
381
385
|
}
|
|
382
386
|
function pushCstTriviaEntry(ctx, start, end, kindIndex) {
|
|
383
387
|
const insertIdx = cstRawLen(ctx);
|
|
@@ -1117,10 +1121,10 @@ function needsDeferredTriviaCommit(ctx) {
|
|
|
1117
1121
|
}
|
|
1118
1122
|
function saveTriviaMark(ctx) {
|
|
1119
1123
|
const m = saveCstMark(ctx);
|
|
1120
|
-
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
1124
|
+
return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, fields: m.fields, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
|
|
1121
1125
|
}
|
|
1122
1126
|
function rollbackTrivia(ctx, mark) {
|
|
1123
|
-
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves });
|
|
1127
|
+
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields });
|
|
1124
1128
|
if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
|
|
1125
1129
|
}
|
|
1126
1130
|
function scanWithLabels(input, cur, ctx) {
|
|
@@ -1494,6 +1498,13 @@ function ref() {
|
|
|
1494
1498
|
define(p) {
|
|
1495
1499
|
if (resolved) throw new Error("ref<T>() already defined");
|
|
1496
1500
|
resolved = p;
|
|
1501
|
+
meta.firstSet = p._meta.firstSet;
|
|
1502
|
+
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
1503
|
+
meta.isTrivia = p._meta.isTrivia;
|
|
1504
|
+
if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
|
|
1505
|
+
else delete meta.triviaKindLabels;
|
|
1506
|
+
if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
|
|
1507
|
+
else delete meta.disjoint;
|
|
1497
1508
|
}
|
|
1498
1509
|
};
|
|
1499
1510
|
return slot;
|
|
@@ -1534,6 +1545,9 @@ function markUnusedValues(root) {
|
|
|
1534
1545
|
case "transform":
|
|
1535
1546
|
visit(def.parser, true);
|
|
1536
1547
|
return;
|
|
1548
|
+
case "field":
|
|
1549
|
+
visit(def.parser, true);
|
|
1550
|
+
return;
|
|
1537
1551
|
case "skip":
|
|
1538
1552
|
visit(def.main, consumed);
|
|
1539
1553
|
visit(def.skipped, false);
|
|
@@ -1585,6 +1599,11 @@ function markUnusedValues(root) {
|
|
|
1585
1599
|
}
|
|
1586
1600
|
|
|
1587
1601
|
// src/combinators/parser.ts
|
|
1602
|
+
function tagRule(r, key) {
|
|
1603
|
+
;
|
|
1604
|
+
r._ruleName = key;
|
|
1605
|
+
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
|
|
1606
|
+
}
|
|
1588
1607
|
function rules(factory) {
|
|
1589
1608
|
const cache = {};
|
|
1590
1609
|
const proxy = new Proxy(cache, {
|
|
@@ -1593,7 +1612,7 @@ function rules(factory) {
|
|
|
1593
1612
|
const record = target;
|
|
1594
1613
|
if (!(key in record)) {
|
|
1595
1614
|
const r = ref();
|
|
1596
|
-
r
|
|
1615
|
+
tagRule(r, key);
|
|
1597
1616
|
record[key] = r;
|
|
1598
1617
|
}
|
|
1599
1618
|
return record[key];
|
|
@@ -1604,12 +1623,12 @@ function rules(factory) {
|
|
|
1604
1623
|
const placeholder = cache[key];
|
|
1605
1624
|
const parser2 = definitions[key];
|
|
1606
1625
|
if (placeholder !== void 0 && typeof placeholder.define === "function") {
|
|
1607
|
-
;
|
|
1626
|
+
tagRule(parser2, key);
|
|
1608
1627
|
placeholder.define(parser2);
|
|
1609
1628
|
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
1610
1629
|
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
1611
1630
|
} else {
|
|
1612
|
-
;
|
|
1631
|
+
tagRule(parser2, key);
|
|
1613
1632
|
cache[key] = parser2;
|
|
1614
1633
|
}
|
|
1615
1634
|
}
|
|
@@ -1666,44 +1685,130 @@ function buildReadsTrivia(def) {
|
|
|
1666
1685
|
const src = def.buildSrc ?? def.build.toString();
|
|
1667
1686
|
const arity = confirmedBuildArity(src);
|
|
1668
1687
|
if (arity === null) return true;
|
|
1669
|
-
return arity >=
|
|
1688
|
+
return arity >= 5;
|
|
1670
1689
|
}
|
|
1671
1690
|
function buildReadsState(def) {
|
|
1672
1691
|
if (!def.build) return true;
|
|
1673
1692
|
const src = def.buildSrc ?? def.build.toString();
|
|
1674
1693
|
const arity = confirmedBuildArity(src);
|
|
1675
1694
|
if (arity === null) return true;
|
|
1676
|
-
return arity >=
|
|
1695
|
+
return arity >= 6;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
// src/compiler/fields.ts
|
|
1699
|
+
function buildReadsFields(def) {
|
|
1700
|
+
if (!def.build) return true;
|
|
1701
|
+
const src = def.buildSrc ?? def.build.toString();
|
|
1702
|
+
const arity = confirmedBuildArity(src);
|
|
1703
|
+
if (arity === null) return true;
|
|
1704
|
+
return arity >= 2;
|
|
1705
|
+
}
|
|
1706
|
+
function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
1707
|
+
if (seen.has(p)) return false;
|
|
1708
|
+
seen.add(p);
|
|
1709
|
+
const d = p._def;
|
|
1710
|
+
switch (d.tag) {
|
|
1711
|
+
case "field":
|
|
1712
|
+
return true;
|
|
1713
|
+
case "node":
|
|
1714
|
+
return false;
|
|
1715
|
+
case "lazy": {
|
|
1716
|
+
try {
|
|
1717
|
+
return parserHasOwnFields(d.thunk(), seen);
|
|
1718
|
+
} catch {
|
|
1719
|
+
return false;
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
case "sequence":
|
|
1723
|
+
case "choice":
|
|
1724
|
+
return d.parsers.some((x) => parserHasOwnFields(x, seen));
|
|
1725
|
+
case "sepBy":
|
|
1726
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.separator, seen);
|
|
1727
|
+
case "skip":
|
|
1728
|
+
return parserHasOwnFields(d.main, seen) || parserHasOwnFields(d.skipped, seen);
|
|
1729
|
+
case "grammar":
|
|
1730
|
+
return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
|
|
1731
|
+
case "scanTo":
|
|
1732
|
+
return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen));
|
|
1733
|
+
case "recover":
|
|
1734
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
|
|
1735
|
+
case "many":
|
|
1736
|
+
case "oneOrMore":
|
|
1737
|
+
case "optional":
|
|
1738
|
+
case "transform":
|
|
1739
|
+
case "trivia":
|
|
1740
|
+
case "token":
|
|
1741
|
+
case "label":
|
|
1742
|
+
case "expect":
|
|
1743
|
+
case "withCtx":
|
|
1744
|
+
case "not":
|
|
1745
|
+
return parserHasOwnFields(d.parser, seen);
|
|
1746
|
+
default:
|
|
1747
|
+
return false;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
function buildFieldMap(captures) {
|
|
1751
|
+
if (!captures?.length) return void 0;
|
|
1752
|
+
const out = {};
|
|
1753
|
+
for (const cap of captures) {
|
|
1754
|
+
const entry = { value: cap.value, span: cap.span };
|
|
1755
|
+
const current = out[cap.name];
|
|
1756
|
+
if (current === void 0) out[cap.name] = entry;
|
|
1757
|
+
else if (Array.isArray(current)) current.push(entry);
|
|
1758
|
+
else out[cap.name] = [current, entry];
|
|
1759
|
+
}
|
|
1760
|
+
return out;
|
|
1677
1761
|
}
|
|
1678
1762
|
|
|
1679
1763
|
// src/combinators/node.ts
|
|
1680
|
-
function
|
|
1764
|
+
function unwrapChild(child) {
|
|
1681
1765
|
return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
|
|
1682
1766
|
}
|
|
1683
|
-
function
|
|
1767
|
+
function isCstChild(value) {
|
|
1768
|
+
return typeof value === "object" && value !== null && (value._tag === "node" || value._tag === "leaf" || value._tag === "error");
|
|
1769
|
+
}
|
|
1770
|
+
function missingInferredType() {
|
|
1771
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
1772
|
+
}
|
|
1773
|
+
function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
1774
|
+
const hasExplicitType = typeof typeOrCombinator === "string";
|
|
1775
|
+
const type = hasExplicitType ? typeOrCombinator : void 0;
|
|
1776
|
+
const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
|
|
1777
|
+
const build = hasExplicitType ? buildOrOpts : combinatorOrBuild;
|
|
1778
|
+
const opts = hasExplicitType ? maybeOpts : buildOrOpts;
|
|
1779
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
1684
1780
|
const meta = {
|
|
1685
1781
|
firstSet: combinator._meta.firstSet,
|
|
1686
1782
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
1687
1783
|
isTrivia: false
|
|
1688
1784
|
};
|
|
1785
|
+
const unwrap = opts?.unwrap === true;
|
|
1689
1786
|
const collapse = opts?.collapse === true;
|
|
1690
|
-
|
|
1787
|
+
if (unwrap && collapse) {
|
|
1788
|
+
throw new Error("node() options cannot set both unwrap and collapse");
|
|
1789
|
+
}
|
|
1790
|
+
const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
|
|
1691
1791
|
const capturesTrivia = build ? buildReadsTrivia(def) : true;
|
|
1692
1792
|
const clonesState = build ? buildReadsState(def) : true;
|
|
1793
|
+
const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
|
|
1693
1794
|
return {
|
|
1694
1795
|
_tag: "node",
|
|
1695
1796
|
_meta: meta,
|
|
1696
1797
|
_def: def,
|
|
1697
1798
|
parse(input, pos, ctx) {
|
|
1698
1799
|
const saved = beginCstNodeCapture(ctx);
|
|
1800
|
+
const savedFields = ctx._fields;
|
|
1801
|
+
ctx._fields = capturesFields ? [] : void 0;
|
|
1699
1802
|
if (!capturesTrivia) ctx.captureTrivia = false;
|
|
1700
1803
|
const r = combinator.parse(input, pos, ctx);
|
|
1804
|
+
const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
|
|
1805
|
+
ctx._fields = savedFields;
|
|
1701
1806
|
const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
1702
1807
|
if (!r.ok) return r;
|
|
1703
1808
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
1704
|
-
const
|
|
1705
|
-
const
|
|
1706
|
-
const rawEntry =
|
|
1809
|
+
const nodeType = def.type ?? missingInferredType();
|
|
1810
|
+
const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : build ? build(children, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children };
|
|
1811
|
+
const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
|
|
1707
1812
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
1708
1813
|
pushCstChild(ctx, built, rawEntry);
|
|
1709
1814
|
}
|
|
@@ -1764,6 +1869,19 @@ function label(name, combinator) {
|
|
|
1764
1869
|
}
|
|
1765
1870
|
};
|
|
1766
1871
|
}
|
|
1872
|
+
function field(name, combinator) {
|
|
1873
|
+
return {
|
|
1874
|
+
_tag: combinator._tag,
|
|
1875
|
+
_meta: combinator._meta,
|
|
1876
|
+
_def: { tag: "field", name, parser: combinator },
|
|
1877
|
+
parse(input, pos, ctx) {
|
|
1878
|
+
const result = combinator.parse(input, pos, ctx);
|
|
1879
|
+
if (!result.ok) return result;
|
|
1880
|
+
ctx._fields?.push({ name, value: result.value, span: result.span });
|
|
1881
|
+
return result;
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1767
1885
|
|
|
1768
1886
|
// src/compiler/line-index.ts
|
|
1769
1887
|
function buildLineIndex(input) {
|
|
@@ -3246,21 +3364,22 @@ function emitScannableTerminal(shape, c) {
|
|
|
3246
3364
|
}
|
|
3247
3365
|
|
|
3248
3366
|
// src/compiler/inline-build.ts
|
|
3249
|
-
var MK_BUILD_RE = /^\(\s*(
|
|
3367
|
+
var MK_BUILD_RE = /^\(\s*(\w+)\s*,\s*\w+\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\)\s*=>\s*mk\s*\(\s*(['"])([^'"]+)\5\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$/;
|
|
3250
3368
|
function escapeRegExp(s) {
|
|
3251
3369
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3252
3370
|
}
|
|
3253
3371
|
function looseMkBuildRe(type) {
|
|
3254
3372
|
return new RegExp(
|
|
3255
|
-
String.raw`^\(\s*(
|
|
3373
|
+
String.raw`^\(\s*(\w+)\s*,\s*\w+\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\)\s*=>\s*.+\(\s*(['"])${escapeRegExp(type)}\5\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$`
|
|
3256
3374
|
);
|
|
3257
3375
|
}
|
|
3258
3376
|
function analyzeMkInlineBuild(def) {
|
|
3259
3377
|
if (!def.build) return null;
|
|
3378
|
+
if (def.type === void 0) return null;
|
|
3260
3379
|
const src = (def.buildSrc ?? def.build.toString()).trim();
|
|
3261
3380
|
const strict = src.match(MK_BUILD_RE);
|
|
3262
3381
|
if (strict) {
|
|
3263
|
-
const mkType = strict[
|
|
3382
|
+
const mkType = strict[6];
|
|
3264
3383
|
return mkType === def.type ? def.type : null;
|
|
3265
3384
|
}
|
|
3266
3385
|
if (looseMkBuildRe(def.type).test(src)) return def.type;
|
|
@@ -3587,8 +3706,9 @@ function planDisjointDispatch(parsers) {
|
|
|
3587
3706
|
}
|
|
3588
3707
|
return total >= SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
|
|
3589
3708
|
}
|
|
3590
|
-
function captureRestoreBody(mL, mR, mTl, mLg) {
|
|
3591
|
-
const
|
|
3709
|
+
function captureRestoreBody(mL, mR, mTl, mLg, mF = null) {
|
|
3710
|
+
const fieldRestore = mF ? `; if (_ctx._fields) _ctx._fields.length = ${mF}` : "";
|
|
3711
|
+
const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
|
|
3592
3712
|
return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
|
|
3593
3713
|
}
|
|
3594
3714
|
function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
@@ -3636,6 +3756,7 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3636
3756
|
// Delegating wrappers: defer to the wrapped parser.
|
|
3637
3757
|
case "transform":
|
|
3638
3758
|
case "label":
|
|
3759
|
+
case "field":
|
|
3639
3760
|
case "expect":
|
|
3640
3761
|
case "withCtx":
|
|
3641
3762
|
case "grammar":
|
|
@@ -3682,6 +3803,7 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3682
3803
|
case "optional":
|
|
3683
3804
|
case "transform":
|
|
3684
3805
|
case "label":
|
|
3806
|
+
case "field":
|
|
3685
3807
|
case "expect":
|
|
3686
3808
|
case "withCtx":
|
|
3687
3809
|
case "grammar":
|
|
@@ -3719,22 +3841,25 @@ function emitFallible(inner, ctx, pos, swallow = false) {
|
|
|
3719
3841
|
ctx.recordFail = savedRecord;
|
|
3720
3842
|
const ind0 = ind(ctx);
|
|
3721
3843
|
const needsRollback = ctx.capturing && mayLeavePartialCapture(inner);
|
|
3844
|
+
const needsFieldRollback = needsRollback && parserHasOwnFields(inner);
|
|
3722
3845
|
const mL = needsRollback ? v(ctx, "_fcl") : null;
|
|
3723
3846
|
const mR = needsRollback ? v(ctx, "_fcr") : null;
|
|
3724
3847
|
const mTl = needsRollback ? v(ctx, "_fctl") : null;
|
|
3848
|
+
const mF = needsFieldRollback ? v(ctx, "_fcf") : null;
|
|
3725
3849
|
const stmts = [
|
|
3726
3850
|
`${ind0}let ${okV} = false, ${valV}, ${endV} = ${pos}`,
|
|
3727
3851
|
...mL ? [
|
|
3728
3852
|
`${ind0}const ${mL} = _ctx._cstLeaves?.length ?? 0`,
|
|
3729
3853
|
`${ind0}const ${mR} = _ctx._cstRawChildren?.length ?? 0`,
|
|
3730
|
-
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0
|
|
3854
|
+
`${ind0}const ${mTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
3855
|
+
...mF ? [`${ind0}const ${mF} = _ctx._fields?.length ?? 0`] : []
|
|
3731
3856
|
] : [],
|
|
3732
3857
|
`${ind0}${lbl}: {`,
|
|
3733
3858
|
...r.stmts,
|
|
3734
3859
|
`${ind0} ${valV} = ${r.valueVar}; ${endV} = ${r.endVar}; ${okV} = true`,
|
|
3735
3860
|
`${ind0}}`,
|
|
3736
3861
|
...mL ? [
|
|
3737
|
-
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null)} }`
|
|
3862
|
+
`${ind0}if (!${okV}) { ${captureRestoreBody(mL, mR, mTl, null, mF)} }`
|
|
3738
3863
|
] : []
|
|
3739
3864
|
];
|
|
3740
3865
|
return { stmts, okVar: okV, valVar: valV, endVar: endV };
|
|
@@ -3961,6 +4086,7 @@ function failsAtStart(p) {
|
|
|
3961
4086
|
return true;
|
|
3962
4087
|
case "transform":
|
|
3963
4088
|
case "label":
|
|
4089
|
+
case "field":
|
|
3964
4090
|
return failsAtStart(d.parser);
|
|
3965
4091
|
default:
|
|
3966
4092
|
return false;
|
|
@@ -3980,6 +4106,7 @@ function canMatchEmptyAtStart(p) {
|
|
|
3980
4106
|
return true;
|
|
3981
4107
|
case "transform":
|
|
3982
4108
|
case "label":
|
|
4109
|
+
case "field":
|
|
3983
4110
|
return canMatchEmptyAtStart(d.parser);
|
|
3984
4111
|
case "literal":
|
|
3985
4112
|
return d.value.length === 0;
|
|
@@ -4162,11 +4289,13 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4162
4289
|
const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
|
|
4163
4290
|
const armHasAutoNot = !!(autoNot && autoNot.length > 0);
|
|
4164
4291
|
const armNeedsRollback = ctx.capturing && (mayLeavePartialCapture(p) || armHasAutoNot && capturesLeaf(p));
|
|
4292
|
+
const armNeedsFieldRollback = armNeedsRollback && parserHasOwnFields(p);
|
|
4165
4293
|
const markLeaves = armNeedsRollback ? v(ctx, "_cml") : null;
|
|
4166
4294
|
const markRaw = armNeedsRollback ? v(ctx, "_cmr") : null;
|
|
4167
4295
|
const markTl = armNeedsRollback ? v(ctx, "_cmtl") : null;
|
|
4168
4296
|
const markLog = armNeedsRollback ? v(ctx, "_cmlg") : null;
|
|
4169
|
-
const
|
|
4297
|
+
const markFields = armNeedsFieldRollback ? v(ctx, "_cmf") : null;
|
|
4298
|
+
const rollback = markLeaves ? captureRestoreBody(markLeaves, markRaw, markTl, markLog, markFields) : "";
|
|
4170
4299
|
const failSlot = atStart ? staticFx : "_ctx._fx";
|
|
4171
4300
|
stmts.push(`${ind0}if (${skipCond}) {`);
|
|
4172
4301
|
if (fsGuard) stmts.push(`${ind(ctx)}if (${fsGuard}) {`);
|
|
@@ -4176,7 +4305,8 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
4176
4305
|
`${ind(ctx)}const ${markLeaves} = _ctx._cstLeaves?.length ?? 0`,
|
|
4177
4306
|
`${ind(ctx)}const ${markRaw} = _ctx._cstRawChildren?.length ?? 0`,
|
|
4178
4307
|
`${ind(ctx)}const ${markTl} = _ctx._cstTriviaLog?.length ?? 0`,
|
|
4179
|
-
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0
|
|
4308
|
+
`${ind(ctx)}const ${markLog} = _ctx._triviaLog?.length ?? 0`,
|
|
4309
|
+
...markFields ? [`${ind(ctx)}const ${markFields} = _ctx._fields?.length ?? 0`] : []
|
|
4180
4310
|
);
|
|
4181
4311
|
}
|
|
4182
4312
|
const { stmts: armStmts, okVar, valVar, endVar } = emitFallible(p, ctx, pos, atStart);
|
|
@@ -4569,6 +4699,9 @@ function emitToken(def, ctx, pos) {
|
|
|
4569
4699
|
};
|
|
4570
4700
|
}
|
|
4571
4701
|
function emitNode(def, ctx, pos) {
|
|
4702
|
+
if (def.type === void 0) {
|
|
4703
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
4704
|
+
}
|
|
4572
4705
|
const structural = def.build === void 0;
|
|
4573
4706
|
const mkType = structural ? null : analyzeMkInlineBuild(def);
|
|
4574
4707
|
let buildIdx = null;
|
|
@@ -4580,25 +4713,36 @@ function emitNode(def, ctx, pos) {
|
|
|
4580
4713
|
const i = ind(ctx);
|
|
4581
4714
|
const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
|
|
4582
4715
|
const clonesState = !structural && buildReadsState(def);
|
|
4716
|
+
const hasFields = parserHasOwnFields(def.parser);
|
|
4717
|
+
const capturesFields = hasFields && !structural && buildReadsFields(def);
|
|
4583
4718
|
const chV = v(ctx, "_ch");
|
|
4584
4719
|
const rawV = v(ctx, "_raw");
|
|
4585
4720
|
const capTLv = structural ? v(ctx, "_ctl") : null;
|
|
4586
4721
|
const capSTv = structural ? v(ctx, "_cst") : null;
|
|
4722
|
+
const capFv = structural && hasFields ? v(ctx, "_cf") : null;
|
|
4587
4723
|
const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
|
|
4588
4724
|
if (!capturesTrivia) ctx.needsEmptyTl = true;
|
|
4589
4725
|
const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
|
|
4590
4726
|
if (structural) ctx.needsHostReads = true;
|
|
4591
|
-
const
|
|
4727
|
+
const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
|
|
4728
|
+
const allocStmt = structural ? `${i}const ${capTLv} = ${hostTriviaGate}, ${capSTv} = _ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 6))${capFv ? `, ${capFv} = _ctx.build !== undefined && _hostReads(_ctx.build, 2)` : ""}
|
|
4592
4729
|
${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
|
|
4593
4730
|
const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
|
|
4731
|
+
const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
|
|
4732
|
+
const sf = hasFields ? v(ctx, "_sf") : null;
|
|
4733
|
+
const fArr = hasFields ? v(ctx, "_fa") : null;
|
|
4734
|
+
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
4594
4735
|
const stmts = [
|
|
4595
4736
|
allocStmt,
|
|
4596
|
-
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog`,
|
|
4597
|
-
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}`
|
|
4737
|
+
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
4738
|
+
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
4598
4739
|
];
|
|
4599
4740
|
const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
|
|
4600
4741
|
stmts.push(...innerStmts);
|
|
4601
|
-
|
|
4742
|
+
if (sf && fArr) {
|
|
4743
|
+
stmts.push(`${i}const ${fArr} = _ctx._fields`);
|
|
4744
|
+
}
|
|
4745
|
+
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${sf ? `; _ctx._fields = ${sf}` : ""}`);
|
|
4602
4746
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
4603
4747
|
let stV = "undefined";
|
|
4604
4748
|
if (structural) {
|
|
@@ -4608,14 +4752,33 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
|
|
|
4608
4752
|
stV = v(ctx, "_nst");
|
|
4609
4753
|
stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
4610
4754
|
}
|
|
4755
|
+
if (sf && fArr) {
|
|
4756
|
+
const fe = v(ctx, "_fe");
|
|
4757
|
+
const cur = v(ctx, "_fc");
|
|
4758
|
+
stmts.push(
|
|
4759
|
+
`${i}let ${fObj} = undefined`,
|
|
4760
|
+
`${i}if (${fArr} && ${fArr}.length) {`,
|
|
4761
|
+
`${i} ${fObj} = {}`,
|
|
4762
|
+
`${i} for (const ${fe} of ${fArr}) {`,
|
|
4763
|
+
`${i} const ${cur} = ${fObj}[${fe}.name], _entry = { value: ${fe}.value, span: ${fe}.span }`,
|
|
4764
|
+
`${i} if (${cur} === undefined) ${fObj}[${fe}.name] = _entry`,
|
|
4765
|
+
`${i} else if (Array.isArray(${cur})) ${cur}.push(_entry)`,
|
|
4766
|
+
`${i} else ${fObj}[${fe}.name] = [${cur}, _entry]`,
|
|
4767
|
+
`${i} }`,
|
|
4768
|
+
`${i}}`
|
|
4769
|
+
);
|
|
4770
|
+
}
|
|
4611
4771
|
const ndV = v(ctx, "_nd");
|
|
4612
|
-
const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: { start: ${pos}, end: ${endVar} }, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${
|
|
4613
|
-
const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${
|
|
4614
|
-
const
|
|
4772
|
+
const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: { start: ${pos}, end: ${endVar} }, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
|
|
4773
|
+
const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV}) : (${buildExpr})` : buildExpr;
|
|
4774
|
+
const hostCollapseExpr = ctx.ns || structural ? `_ctx.build !== undefined && _ctx.build._parsemanCstCollapse !== undefined && ${chV}.length === 1 && ${rawV}.length === 1 && _ctx.build._parsemanCstCollapse(${JSON.stringify(def.type)}, ${chV}[0], ${chV}, ${rawV}) ? ${chV}[0] : (${ndExpr})` : ndExpr;
|
|
4775
|
+
const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
|
|
4776
|
+
const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
|
|
4777
|
+
const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
|
|
4615
4778
|
stmts.push(
|
|
4616
4779
|
`${i}const ${ndV} = ${finalExpr}`,
|
|
4617
4780
|
`${i}if (${sc}) ${sc}.push(${ndV})`,
|
|
4618
|
-
`${i}if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && ${ndV}._tag === 'node') ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`
|
|
4781
|
+
`${i}if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'error')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`
|
|
4619
4782
|
);
|
|
4620
4783
|
return { stmts, valueVar: ndV, endVar };
|
|
4621
4784
|
}
|
|
@@ -4830,6 +4993,17 @@ function emitDispatch(p, ctx, pos) {
|
|
|
4830
4993
|
endVar: inner.endVar
|
|
4831
4994
|
};
|
|
4832
4995
|
}
|
|
4996
|
+
case "field": {
|
|
4997
|
+
const inner = emit(def.parser, ctx, pos);
|
|
4998
|
+
return {
|
|
4999
|
+
stmts: [
|
|
5000
|
+
...inner.stmts,
|
|
5001
|
+
`${ind(ctx)}if (_ctx._fields) _ctx._fields.push({ name: ${JSON.stringify(def.name)}, value: ${inner.valueVar}, span: { start: ${pos}, end: ${inner.endVar} } })`
|
|
5002
|
+
],
|
|
5003
|
+
valueVar: inner.valueVar,
|
|
5004
|
+
endVar: inner.endVar
|
|
5005
|
+
};
|
|
5006
|
+
}
|
|
4833
5007
|
case "grammar": {
|
|
4834
5008
|
const savedTrivia = ctx.activeTrivia;
|
|
4835
5009
|
const savedKindLabels = ctx.triviaKindLabels;
|
|
@@ -4931,6 +5105,7 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
4931
5105
|
case "trivia":
|
|
4932
5106
|
case "token":
|
|
4933
5107
|
case "label":
|
|
5108
|
+
case "field":
|
|
4934
5109
|
case "optional":
|
|
4935
5110
|
case "many":
|
|
4936
5111
|
case "oneOrMore":
|
|
@@ -4967,6 +5142,7 @@ function childrenOf(def) {
|
|
|
4967
5142
|
case "trivia":
|
|
4968
5143
|
case "token":
|
|
4969
5144
|
case "label":
|
|
5145
|
+
case "field":
|
|
4970
5146
|
case "grammar":
|
|
4971
5147
|
case "not":
|
|
4972
5148
|
case "node":
|
|
@@ -5208,6 +5384,11 @@ function assertRuleName(name) {
|
|
|
5208
5384
|
);
|
|
5209
5385
|
}
|
|
5210
5386
|
}
|
|
5387
|
+
function publicRuleWrapperSource(rule, fnSource) {
|
|
5388
|
+
const labels = rule._meta.triviaKindLabels;
|
|
5389
|
+
if (labels === void 0) return fnSource;
|
|
5390
|
+
return `Object.assign(${fnSource}, { _meta: { triviaKindLabels: ${JSON.stringify(labels)} } })`;
|
|
5391
|
+
}
|
|
5211
5392
|
function compileLinkable(ruleMapArg, ns) {
|
|
5212
5393
|
if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
|
|
5213
5394
|
for (const [, rule] of ruleMapArg) markUnusedValues(rule);
|
|
@@ -5310,7 +5491,7 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5310
5491
|
ctx.recordFail = savedRec;
|
|
5311
5492
|
pushNamedFnDecl(ctx, fn, body.stmts, body.valueVar, body.endVar);
|
|
5312
5493
|
}
|
|
5313
|
-
perEntry.push({ key, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5494
|
+
perEntry.push({ key, rule, r: emitNamedFnCall(ctx, fn, "_pos") });
|
|
5314
5495
|
}
|
|
5315
5496
|
if (ctx.runtimeParsers.length !== 0) return null;
|
|
5316
5497
|
const mfSrcs = ctx.mapFns.length > 0 && ctx.mapFnSrcs.every((s) => s !== null) ? ctx.mapFnSrcs : null;
|
|
@@ -5333,14 +5514,14 @@ function compileLinkable(ruleMapArg, ns) {
|
|
|
5333
5514
|
...privateFns
|
|
5334
5515
|
].filter(Boolean);
|
|
5335
5516
|
const wrappers = /* @__PURE__ */ new Map();
|
|
5336
|
-
for (const { key, r } of perEntry) {
|
|
5337
|
-
wrappers.set(key, [
|
|
5517
|
+
for (const { key, rule, r } of perEntry) {
|
|
5518
|
+
wrappers.set(key, publicRuleWrapperSource(rule, [
|
|
5338
5519
|
`function(input, _pos, _ctx) {`,
|
|
5339
5520
|
` let pos = _pos`,
|
|
5340
5521
|
...r.stmts,
|
|
5341
5522
|
` return { ok: true, value: ${r.valueVar}, span: { start: _pos, end: ${r.endVar} } }`,
|
|
5342
5523
|
`}`
|
|
5343
|
-
].join("\n"));
|
|
5524
|
+
].join("\n")));
|
|
5344
5525
|
}
|
|
5345
5526
|
const firstSets = /* @__PURE__ */ new Map();
|
|
5346
5527
|
for (const [key, rule] of ruleMap) {
|
|
@@ -5543,6 +5724,7 @@ function evalRuleMapIR(ir) {
|
|
|
5543
5724
|
"skip",
|
|
5544
5725
|
"trivia",
|
|
5545
5726
|
"label",
|
|
5727
|
+
"field",
|
|
5546
5728
|
"expect",
|
|
5547
5729
|
"_tf",
|
|
5548
5730
|
"_nd",
|
|
@@ -5569,6 +5751,7 @@ function evalRuleMapIR(ir) {
|
|
|
5569
5751
|
skip,
|
|
5570
5752
|
trivia,
|
|
5571
5753
|
label,
|
|
5754
|
+
field,
|
|
5572
5755
|
expect,
|
|
5573
5756
|
_tf,
|
|
5574
5757
|
_nd
|
|
@@ -5583,9 +5766,26 @@ function linkable(rulesMap, ns) {
|
|
|
5583
5766
|
if (!pieces) throw new Error("linkable(): this grammar cannot be compiled to a linkable artifact (contains a runtime-only parser fallback)");
|
|
5584
5767
|
return pieces;
|
|
5585
5768
|
}
|
|
5586
|
-
function
|
|
5769
|
+
function normalizeCstCollapse(collapse) {
|
|
5770
|
+
if (collapse === true) return () => true;
|
|
5771
|
+
if (Array.isArray(collapse)) {
|
|
5772
|
+
const types = new Set(collapse);
|
|
5773
|
+
return (type) => types.has(type);
|
|
5774
|
+
}
|
|
5775
|
+
return typeof collapse === "function" ? collapse : void 0;
|
|
5776
|
+
}
|
|
5777
|
+
function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
|
|
5587
5778
|
return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children] };
|
|
5588
5779
|
}
|
|
5780
|
+
function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
|
|
5781
|
+
if (typeof typeOrOptions === "string") {
|
|
5782
|
+
return buildCstNode(typeOrOptions, children ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
|
|
5783
|
+
}
|
|
5784
|
+
const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
|
|
5785
|
+
const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2, fields, span2, rawChildren2, triviaLog2, state2);
|
|
5786
|
+
if (collapse) host._parsemanCstCollapse = collapse;
|
|
5787
|
+
return host;
|
|
5788
|
+
}
|
|
5589
5789
|
function pick(grammar, names) {
|
|
5590
5790
|
const p = grammar.ruleFns instanceof Map ? grammar : linkable(grammar);
|
|
5591
5791
|
const keep = /* @__PURE__ */ new Set();
|
|
@@ -5617,8 +5817,9 @@ function fusedBody(pieces) {
|
|
|
5617
5817
|
}
|
|
5618
5818
|
}
|
|
5619
5819
|
const contributing = new Set(winner.values());
|
|
5620
|
-
const
|
|
5621
|
-
const
|
|
5820
|
+
const contributingPieces = [...contributing];
|
|
5821
|
+
const needsEmptyTl = contributingPieces.some((p) => p.needsEmptyTl);
|
|
5822
|
+
const needsHostReads = contributingPieces.some((p) => p.needsHostReads);
|
|
5622
5823
|
const lines = [
|
|
5623
5824
|
// Shared sentinel protocol (must match NAMED_FN_FAIL / NAMED_FN_END in codegen).
|
|
5624
5825
|
"const _pfFail = {}",
|
|
@@ -5626,7 +5827,7 @@ function fusedBody(pieces) {
|
|
|
5626
5827
|
...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
|
|
5627
5828
|
...needsHostReads ? [HOST_READS_DECL] : [],
|
|
5628
5829
|
// Each contributing artifact's namespaced private prelude (regexes, _pf, …).
|
|
5629
|
-
...[...
|
|
5830
|
+
...[...new Set(contributingPieces.flatMap((p) => p.prelude))],
|
|
5630
5831
|
// The winning `_r_<Name>` function for each rule (one per name → no redeclare).
|
|
5631
5832
|
...[...winner].map(([k, p]) => p.ruleFns.get(k))
|
|
5632
5833
|
];
|
|
@@ -5649,7 +5850,7 @@ function fusedBody(pieces) {
|
|
|
5649
5850
|
}
|
|
5650
5851
|
);
|
|
5651
5852
|
const env = {};
|
|
5652
|
-
for (const p of
|
|
5853
|
+
for (const p of contributingPieces) {
|
|
5653
5854
|
if (p.mfFns.length) env[`${p.ns}mf`] = p.mfFns;
|
|
5654
5855
|
if (p.buildFns.length) env[`${p.ns}build`] = p.buildFns;
|
|
5655
5856
|
}
|
|
@@ -5669,14 +5870,23 @@ function materializePiece(p) {
|
|
|
5669
5870
|
if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
|
|
5670
5871
|
return pieces;
|
|
5671
5872
|
}
|
|
5672
|
-
function
|
|
5873
|
+
function nextComposeNs(used) {
|
|
5874
|
+
let ns;
|
|
5875
|
+
do {
|
|
5876
|
+
ns = `_lk${_nsCounter++}_`;
|
|
5877
|
+
} while (used.has(ns));
|
|
5878
|
+
used.add(ns);
|
|
5879
|
+
return ns;
|
|
5880
|
+
}
|
|
5881
|
+
function itemPieces(item, used) {
|
|
5673
5882
|
const carried = item[COMPOSED_PIECES];
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
return
|
|
5883
|
+
const pieces = Array.isArray(carried) ? carried.map(materializePiece) : item.ruleFns instanceof Map ? [item] : [linkable(item, nextComposeNs(used))];
|
|
5884
|
+
for (const p of pieces) used.add(p.ns);
|
|
5885
|
+
return pieces;
|
|
5677
5886
|
}
|
|
5678
5887
|
function compose(items) {
|
|
5679
|
-
const
|
|
5888
|
+
const used = /* @__PURE__ */ new Set();
|
|
5889
|
+
const pieces = items.flatMap((item) => itemPieces(item, used));
|
|
5680
5890
|
const map = fuseRules(pieces);
|
|
5681
5891
|
Object.defineProperty(map, COMPOSED_PIECES, { value: pieces, enumerable: false });
|
|
5682
5892
|
return map;
|