parseman 0.61.4 → 0.61.6
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/dist/analysis/diagnostics.js +844 -522
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +846 -522
- package/dist/cli/index.js.map +3 -3
- package/dist/cst/capture-buffer.d.ts +3 -2
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/index.js +890 -523
- package/dist/index.js.map +3 -3
- package/dist/plugin/entry-supercompiler.d.ts +15 -0
- package/dist/plugin/entry-supercompiler.d.ts.map +1 -1
- package/dist/plugin/index.js +959 -503
- package/dist/plugin/index.js.map +3 -3
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/child-slots.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +1 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/fail-clean.d.ts.map +1 -1
- package/dist/table/hold-gap.d.ts.map +1 -1
- package/dist/table/index.js +421 -54
- package/dist/table/index.js.map +3 -3
- package/dist/table/late-frame.d.ts +18 -0
- package/dist/table/late-frame.d.ts.map +1 -0
- package/dist/table/ops.d.ts +17 -0
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/select-hot.d.ts +9 -0
- package/dist/table/select-hot.d.ts.map +1 -1
- package/dist/table/site-labels.d.ts +5 -1
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/cst/capture-buffer.ts +20 -11
- package/src/plugin/entry-supercompiler.ts +110 -1
- package/src/table/assemble.ts +124 -4
- package/src/table/child-slots.ts +9 -1
- package/src/table/emit-assembly.ts +101 -14
- package/src/table/encode.ts +69 -6
- package/src/table/exec.ts +7 -1
- package/src/table/fail-clean.ts +8 -1
- package/src/table/hold-gap.ts +5 -1
- package/src/table/late-frame.ts +54 -0
- package/src/table/ops.ts +19 -0
- package/src/table/select-hot.ts +96 -18
- package/src/table/site-labels.ts +38 -14
- package/src/version.ts +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type ContinuationGate = {
|
|
2
|
+
/** Class of the first character, past any trivia. */
|
|
3
|
+
readonly cls: number;
|
|
4
|
+
/** The regex row of a leading gap, or −1. */
|
|
5
|
+
readonly gapRow: number;
|
|
6
|
+
/** Class of the character after the gap. */
|
|
7
|
+
readonly follow: number;
|
|
8
|
+
/** Class of an arm that opens without the gap, or −1. */
|
|
9
|
+
readonly other: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function continuationGate(code: ArrayLike<number>, ip: number): ContinuationGate | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Can this assembly decide at this `OP_CONT`? It needs the tail's test, and the
|
|
14
|
+
* trivia the label names: a scope it cannot name, or one with no scanner, would cost a
|
|
15
|
+
* hit more calls than the frame it saves on a miss.
|
|
16
|
+
*/
|
|
17
|
+
export declare function canDecide(code: ArrayLike<number>, ip: number, tri: number, triviaScan: readonly unknown[]): boolean;
|
|
18
|
+
//# sourceMappingURL=late-frame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"late-frame.d.ts","sourceRoot":"","sources":["../../src/table/late-frame.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAoBlG;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAGnH"}
|
package/dist/table/ops.d.ts
CHANGED
|
@@ -508,6 +508,23 @@ export declare const OP_RGATE2 = 47;
|
|
|
508
508
|
* assembly resolves it to one child; it has no body of its own.
|
|
509
509
|
*/
|
|
510
510
|
export declare const OP_STRICT = 48;
|
|
511
|
+
/**
|
|
512
|
+
* `CONT corner wrapper tail` — a `collapse` node that is `sequence(corner, tail)`, with
|
|
513
|
+
* a tail that can take nothing and a corner that is one node. A strict assembly runs
|
|
514
|
+
* `corner` in the PARENT's collector and looks at the next token. Where `tail` cannot
|
|
515
|
+
* start there, the corner is the result: no frame, no children, no builder. Where it
|
|
516
|
+
* can, the corner's publication is taken back and `wrapper`'s frame opens around it and
|
|
517
|
+
* `tail`, in this one function. `tail` is read for the decision (`late-frame.ts`). Where
|
|
518
|
+
* no decision can be made, and under recovery, a probe or the reference driver, this
|
|
519
|
+
* is `wrapper`, the node as written.
|
|
520
|
+
*/
|
|
521
|
+
export declare const OP_CONT = 49;
|
|
522
|
+
/**
|
|
523
|
+
* `SEED corner` — marks the first term of `wrapper`'s body. Run, it is `corner`. It
|
|
524
|
+
* exists so the labels can leave out the edge from a late frame to its corner, which
|
|
525
|
+
* never runs there.
|
|
526
|
+
*/
|
|
527
|
+
export declare const OP_SEED = 50;
|
|
511
528
|
/**
|
|
512
529
|
* `DISPATCH sel d other otherRouted n a1 … an` — `dispatch()`.
|
|
513
530
|
*
|
package/dist/table/ops.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../src/table/ops.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../src/table/ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,15 @@ export declare function selectHotSites(code: readonly number[], entries: readonl
|
|
|
8
8
|
/** Measured calls per site (`countSiteVisits` over a corpus). Replaces the
|
|
9
9
|
* static estimate when given. */
|
|
10
10
|
profile?: ArrayLike<number>): Set<number>;
|
|
11
|
+
/**
|
|
12
|
+
* The sites the function for `ip` calls, as `emit-assembly.ts` lowers it. An `OP_CONT`
|
|
13
|
+
* with a body is a late frame, lowered with its wrapper in one function, calling its
|
|
14
|
+
* corner and its tail. With no body, the emitter can't decide there and it's an alias
|
|
15
|
+
* to its wrapper, as `OP_SEED` is to its corner. A gap gate has no body either, so its
|
|
16
|
+
* item counts as the repeat's own child, and adding the row moves no other site's
|
|
17
|
+
* estimate (`gap-gate.ts`).
|
|
18
|
+
*/
|
|
19
|
+
export declare function edgesAsLowered(code: readonly number[], siteBytes: ReadonlyMap<number, number>, ip: number, out: number[]): void;
|
|
11
20
|
/**
|
|
12
21
|
* The largest prefix of the ranking whose real source fits `ceiling`. `siteBytes`
|
|
13
22
|
* leaves out what sites add around their bodies, so the estimate can overshoot:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select-hot.d.ts","sourceRoot":"","sources":["../../src/table/select-hot.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"select-hot.d.ts","sourceRoot":"","sources":["../../src/table/select-hot.ts"],"names":[],"mappings":"AAqCA;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACtC,MAAM,EAAE,MAAM;AACd;iCACiC;AACjC,OAAO,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,GAC1B,GAAG,CAAC,MAAM,CAAC,CAUb;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAe/H;AAqDD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC;AACtC,2DAA2D;AAC3D,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,KAAK,MAAM,EACnD,OAAO,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,GAC1B;IAAE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAQ7E"}
|
|
@@ -69,6 +69,8 @@ export declare function gatedPassCollapse(code: Int32Array, ip: number, hostCst:
|
|
|
69
69
|
/** A site's label, or `TOP` for anything the walk did not reach. */
|
|
70
70
|
export type SiteLabels = {
|
|
71
71
|
at: (ip: number) => SiteLabel;
|
|
72
|
+
/** The `OP_CONT` sites whose corner runs in the parent's collector in every engine. */
|
|
73
|
+
late: ReadonlySet<number>;
|
|
72
74
|
};
|
|
73
75
|
/**
|
|
74
76
|
* Compute a label for every site reachable from `roots`.
|
|
@@ -82,7 +84,9 @@ export type SiteLabels = {
|
|
|
82
84
|
* The meet only ever moves a label toward `TOP`, and `TOP` is absorbing, so the
|
|
83
85
|
* lattice has height three and the walk terminates.
|
|
84
86
|
*/
|
|
85
|
-
export declare function computeSiteLabels(code: Int32Array, roots: Iterable<number>, hostCst: boolean
|
|
87
|
+
export declare function computeSiteLabels(code: Int32Array, roots: Iterable<number>, hostCst: boolean,
|
|
88
|
+
/** Does this assembly run this `OP_CONT` late, in EVERY engine it holds? Absent: none. */
|
|
89
|
+
late?: (ip: number, tri: number) => boolean): SiteLabels;
|
|
86
90
|
/**
|
|
87
91
|
* Does a piece entered at `ip` need the caller's INSTALLED trivia scanner handed
|
|
88
92
|
* across an engine boundary?
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"site-labels.d.ts","sourceRoot":"","sources":["../../src/table/site-labels.ts"],"names":[],"mappings":"AAqEA,iFAAiF;AACjF,eAAO,MAAM,WAAW,KAAK,CAAA;AAC7B,qDAAqD;AACrD,eAAO,MAAM,QAAQ,KAAK,CAAA;AAC1B,0EAA0E;AAE1E,qDAAqD;AACrD,eAAO,MAAM,WAAW,IAAI,CAAA;AAC5B,yDAAyD;AACzD,eAAO,MAAM,OAAO,IAAI,CAAA;AACxB,uDAAuD;AACvD,eAAO,MAAM,MAAM,IAAI,CAAA;AAIvB,uCAAuC;AACvC,eAAO,MAAM,WAAW,IAAI,CAAA;AAC5B,oDAAoD;AACpD,eAAO,MAAM,QAAQ,IAAI,CAAA;AAEzB,MAAM,MAAM,SAAS,GAAG;IACtB,mFAAmF;IACnF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;IACrB,kDAAkD;IAClD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wDAAwD;AACxD,eAAO,MAAM,GAAG,EAAE,SAAgF,CAAA;AAWlG;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAarF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAYpF;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAuB/I;AAqED,oEAAoE;AACpE,MAAM,MAAM,UAAU,GAAG;
|
|
1
|
+
{"version":3,"file":"site-labels.d.ts","sourceRoot":"","sources":["../../src/table/site-labels.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -13,5 +13,5 @@
|
|
|
13
13
|
* Kept in sync with `package.json` by `test/unit/version-sync.test.ts`, which fails
|
|
14
14
|
* the build if this constant drifts from the published version.
|
|
15
15
|
*/
|
|
16
|
-
export declare const PARSEMAN_VERSION = "0.61.
|
|
16
|
+
export declare const PARSEMAN_VERSION = "0.61.6";
|
|
17
17
|
//# sourceMappingURL=version.d.ts.map
|
package/package.json
CHANGED
|
@@ -122,26 +122,35 @@ export function pushCstChild(ctx: ParseContext, built: unknown, rawEntry: unknow
|
|
|
122
122
|
/**
|
|
123
123
|
* Undo the LAST `pushCstChild` into the active collector, whichever form it took:
|
|
124
124
|
* a child the lazy buffer's empty sentinel dropped (`undefined` first) leaves no
|
|
125
|
-
* semantic entry to remove, only its raw one.
|
|
125
|
+
* semantic entry to remove, only its raw one. Returns that raw entry, or `undefined`
|
|
126
|
+
* when this collector keeps none.
|
|
126
127
|
*/
|
|
127
|
-
export function popCstChild(ctx: ParseContext):
|
|
128
|
+
export function popCstChild(ctx: ParseContext): unknown {
|
|
128
129
|
const b = ctx._cstBuf
|
|
129
130
|
if (b) {
|
|
130
131
|
const ch = b.ch
|
|
131
|
-
if (b.rawOnly !== true
|
|
132
|
-
ch
|
|
133
|
-
|
|
132
|
+
if (b.rawOnly !== true) {
|
|
133
|
+
if (ch) {
|
|
134
|
+
ch.pop()
|
|
135
|
+
if (ch.length === 1) { b.single = ch[0]; b.ch = undefined }
|
|
136
|
+
} else b.single = undefined
|
|
137
|
+
}
|
|
138
|
+
if (b.noRaw === true) {
|
|
139
|
+
b.rawLen = (b.rawLen ?? 1) - 1
|
|
140
|
+
return undefined
|
|
134
141
|
}
|
|
135
|
-
if (b.
|
|
136
|
-
|
|
137
|
-
b.raw.pop()
|
|
142
|
+
if (b.raw) {
|
|
143
|
+
const entry = b.raw.pop()
|
|
138
144
|
if (b.raw.length === 1) { b.rawSingle = b.raw[0]; b.raw = undefined }
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
return entry
|
|
146
|
+
}
|
|
147
|
+
const entry = b.rawSingle
|
|
148
|
+
b.rawSingle = undefined
|
|
149
|
+
return entry
|
|
141
150
|
}
|
|
142
151
|
if (ctx._cstChildren) ctx._cstChildren.pop()
|
|
143
152
|
else if (ctx._cstLeaves) ctx._cstLeaves.pop()
|
|
144
|
-
|
|
153
|
+
return ctx._cstRawChildren?.pop()
|
|
145
154
|
}
|
|
146
155
|
|
|
147
156
|
export function cstRawLen(ctx: ParseContext): number {
|
|
@@ -65,6 +65,8 @@ type Call = {
|
|
|
65
65
|
type Edit = { readonly start: number; readonly end: number; readonly text: string }
|
|
66
66
|
|
|
67
67
|
const PIECE = /^_pf(\d+)$/
|
|
68
|
+
const MERGEABLE = /^_(?:pf|sk)\d+$/
|
|
69
|
+
const TEMP = /^_t\d+_/
|
|
68
70
|
const WRAP = 'function __parseman_supercompile__(){\n'
|
|
69
71
|
const SUFFIX = '\n}'
|
|
70
72
|
|
|
@@ -225,6 +227,113 @@ export function supercompileEntryAssembly(
|
|
|
225
227
|
return supercompileEmittedAssembly(prog, cfg, extraIps, emitted)
|
|
226
228
|
}
|
|
227
229
|
|
|
230
|
+
/** A name in the source: a site, or a temporary (`tmp` in `emit-assembly.ts`). */
|
|
231
|
+
type NameUse = { readonly start: number; readonly end: number; readonly name: string }
|
|
232
|
+
|
|
233
|
+
/** The uses of site and temporary names under `root`, and the names bound there. */
|
|
234
|
+
function namesUnder(root: Ast, uses: NameUse[], bound: Set<string>): boolean {
|
|
235
|
+
let plain = true
|
|
236
|
+
const bind = (id: Ast | undefined): void => {
|
|
237
|
+
const name = nameOf(id)
|
|
238
|
+
if (name !== undefined) bound.add(name)
|
|
239
|
+
}
|
|
240
|
+
const walk = (node: Ast, parent: Ast | undefined): void => {
|
|
241
|
+
if (node.type === 'VariableDeclarator') bind(ast(node.id))
|
|
242
|
+
else if (node.type === 'LabeledStatement') bind(ast(node.label))
|
|
243
|
+
else if (isFunction(node)) {
|
|
244
|
+
if (node !== root) bind(ast(node.id))
|
|
245
|
+
nodes(node.params).forEach(bind)
|
|
246
|
+
}
|
|
247
|
+
const name = nameOf(node)
|
|
248
|
+
if (name !== undefined && (MERGEABLE.test(name) || TEMP.test(name))) {
|
|
249
|
+
const isKey = parent?.type === 'Property' && parent.key === node && parent.computed !== true
|
|
250
|
+
const isProperty = parent?.type === 'MemberExpression' && parent.property === node && parent.computed !== true
|
|
251
|
+
if (parent?.type === 'Property' && parent.shorthand === true) plain = false
|
|
252
|
+
if (!isKey && !isProperty) uses.push({ ...range(node), name })
|
|
253
|
+
}
|
|
254
|
+
for (const child of children(node)) walk(child, node)
|
|
255
|
+
}
|
|
256
|
+
walk(root, undefined)
|
|
257
|
+
return plain
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Functions that read the same are one function: `optional(x)` written in 25 places
|
|
262
|
+
* is 25 rows and one body, and a trivia skip can be pooled under two labels that
|
|
263
|
+
* lower alike. This runs after the join, so a site with one caller has
|
|
264
|
+
* already gone into it, the selection is untouched and every call a parse makes is
|
|
265
|
+
* still made. Each pass can make the callers of a merged function read alike, so it
|
|
266
|
+
* repeats until nothing merges.
|
|
267
|
+
*
|
|
268
|
+
* Only identifiers are compared or renamed: a grammar's own text reaches this source
|
|
269
|
+
* as strings and regexes, and they count as written. A temporary is local by the
|
|
270
|
+
* emitter's contract and is numbered per assembly, so one this function binds is
|
|
271
|
+
* compared in order of use. A site name that's also bound somewhere, or abbreviated
|
|
272
|
+
* in `{_pf1}`, can't be renamed by name, so that source stays as it is.
|
|
273
|
+
*/
|
|
274
|
+
export function mergeSameBodies(source: string): string {
|
|
275
|
+
const parsed = parseSync('parseman-merge-same-bodies.js', WRAP + source + SUFFIX)
|
|
276
|
+
if (parsed.errors.length > 0) return source
|
|
277
|
+
const statements = nodes(ast(nodes((parsed.program as unknown as Ast).body)[0]?.body)?.body)
|
|
278
|
+
type Body = NameUse & { readonly uses: readonly NameUse[]; readonly local: ReadonlySet<string> }
|
|
279
|
+
const bodies: Body[] = []
|
|
280
|
+
const others: NameUse[] = []
|
|
281
|
+
const declared = new Set<string>()
|
|
282
|
+
for (const statement of statements) {
|
|
283
|
+
const name = statement.type === 'FunctionDeclaration' ? nameOf(ast(statement.id)) : undefined
|
|
284
|
+
const uses: NameUse[] = []
|
|
285
|
+
const bound = new Set<string>()
|
|
286
|
+
if (!namesUnder(statement, uses, bound)) return source
|
|
287
|
+
for (const local of bound) declared.add(local)
|
|
288
|
+
if (name === undefined || !MERGEABLE.test(name)) others.push(...uses)
|
|
289
|
+
else bodies.push({ ...range(statement), name, uses: uses.sort((a, b) => a.start - b.start), local: bound })
|
|
290
|
+
}
|
|
291
|
+
for (const local of declared) if (MERGEABLE.test(local)) return source
|
|
292
|
+
|
|
293
|
+
const merged = new Map<string, string>()
|
|
294
|
+
const current = (name: string): string => {
|
|
295
|
+
let at = name
|
|
296
|
+
for (let next = merged.get(at); next !== undefined; next = merged.get(at)) at = next
|
|
297
|
+
return at
|
|
298
|
+
}
|
|
299
|
+
let live = bodies
|
|
300
|
+
for (let more = true; more;) {
|
|
301
|
+
more = false
|
|
302
|
+
const first = new Map<string, string>()
|
|
303
|
+
live = live.filter(body => {
|
|
304
|
+
const temps = new Map<string, number>()
|
|
305
|
+
const edits = body.uses.map((use): Edit => {
|
|
306
|
+
if (MERGEABLE.test(use.name)) {
|
|
307
|
+
const site = current(use.name)
|
|
308
|
+
return { ...use, text: site === body.name ? '#self' : site }
|
|
309
|
+
}
|
|
310
|
+
if (!body.local.has(use.name)) return { ...use, text: use.name }
|
|
311
|
+
const seen = temps.get(use.name) ?? temps.size
|
|
312
|
+
temps.set(use.name, seen)
|
|
313
|
+
return { ...use, text: `#t${seen}` }
|
|
314
|
+
})
|
|
315
|
+
const key = render(source, body.start, body.end, edits)
|
|
316
|
+
const kept = first.get(key)
|
|
317
|
+
if (kept === undefined) { first.set(key, body.name); return true }
|
|
318
|
+
merged.set(body.name, kept)
|
|
319
|
+
more = true
|
|
320
|
+
return false
|
|
321
|
+
})
|
|
322
|
+
}
|
|
323
|
+
if (merged.size === 0) return source
|
|
324
|
+
|
|
325
|
+
const edits: Edit[] = []
|
|
326
|
+
const rename = (use: NameUse): void => {
|
|
327
|
+
if (MERGEABLE.test(use.name) && merged.has(use.name)) edits.push({ ...use, text: current(use.name) })
|
|
328
|
+
}
|
|
329
|
+
others.forEach(rename)
|
|
330
|
+
for (const body of bodies) {
|
|
331
|
+
if (merged.has(body.name)) edits.push({ start: body.start, end: body.end, text: '' })
|
|
332
|
+
else body.uses.forEach(rename)
|
|
333
|
+
}
|
|
334
|
+
return render(source, 0, source.length, edits)
|
|
335
|
+
}
|
|
336
|
+
|
|
228
337
|
/**
|
|
229
338
|
* Plugin-only final splice for an ordinary macro replacement. The table
|
|
230
339
|
* compiler emits its canonical callback-free public artifact first; this pass
|
|
@@ -274,7 +383,7 @@ export function supercompileRuleMapReplacement(
|
|
|
274
383
|
const start = body.start - prefix.length + 1
|
|
275
384
|
const end = body.end - prefix.length - 1
|
|
276
385
|
if (replacement.slice(start, end) !== FACTORY_ARITY_GUARD + canonical.source + '\n') return replacement
|
|
277
|
-
const transformed = replacement.slice(0, start) + FACTORY_ARITY_GUARD + candidate.source + '\n' + replacement.slice(end)
|
|
386
|
+
const transformed = replacement.slice(0, start) + FACTORY_ARITY_GUARD + mergeSameBodies(candidate.source) + '\n' + replacement.slice(end)
|
|
278
387
|
const checked = parseSync('parseman-entry-supercompile-replacement-result.js', prefix + transformed)
|
|
279
388
|
return checked.errors.length === 0 ? transformed : replacement
|
|
280
389
|
}
|
package/src/table/assemble.ts
CHANGED
|
@@ -83,6 +83,7 @@ import {
|
|
|
83
83
|
cstCaptureActive, cstLeavesLen, cstTlLen,
|
|
84
84
|
demoteCapturedToRaw, pushCstChild, pushCstLeaf,
|
|
85
85
|
type CstCaptureBuf,
|
|
86
|
+
popCstChild,
|
|
86
87
|
} from '../cst/capture-buffer.ts'
|
|
87
88
|
import { PlainBuf, PlainField, PlainLeaf, PlainNode, PlainSpan } from '../cst/plain.js'
|
|
88
89
|
import {
|
|
@@ -91,7 +92,7 @@ import {
|
|
|
91
92
|
OP_LIT_TRACK, OP_RX_TRACK, OP_NODE_TRACK, OP_SCOPE, OP_SCOPE_CAP, OP_SCOPE_PLAIN, SCOPE_INHERIT, OP_EXPECT, OP_SEQX, OP_SCAN,
|
|
92
93
|
OP_LIVE,
|
|
93
94
|
OP_FIELD, OP_DISPATCH, OP_ROUTED, OP_LIT_CI, OP_LIT_CI_TRACK, OP_TOKEN, OP_WITHCTX, OP_GUARD, OP_ATTEMPT, OP_LABEL,
|
|
94
|
-
OP_COV, OP_GAPGATE, OP_STRICT,
|
|
95
|
+
OP_COV, OP_GAPGATE, OP_STRICT, OP_CONT, OP_SEED,
|
|
95
96
|
OP_ADJ, OP_GREEDY, OP_REJECT, OP_ARMGATE, OP_RGATE, OP_RGATE2,
|
|
96
97
|
OP_LEX_BODY, OP_LEX_PROGRAM,
|
|
97
98
|
} from './ops.ts'
|
|
@@ -110,6 +111,7 @@ import {
|
|
|
110
111
|
type EmittedAssembly, type EmittedFactory,
|
|
111
112
|
} from './emit-assembly.ts'
|
|
112
113
|
import { collapseEmpty, lead, rawEntry, spanLines } from './run-support.ts'
|
|
114
|
+
import { canDecide, continuationGate } from './late-frame.ts'
|
|
113
115
|
import { holdsGap, rowNullable } from './hold-gap.ts'
|
|
114
116
|
import { gapRows, newGapSlot } from './gap-gate.ts'
|
|
115
117
|
import { failCleanAnalysis } from './fail-clean.ts'
|
|
@@ -133,7 +135,7 @@ import {
|
|
|
133
135
|
type SubtreeRef, type TableProgram, type TableRule,
|
|
134
136
|
} from './program.ts'
|
|
135
137
|
import { stampRuleMap } from './stamp.ts'
|
|
136
|
-
import { computeSiteLabels, gatedPassCollapse, passCollapse, reachableSites, scanHandoffNeeded, scopeIsIdentity, triviaLeadRanges } from './site-labels.ts'
|
|
138
|
+
import { CAP_OFF, CAP_ON, type SiteLabel, computeSiteLabels, gatedPassCollapse, passCollapse, reachableSites, scanHandoffNeeded, scopeIsIdentity, triviaLeadRanges, TRI_NONE } from './site-labels.ts'
|
|
137
139
|
import { refuseUnclassifiedRootScope } from '../cst/root-trivia-scope.ts'
|
|
138
140
|
import { captureError, firstSetSentinel, matchesAt, orSentinel, recoverScan } from '../recovery/scan.ts'
|
|
139
141
|
import {
|
|
@@ -544,6 +546,7 @@ export function assemble(t: ResolvedTable, prog: TableProgram, cfg: RunCfg): Ass
|
|
|
544
546
|
const GAP = newGapSlot()
|
|
545
547
|
const closureLabels = computeSiteLabels(
|
|
546
548
|
code, [...Object.values(prog.rules), ...labelExtraIps], hostCst,
|
|
549
|
+
cfg.tolerant || cfg.probe ? undefined : (ip, tri) => canDecide(code, ip, tri, t.triviaScan),
|
|
547
550
|
)
|
|
548
551
|
|
|
549
552
|
/**
|
|
@@ -1177,6 +1180,41 @@ export function assemble(t: ResolvedTable, prog: TableProgram, cfg: RunCfg): Ass
|
|
|
1177
1180
|
return cur
|
|
1178
1181
|
}
|
|
1179
1182
|
|
|
1183
|
+
/** Whether `cls` admits the character at `at`, without a call for the ASCII answer. */
|
|
1184
|
+
function startsTail(cls: ResolvedClass, input: string, at: number): boolean {
|
|
1185
|
+
const c = input.charCodeAt(at)
|
|
1186
|
+
return c < 128 ? cls.ascii[c] === 1 : classHas(cls, lead(input, at))
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
/**
|
|
1190
|
+
* The tail of a late frame. The gap was scanned to decide, so with no gap there is
|
|
1191
|
+
* nothing to record or undo, and with nothing recording it is not scanned again.
|
|
1192
|
+
*/
|
|
1193
|
+
function lateTail(tail: Piece, input: string, end: number, at: number, ctx: ParseContext, frame: SiteLabel): unknown {
|
|
1194
|
+
if (at === end) return tail(input, end, ctx)
|
|
1195
|
+
if (ctx._triviaLog === undefined && ctx._rootTriviaLog === undefined
|
|
1196
|
+
&& (frame.cap === CAP_OFF || !((frame.cap === CAP_ON || ctx.captureTrivia === true)
|
|
1197
|
+
&& (frame.buf || ctx._cstBuf !== undefined || ctx._cstTriviaLog !== undefined)))) {
|
|
1198
|
+
const v = tail(input, at, ctx)
|
|
1199
|
+
if (v !== FAIL && EC.e <= at) EC.e = end
|
|
1200
|
+
return v
|
|
1201
|
+
}
|
|
1202
|
+
const need = rollbackNeeded(ctx)
|
|
1203
|
+
const mTl = need ? cstTlLen(ctx) : 0
|
|
1204
|
+
const mLog = need ? ctx._triviaLog?.length ?? 0 : 0
|
|
1205
|
+
const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0
|
|
1206
|
+
const scanEnd = skipTrivia(input, end, ctx)
|
|
1207
|
+
const scanTl = need ? cstTlLen(ctx) : 0
|
|
1208
|
+
const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0
|
|
1209
|
+
const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0
|
|
1210
|
+
const v = tail(input, scanEnd, ctx)
|
|
1211
|
+
if (v !== FAIL && EC.e <= scanEnd) {
|
|
1212
|
+
if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot)
|
|
1213
|
+
EC.e = end
|
|
1214
|
+
}
|
|
1215
|
+
return v
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1180
1218
|
/** A non-first term at a site proven to run under an open node capture buffer. */
|
|
1181
1219
|
function nextTermBuffered(child: Piece, input: string, cur: number, ctx: ParseContext): number {
|
|
1182
1220
|
const t = ctx.trivia
|
|
@@ -1846,6 +1884,88 @@ export function assemble(t: ResolvedTable, prog: TableProgram, cfg: RunCfg): Ass
|
|
|
1846
1884
|
case OP_EMPTY:
|
|
1847
1885
|
return (_input, pos) => { EC.e = pos; return '' }
|
|
1848
1886
|
|
|
1887
|
+
case OP_SEED:
|
|
1888
|
+
return link(code[ip + 1]!)
|
|
1889
|
+
|
|
1890
|
+
case OP_CONT: {
|
|
1891
|
+
const wrapper = code[ip + 2]!
|
|
1892
|
+
if (!closureLabels.late.has(ip)) return lower(wrapper)
|
|
1893
|
+
const corner = link(code[ip + 1]!)
|
|
1894
|
+
const tail = link(code[ip + 3]!)
|
|
1895
|
+
const g = continuationGate(code, code[ip + 3]!)!
|
|
1896
|
+
const tri = closureLabels.at(ip).tri
|
|
1897
|
+
// The gap the tail would start past, read without recording anything: no scan
|
|
1898
|
+
// at a character no trivia can start.
|
|
1899
|
+
const scan = tri === TRI_NONE ? undefined : t.triviaScan[tri]!
|
|
1900
|
+
const leads = tri === TRI_NONE ? null : LEAD_TABLES[tri]!
|
|
1901
|
+
const cls = cc[g.cls]!
|
|
1902
|
+
const gapRe = g.gapRow < 0 ? undefined : k[code[g.gapRow + 1]!] as RegExp
|
|
1903
|
+
const follow = g.follow < 0 ? undefined : cc[g.follow]!
|
|
1904
|
+
const other = g.other < 0 ? undefined : cc[g.other]!
|
|
1905
|
+
const mayStartPastGap = (input: string, at: number): boolean => {
|
|
1906
|
+
gapRe!.lastIndex = at
|
|
1907
|
+
const q = gapRe!.test(input) ? gapRe!.lastIndex : -1
|
|
1908
|
+
return (q >= 0 && classHas(follow!, lead(input, q))) || (other !== undefined && classHas(other, lead(input, at)))
|
|
1909
|
+
}
|
|
1910
|
+
const frame = closureLabels.at(code[wrapper + 2]!)
|
|
1911
|
+
const flags = code[wrapper + 3]!
|
|
1912
|
+
const buildIdx = code[wrapper + 1]!
|
|
1913
|
+
// The seed for this frame, handed over before anything can parse.
|
|
1914
|
+
let held: unknown
|
|
1915
|
+
let heldRaw: unknown
|
|
1916
|
+
let heldEnd = 0
|
|
1917
|
+
let heldAt = 0
|
|
1918
|
+
const omitsRaw = !hostCst && buildIdx >= 0 && code[wrapper + 4]! < 0 && (flags & 2) !== 0
|
|
1919
|
+
const body: Piece = omitsRaw
|
|
1920
|
+
? (input, _pos, ctx) => {
|
|
1921
|
+
const b = ctx._cstBuf
|
|
1922
|
+
if (b !== undefined) {
|
|
1923
|
+
b.single = held
|
|
1924
|
+
b.rawLen = 1
|
|
1925
|
+
} else ctx._cstChildren!.push(held)
|
|
1926
|
+
held = undefined
|
|
1927
|
+
heldRaw = undefined
|
|
1928
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame)
|
|
1929
|
+
}
|
|
1930
|
+
: (input, pos, ctx) => {
|
|
1931
|
+
const b = ctx._cstBuf
|
|
1932
|
+
if (b !== undefined) {
|
|
1933
|
+
b.single = held
|
|
1934
|
+
b.rawSingle = heldRaw ?? rawEntry(held, input, pos, heldEnd)
|
|
1935
|
+
} else ctx._cstChildren!.push(held)
|
|
1936
|
+
held = undefined
|
|
1937
|
+
heldRaw = undefined
|
|
1938
|
+
return lateTail(tail, input, heldEnd, heldAt, ctx, frame)
|
|
1939
|
+
}
|
|
1940
|
+
let open: Piece
|
|
1941
|
+
// An AST reducer: the frame is one of the two lean bodies. Any other frame is
|
|
1942
|
+
// the node's own closure, with `body` for its child.
|
|
1943
|
+
if (!hostCst && !cfg.trackLines && code[wrapper] === OP_NODE && code[wrapper + 4]! < 0 && (flags === 32 || flags === 34)) {
|
|
1944
|
+
const build = fns[buildIdx] as NodeBuilder
|
|
1945
|
+
open = flags === 34 ? childrenOnlyCollapseBuildNode(body, build) : collapseBuildNode(body, build)
|
|
1946
|
+
} else {
|
|
1947
|
+
NODE_BODY = body
|
|
1948
|
+
open = lower(wrapper)
|
|
1949
|
+
}
|
|
1950
|
+
return (input, pos, ctx) => {
|
|
1951
|
+
const v = corner(input, pos, ctx)
|
|
1952
|
+
if (v === FAIL) return FAIL
|
|
1953
|
+
const end = EC.e
|
|
1954
|
+
let at = end
|
|
1955
|
+
if (scan !== undefined) {
|
|
1956
|
+
const c = input.charCodeAt(end)
|
|
1957
|
+
if (leads === null || !(c < 128) || leads[c] !== 0) at = scan(input, end)
|
|
1958
|
+
}
|
|
1959
|
+
if (v !== undefined && !(gapRe === undefined ? startsTail(cls, input, at) : mayStartPastGap(input, at))) return v
|
|
1960
|
+
if (ctx._cstBuf === undefined && ctx._cstRawChildren === undefined && ctx._cstChildren !== undefined) ctx._cstChildren.pop()
|
|
1961
|
+
else if (ctx._cstBuf !== undefined || ctx._cstChildren !== undefined) heldRaw = popCstChild(ctx)
|
|
1962
|
+
held = v
|
|
1963
|
+
heldEnd = end
|
|
1964
|
+
heldAt = at
|
|
1965
|
+
return open(input, pos, ctx)
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1849
1969
|
/* ── transparent / structural ────────────────────────────────────────── */
|
|
1850
1970
|
|
|
1851
1971
|
case OP_GUARD: {
|
|
@@ -4290,7 +4410,7 @@ export function assemble(t: ResolvedTable, prog: TableProgram, cfg: RunCfg): Ass
|
|
|
4290
4410
|
matchesAt, recoverScan, orSentinel, captureError,
|
|
4291
4411
|
scalarRecognizers, t.lex, adjacencyHolds, t.lexPrograms,
|
|
4292
4412
|
LEAD, triviaFieldCapture, skipDeferredTrivia,
|
|
4293
|
-
collapseEmpty,
|
|
4413
|
+
collapseEmpty, popCstChild,
|
|
4294
4414
|
PlainSpan, PlainLeaf, PlainNode, PlainField, PlainBuf, GAP,
|
|
4295
4415
|
)
|
|
4296
4416
|
emitReached = new Set(pre.reached)
|
|
@@ -4375,7 +4495,7 @@ export function assemble(t: ResolvedTable, prog: TableProgram, cfg: RunCfg): Ass
|
|
|
4375
4495
|
matchesAt, recoverScan, orSentinel, captureError,
|
|
4376
4496
|
scalarRecognizers, t.lex, adjacencyHolds, t.lexPrograms,
|
|
4377
4497
|
LEAD, triviaFieldCapture, skipDeferredTrivia,
|
|
4378
|
-
collapseEmpty,
|
|
4498
|
+
collapseEmpty, popCstChild,
|
|
4379
4499
|
PlainSpan, PlainLeaf, PlainNode, PlainField, PlainBuf, GAP,
|
|
4380
4500
|
)
|
|
4381
4501
|
emitReached = em.reached
|
package/src/table/child-slots.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
OP_LIT_CI_TRACK, OP_LIT_TRACK, OP_LIVE, OP_NODE, OP_NODE_TRACK, OP_NOT, OP_OPT,
|
|
5
5
|
OP_PEEK, OP_REJECT, OP_REP, OP_REPV, OP_ROUTED, OP_RULE, OP_RX, OP_RX_TRACK, OP_SCAN,
|
|
6
6
|
OP_SCOPE, OP_SCOPE_CAP, OP_SCOPE_PLAIN, OP_SEQ, OP_SEQV, OP_SEQX, OP_TOKEN, OP_WITHCTX, OP_XFORM,
|
|
7
|
-
OP_LEX_BODY, OP_LEX_PROGRAM, OP_GAPGATE, OP_RGATE2, OP_STRICT,
|
|
7
|
+
OP_LEX_BODY, OP_LEX_PROGRAM, OP_GAPGATE, OP_RGATE2, OP_STRICT, OP_CONT, OP_SEED,
|
|
8
8
|
} from './ops.ts'
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -73,6 +73,14 @@ export function childSlotOffsets(code: ArrayLike<number>, ip: number, out: numbe
|
|
|
73
73
|
out.push(ip + 2)
|
|
74
74
|
return true
|
|
75
75
|
|
|
76
|
+
// `CONT corner wrapper tail`: `tail` is reached through `wrapper`.
|
|
77
|
+
case OP_CONT:
|
|
78
|
+
out.push(ip + 1, ip + 2)
|
|
79
|
+
return true
|
|
80
|
+
case OP_SEED:
|
|
81
|
+
out.push(ip + 1)
|
|
82
|
+
return true
|
|
83
|
+
|
|
76
84
|
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
77
85
|
case OP_STRICT:
|
|
78
86
|
out.push(ip + 1, ip + 2)
|