parseman 0.45.0 → 0.47.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 +8 -3
- package/dist/analysis/choice-cost-gate.d.ts +158 -0
- package/dist/analysis/choice-cost-gate.d.ts.map +1 -0
- package/dist/analysis/choice-cost-render.d.ts +96 -0
- package/dist/analysis/choice-cost-render.d.ts.map +1 -0
- package/dist/analysis/choice-cost.d.ts +383 -0
- package/dist/analysis/choice-cost.d.ts.map +1 -0
- package/dist/analysis/commitment.d.ts +131 -0
- package/dist/analysis/commitment.d.ts.map +1 -0
- package/dist/analysis/corpus.d.ts +73 -0
- package/dist/analysis/corpus.d.ts.map +1 -0
- package/dist/analysis/diagnose-render.d.ts +65 -0
- package/dist/analysis/diagnose-render.d.ts.map +1 -0
- package/dist/analysis/diagnose.d.ts +15 -0
- package/dist/analysis/diagnose.d.ts.map +1 -1
- package/dist/analysis/diagnostics.cjs +13736 -0
- package/dist/analysis/diagnostics.cjs.map +6 -0
- package/dist/analysis/diagnostics.d.ts +27 -0
- package/dist/analysis/diagnostics.d.ts.map +1 -0
- package/dist/analysis/diagnostics.js +13713 -0
- package/dist/analysis/diagnostics.js.map +6 -0
- package/dist/analysis/duplication.d.ts.map +1 -1
- package/dist/analysis/fix-render.d.ts +43 -0
- package/dist/analysis/fix-render.d.ts.map +1 -0
- package/dist/analysis/fix.d.ts +172 -0
- package/dist/analysis/fix.d.ts.map +1 -0
- package/dist/analysis/format-number.d.ts +23 -0
- package/dist/analysis/format-number.d.ts.map +1 -0
- package/dist/analysis/gating.d.ts +47 -2
- package/dist/analysis/gating.d.ts.map +1 -1
- package/dist/analysis/rebuild.d.ts +61 -0
- package/dist/analysis/rebuild.d.ts.map +1 -0
- package/dist/analysis/terminal.d.ts +145 -0
- package/dist/analysis/terminal.d.ts.map +1 -0
- package/dist/cli/index.cjs +14837 -0
- package/dist/cli/index.cjs.map +6 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +14814 -0
- package/dist/cli/index.js.map +6 -0
- package/dist/combinators/adjacency.d.ts +100 -0
- package/dist/combinators/adjacency.d.ts.map +1 -0
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/completions.d.ts.map +1 -1
- package/dist/combinators/dispatch.d.ts +8 -1
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/gate.d.ts.map +1 -1
- package/dist/combinators/grammar.d.ts +22 -0
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/literal.d.ts +8 -0
- package/dist/combinators/literal.d.ts.map +1 -1
- package/dist/combinators/map.d.ts +0 -1
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +13 -3
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/combinators/parser.d.ts +1 -1
- package/dist/combinators/parser.d.ts.map +1 -1
- package/dist/combinators/ref.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts +1 -16
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/repeat.d.ts +30 -2
- package/dist/combinators/repeat.d.ts.map +1 -1
- package/dist/combinators/scanTo.d.ts +71 -1
- package/dist/combinators/scanTo.d.ts.map +1 -1
- package/dist/combinators/sequence.d.ts.map +1 -1
- package/dist/combinators/token.d.ts.map +1 -1
- package/dist/combinators/trivia-boundary.d.ts +26 -0
- package/dist/combinators/trivia-boundary.d.ts.map +1 -0
- package/dist/combinators/trivia-skip.d.ts +40 -1
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/combinators/withCtx.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts.map +1 -1
- package/dist/compiler/compile-linkable-table.d.ts +104 -0
- package/dist/compiler/compile-linkable-table.d.ts.map +1 -0
- package/dist/compiler/degradation.d.ts +0 -2
- package/dist/compiler/degradation.d.ts.map +1 -1
- package/dist/compiler/fields.d.ts +13 -0
- package/dist/compiler/fields.d.ts.map +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts +5 -5
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +79 -47
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts +81 -0
- package/dist/compiler/token-alphabet.d.ts.map +1 -0
- package/dist/compiler/token-dispatch.d.ts +95 -0
- package/dist/compiler/token-dispatch.d.ts.map +1 -0
- package/dist/compiler/token-scanner.d.ts +53 -0
- package/dist/compiler/token-scanner.d.ts.map +1 -0
- package/dist/compiler/value-usage.d.ts.map +1 -1
- package/dist/coverage.d.ts +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/capture-buffer.d.ts +35 -0
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/cst/reflection-attach.d.ts +8 -0
- package/dist/cst/reflection-attach.d.ts.map +1 -0
- package/dist/cst/reflection-symbols.d.ts +10 -0
- package/dist/cst/reflection-symbols.d.ts.map +1 -0
- package/dist/cst/reflection.d.ts +2 -4
- package/dist/cst/reflection.d.ts.map +1 -1
- package/dist/cst/root-trivia-scope.d.ts +26 -0
- package/dist/cst/root-trivia-scope.d.ts.map +1 -0
- package/dist/cst/trivia-charscan.d.ts +18 -0
- package/dist/cst/trivia-charscan.d.ts.map +1 -0
- package/dist/cst/trivia-kinds.d.ts +19 -0
- package/dist/cst/trivia-kinds.d.ts.map +1 -1
- package/dist/functional/doc.d.ts.map +1 -1
- package/dist/functional/run-tabled.d.ts +12 -0
- package/dist/functional/run-tabled.d.ts.map +1 -0
- package/dist/functional/run.d.ts +25 -42
- package/dist/functional/run.d.ts.map +1 -1
- package/dist/grammar-metadata.d.ts +3 -0
- package/dist/grammar-metadata.d.ts.map +1 -0
- package/dist/index.cjs +10499 -7478
- package/dist/index.cjs.map +3 -4
- package/dist/index.d.ts +24 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10499 -7478
- package/dist/index.js.map +3 -4
- package/dist/language-service/index.cjs +311 -121
- package/dist/language-service/index.cjs.map +3 -4
- package/dist/language-service/index.js +311 -121
- package/dist/language-service/index.js.map +3 -4
- package/dist/oracle/index.cjs.map +0 -1
- package/dist/oracle/index.js.map +0 -1
- package/dist/parse-context.d.ts +49 -0
- package/dist/parse-context.d.ts.map +1 -0
- package/dist/plugin/evaluator.d.ts +41 -2
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/free-identifiers.d.ts +23 -0
- package/dist/plugin/free-identifiers.d.ts.map +1 -0
- package/dist/plugin/index.cjs +11381 -9442
- package/dist/plugin/index.cjs.map +3 -4
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +11381 -9442
- package/dist/plugin/index.js.map +3 -4
- package/dist/plugin/reducer-resolver.d.ts +17 -1
- package/dist/plugin/reducer-resolver.d.ts.map +1 -1
- package/dist/regex/classes.d.ts +28 -0
- package/dist/regex/classes.d.ts.map +1 -1
- package/dist/regex/first-set.d.ts +14 -0
- package/dist/regex/first-set.d.ts.map +1 -1
- package/dist/run/index.cjs +136 -51
- package/dist/run/index.cjs.map +2 -3
- package/dist/run/index.js +136 -51
- package/dist/run/index.js.map +2 -3
- package/dist/spec/index.cjs +2898 -1622
- package/dist/spec/index.cjs.map +3 -4
- package/dist/spec/index.js +2898 -1622
- package/dist/spec/index.js.map +3 -4
- package/dist/spec/model.d.ts +8 -0
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/table/assemble.d.ts +307 -0
- package/dist/table/assemble.d.ts.map +1 -0
- package/dist/table/cell.d.ts +42 -0
- package/dist/table/cell.d.ts.map +1 -0
- package/dist/table/child-slots.d.ts +30 -0
- package/dist/table/child-slots.d.ts.map +1 -0
- package/dist/table/compile-rule-map.d.ts +136 -0
- package/dist/table/compile-rule-map.d.ts.map +1 -0
- package/dist/table/compile.d.ts +56 -0
- package/dist/table/compile.d.ts.map +1 -0
- package/dist/table/duplication-hook.d.ts +32 -0
- package/dist/table/duplication-hook.d.ts.map +1 -0
- package/dist/table/emit-assembly.d.ts +139 -0
- package/dist/table/emit-assembly.d.ts.map +1 -0
- package/dist/table/emit.d.ts +113 -0
- package/dist/table/emit.d.ts.map +1 -0
- package/dist/table/encode-baseline.d.ts +16 -0
- package/dist/table/encode-baseline.d.ts.map +1 -0
- package/dist/table/encode.d.ts +71 -0
- package/dist/table/encode.d.ts.map +1 -0
- package/dist/table/exec-baseline.d.ts +9 -0
- package/dist/table/exec-baseline.d.ts.map +1 -0
- package/dist/table/exec.d.ts +72 -0
- package/dist/table/exec.d.ts.map +1 -0
- package/dist/table/fold.d.ts +25 -0
- package/dist/table/fold.d.ts.map +1 -0
- package/dist/table/index.cjs +11375 -0
- package/dist/table/index.cjs.map +6 -0
- package/dist/table/index.d.ts +100 -0
- package/dist/table/index.d.ts.map +1 -0
- package/dist/table/index.js +11352 -0
- package/dist/table/index.js.map +6 -0
- package/dist/table/inspect.d.ts +17 -0
- package/dist/table/inspect.d.ts.map +1 -0
- package/dist/table/ops.d.ts +446 -0
- package/dist/table/ops.d.ts.map +1 -0
- package/dist/table/program.d.ts +493 -0
- package/dist/table/program.d.ts.map +1 -0
- package/dist/table/run-support.d.ts +38 -0
- package/dist/table/run-support.d.ts.map +1 -0
- package/dist/{compiler/scannable-run.d.ts → table/scan-shapes.d.ts} +14 -13
- package/dist/table/scan-shapes.d.ts.map +1 -0
- package/dist/table/site-labels.d.ts +58 -0
- package/dist/table/site-labels.d.ts.map +1 -0
- package/dist/table/stamp.d.ts +70 -0
- package/dist/table/stamp.d.ts.map +1 -0
- package/dist/types.d.ts +80 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +41 -3
- package/src/analysis/choice-cost-gate.ts +359 -0
- package/src/analysis/choice-cost-render.ts +293 -0
- package/src/analysis/choice-cost.ts +1008 -0
- package/src/analysis/commitment.ts +557 -0
- package/src/analysis/corpus.ts +130 -0
- package/src/analysis/diagnose-render.ts +625 -0
- package/src/analysis/diagnose.ts +317 -0
- package/src/analysis/diagnostics.ts +33 -0
- package/src/analysis/duplication.ts +1955 -0
- package/src/analysis/fix-render.ts +217 -0
- package/src/analysis/fix.ts +669 -0
- package/src/analysis/format-number.ts +31 -0
- package/src/analysis/gating.ts +792 -0
- package/src/analysis/grammar.ts +72 -0
- package/src/analysis/rebuild.ts +287 -0
- package/src/analysis/terminal.ts +336 -0
- package/src/cli/index.ts +413 -0
- package/src/combinators/adjacency.ts +171 -0
- package/src/combinators/attempt.ts +41 -0
- package/src/combinators/case-fold.ts +90 -0
- package/src/combinators/choice.ts +466 -0
- package/src/combinators/completions.ts +64 -0
- package/src/combinators/dispatch.ts +358 -0
- package/src/combinators/expect.ts +159 -0
- package/src/combinators/first-set.ts +322 -0
- package/src/combinators/gate.ts +50 -0
- package/src/combinators/grammar.ts +272 -0
- package/src/combinators/keywords.ts +145 -0
- package/src/combinators/literal.ts +102 -0
- package/src/combinators/map.ts +106 -0
- package/src/combinators/node.ts +345 -0
- package/src/combinators/not.ts +55 -0
- package/src/combinators/parser.ts +266 -0
- package/src/combinators/peek.ts +63 -0
- package/src/combinators/probe.ts +25 -0
- package/src/combinators/ref.ts +109 -0
- package/src/combinators/regex.ts +170 -0
- package/src/combinators/repeat.ts +561 -0
- package/src/combinators/scanTo.ts +393 -0
- package/src/combinators/sequence.ts +221 -0
- package/src/combinators/token.ts +120 -0
- package/src/combinators/trivia-boundary.ts +48 -0
- package/src/combinators/trivia-skip.ts +821 -0
- package/src/combinators/withCtx.ts +45 -0
- package/src/compiler/build-arity.ts +330 -0
- package/src/compiler/compile-linkable-table.ts +209 -0
- package/src/compiler/degradation.ts +266 -0
- package/src/compiler/fields.ts +191 -0
- package/src/compiler/grammar-coverage-ids.ts +129 -0
- package/src/compiler/ir-serialize.ts +615 -0
- package/src/compiler/linker.ts +954 -0
- package/src/compiler/token-alphabet.ts +209 -0
- package/src/compiler/token-dispatch.ts +353 -0
- package/src/compiler/token-scanner.ts +318 -0
- package/src/compiler/value-usage.ts +147 -0
- package/src/coverage.ts +383 -0
- package/src/cst/capture-buffer.ts +297 -0
- package/src/cst/host-mode.ts +69 -0
- package/src/cst/reflection-attach.ts +11 -0
- package/src/cst/reflection-symbols.ts +9 -0
- package/src/cst/reflection.ts +149 -0
- package/src/cst/relative-spans.ts +207 -0
- package/src/cst/root-trivia-scope.ts +30 -0
- package/src/cst/trivia-charscan.ts +312 -0
- package/src/cst/trivia-entries.ts +285 -0
- package/src/cst/trivia-index.ts +131 -0
- package/src/cst/trivia-kinds.ts +358 -0
- package/src/cst/types.ts +76 -0
- package/src/cst/walk.ts +101 -0
- package/src/functional/doc.ts +959 -0
- package/src/functional/run-tabled.ts +153 -0
- package/src/functional/run.ts +558 -0
- package/src/grammar-metadata.ts +2 -0
- package/src/index.ts +189 -0
- package/src/language-service/index.ts +221 -0
- package/src/line-index.ts +131 -0
- package/src/oracle/digest.ts +620 -0
- package/src/oracle/index.ts +55 -0
- package/src/parse-context.ts +91 -0
- package/src/plugin/direct-builder-static.ts +102 -0
- package/src/plugin/evaluator.ts +1505 -0
- package/src/plugin/free-identifiers.ts +338 -0
- package/src/plugin/index.ts +2281 -0
- package/src/plugin/reducer-resolver.ts +606 -0
- package/src/recovery/scan.ts +155 -0
- package/src/regex/classes.ts +183 -0
- package/src/regex/first-set.ts +316 -0
- package/src/run/index.ts +31 -0
- package/src/spec/ebnf.ts +128 -0
- package/src/spec/index.ts +54 -0
- package/src/spec/model.ts +636 -0
- package/src/spec/railroad-lib.ts +559 -0
- package/src/spec/railroad.ts +256 -0
- package/src/table/assemble.ts +2994 -0
- package/src/table/cell.ts +42 -0
- package/src/table/child-slots.ts +113 -0
- package/src/table/compile-rule-map.ts +336 -0
- package/src/table/compile.ts +244 -0
- package/src/table/duplication-hook.ts +89 -0
- package/src/table/emit-assembly.ts +1766 -0
- package/src/table/emit.ts +418 -0
- package/src/table/encode-baseline.ts +340 -0
- package/src/table/encode.ts +1569 -0
- package/src/table/exec-baseline.ts +537 -0
- package/src/table/exec.ts +1672 -0
- package/src/table/fold.ts +38 -0
- package/src/table/index.ts +108 -0
- package/src/table/inspect.ts +52 -0
- package/src/table/ops.ts +459 -0
- package/src/table/program.ts +855 -0
- package/src/table/run-support.ts +66 -0
- package/src/table/scan-shapes.ts +1578 -0
- package/src/table/site-labels.ts +228 -0
- package/src/table/stamp.ts +229 -0
- package/src/types.ts +563 -0
- package/src/version.ts +16 -0
- package/dist/compiler/codegen.d.ts +0 -334
- package/dist/compiler/codegen.d.ts.map +0 -1
- package/dist/compiler/inline-build.d.ts +0 -11
- package/dist/compiler/inline-build.d.ts.map +0 -1
- package/dist/compiler/inline-callback.d.ts +0 -21
- package/dist/compiler/inline-callback.d.ts.map +0 -1
- package/dist/compiler/line-index.d.ts +0 -2
- package/dist/compiler/line-index.d.ts.map +0 -1
- package/dist/compiler/scannable-run.d.ts.map +0 -1
- package/dist/compiler/scannable-terminal.d.ts +0 -23
- package/dist/compiler/scannable-terminal.d.ts.map +0 -1
- package/dist/compiler/trivia-fast-path.d.ts +0 -38
- package/dist/compiler/trivia-fast-path.d.ts.map +0 -1
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CHOICE COST — the shape of an ordered choice, and what that shape costs.
|
|
3
|
+
* ========================================================================
|
|
4
|
+
*
|
|
5
|
+
* READ THIS FIRST: THIS MEASURES THE INTERPRETER, NOT THE SHIPPED PARSER.
|
|
6
|
+
* ----------------------------------------------------------------------
|
|
7
|
+
* The interpreter's `firstMatch` loop (src/combinators/choice.ts:149-165) enters every
|
|
8
|
+
* alternative unconditionally. The EMITTED engine does not: `src/table/emit-assembly.ts`
|
|
9
|
+
* hoists a per-choice candidate mask and emits a per-arm first-CHARACTER guard, so an arm
|
|
10
|
+
* whose first set excludes the character at the current position is never entered.
|
|
11
|
+
* First-set gating is this project's single largest parse lever — 25-48% across all
|
|
12
|
+
* four jess parsers — and a naive interpreted profile is blind to every byte of it.
|
|
13
|
+
*
|
|
14
|
+
* So `profileWastedWork` reports TWO columns and derives neither from the other:
|
|
15
|
+
* `attempts`/`wastedBytes` (interpreted) and `gatedAttempts`/`gatedWastedBytes`
|
|
16
|
+
* (modelling codegen's guard — see `compiledFirstCharGate`). Rankings use the compiled
|
|
17
|
+
* column. The DELTA is itself a result: an arm expensive interpreted and cheap gated is
|
|
18
|
+
* ALREADY SOLVED by codegen, and reordering it is unpaid work.
|
|
19
|
+
*
|
|
20
|
+
* WHAT THE GATE ACTUALLY REMOVES — measured, not assumed.
|
|
21
|
+
* Over jess's four dialect grammars (637 kB of CSS, 212 kB of Less):
|
|
22
|
+
*
|
|
23
|
+
* dialect arms whose GATED BYTES differ arm entries removed by the gate
|
|
24
|
+
* css 0 of 158 331,313 of 435,767 (76%)
|
|
25
|
+
* less 0 of 199 413,737 of 562,852 (74%)
|
|
26
|
+
* scss 0 of 200 617,735 of 777,356 (79%)
|
|
27
|
+
* jess 0 of 158 325,655 of 388,263 (84%)
|
|
28
|
+
*
|
|
29
|
+
* The gate removes ATTEMPTS, not rescanned BYTES — and the byte columns are identical
|
|
30
|
+
* to the byte in all four. That is structural, not a coincidence of these corpora: the
|
|
31
|
+
* guard is derived from the arm's first SET, which over-approximates what the arm can
|
|
32
|
+
* start with, so whenever the guard rejects, the arm's own leading terminal would have
|
|
33
|
+
* rejected at the same position having consumed nothing.
|
|
34
|
+
*
|
|
35
|
+
* The practical consequence, and the reason this warning is at the top: any claim of
|
|
36
|
+
* the form "this arm is entered on every X and fails N% of the time" is a statement
|
|
37
|
+
* about the INTERPRETER and is usually false of the shipped parser. A byte ranking
|
|
38
|
+
* survives the correction; a failure-RATE or attempt-count claim does not. Measured on
|
|
39
|
+
* jess's CSS `Value` choice, arm 0 `Percentage` reads as 25,939 entries at 97% failure
|
|
40
|
+
* interpreted, and 7,455 at 90% gated — the same arm, a fifth as important. Arm 4
|
|
41
|
+
* `IdentBlock` is 100% failure in BOTH columns and carries 27,131 bytes; it is the real
|
|
42
|
+
* finding, and only the gated column makes that legible.
|
|
43
|
+
*
|
|
44
|
+
* KNOWN LIMIT OF THE MODEL. On the compose/linkable path a named-rule arm gets a
|
|
45
|
+
* DEFERRED guard (an `@FS:name@` placeholder) that fuse time rewrites with the winning rule's
|
|
46
|
+
* first set — or with `true`, always-try, if it cannot be resolved. This model always
|
|
47
|
+
* resolves, so for cross-artifact ref arms `gatedAttempts` is a LOWER bound: the
|
|
48
|
+
* shipped artifact may enter such an arm more often than modelled. Where a compiled
|
|
49
|
+
* measurement disagrees with this report on an arm that is a bare rule reference, the
|
|
50
|
+
* compiled measurement is right.
|
|
51
|
+
*
|
|
52
|
+
* A PEG `choice` is ordered: arm `i` is only reached once arms `0..i-1` have been
|
|
53
|
+
* TRIED AND FAILED, and every one of those failures re-scanned input that the
|
|
54
|
+
* winning arm then scans again. So each additional alternative, and each earlier
|
|
55
|
+
* alternative, has a time cost — and that cost is invisible in the grammar source,
|
|
56
|
+
* which is why grammar shape drifts without anything going red.
|
|
57
|
+
*
|
|
58
|
+
* This module makes it visible, in two halves that answer two different questions.
|
|
59
|
+
*
|
|
60
|
+
* STATIC — `analyzeChoiceInventory()`
|
|
61
|
+
* Which choice sites have alternatives that share a leading term, and for each:
|
|
62
|
+
* did the compiler LEFT-FACTOR it, or did it decline, and why? `detectSharedPrefix`
|
|
63
|
+
* (src/combinators/choice.ts) already computes this to decide whether to emit the
|
|
64
|
+
* `sharedPrefix` strategy, but it is ALL-OR-NOTHING (every arm must share) and it
|
|
65
|
+
* returns `null` on the first arm that does not qualify — silently, with no record
|
|
66
|
+
* of how close the site came or which arm blocked it. The inventory reports the
|
|
67
|
+
* declines, with the blocking arm and the reason. That set is the refactor backlog,
|
|
68
|
+
* GENERATED rather than noticed by a human reading grammar source.
|
|
69
|
+
*
|
|
70
|
+
* It is complete, not sampled: every `choice` reachable from the rule map appears,
|
|
71
|
+
* including the ones with nothing to report (`groups: []`).
|
|
72
|
+
*
|
|
73
|
+
* DYNAMIC — `profileWastedWork()`
|
|
74
|
+
* How many BYTES were re-scanned because an alternative was tried and failed,
|
|
75
|
+
* attributed per choice site and per arm, over a real corpus. Ordering pathologies
|
|
76
|
+
* fall out of the ranking for free: an arm that fails 98% of the time while sitting
|
|
77
|
+
* first is exactly the top entry.
|
|
78
|
+
*
|
|
79
|
+
* The static half can only see shape. It cannot know that one declined site is on
|
|
80
|
+
* the hot path of every stylesheet and another is reached twice a year. The dynamic
|
|
81
|
+
* half supplies that weight. Neither is sufficient alone.
|
|
82
|
+
*
|
|
83
|
+
* WHY BYTES, AND WHY THIS IS GATEABLE
|
|
84
|
+
* -----------------------------------
|
|
85
|
+
* The metric is a COUNT of input bytes, not a timing. It is a pure function of
|
|
86
|
+
* (grammar, corpus): the same grammar over the same corpus yields the same number on
|
|
87
|
+
* an idle machine and on a machine at load 10. There is no noise floor to argue about
|
|
88
|
+
* and no rebaseline needed for a hardware change. That is what makes it usable as a
|
|
89
|
+
* deterministic gate rather than a benchmark.
|
|
90
|
+
*
|
|
91
|
+
* INTERPRETED MODE ONLY
|
|
92
|
+
* ---------------------
|
|
93
|
+
* Nothing here is emitted into a compiled parser and nothing here costs codegen a
|
|
94
|
+
* single byte or a single millisecond. The profiler does not add an instrumentation
|
|
95
|
+
* flag to the hot combinators either — `src/combinators/choice.ts` is UNTOUCHED by
|
|
96
|
+
* this file. Instrumentation is installed by temporarily substituting arm slots and
|
|
97
|
+
* terminal `parse` methods on the combinator tree, and removed in a `finally`. When
|
|
98
|
+
* you are not profiling, the cost is exactly zero because the shipping code contains
|
|
99
|
+
* no profiling branch to skip.
|
|
100
|
+
*
|
|
101
|
+
* (For contrast: `run({ profile })` — the node/slot-count profiler — was compiled-path
|
|
102
|
+
* only, was never implemented in the interpreter, and now throws rather than reporting
|
|
103
|
+
* zeros. See src/functional/run.ts. This is a different measurement and a new build,
|
|
104
|
+
* not a port of that one.)
|
|
105
|
+
*
|
|
106
|
+
* WHAT THIS INSTRUMENT CANNOT SEE
|
|
107
|
+
* -------------------------------
|
|
108
|
+
* Stated up front, because a diagnostic whose blind spots are undocumented gets read
|
|
109
|
+
* as complete:
|
|
110
|
+
*
|
|
111
|
+
* 0. It measures the INTERPRETER. See the top of this header — this is the blind spot
|
|
112
|
+
* that reorders results rather than merely shifting them, which is why it is not
|
|
113
|
+
* in this list but above it. The `gated*` columns model it; they do not remove it.
|
|
114
|
+
* 1. Only `firstMatch` and `sharedPrefix` choices are instrumented. Those are the
|
|
115
|
+
* two strategies that try arms in order and can fail one. A `disjoint` choice
|
|
116
|
+
* dispatches on the first character and tries exactly one arm; `greedyClassify`
|
|
117
|
+
* runs one regex; `literalsLongestFirst` captures its sorted arm array at
|
|
118
|
+
* construction, so slot substitution cannot reach it. Their sites still appear
|
|
119
|
+
* in the static inventory, with zero dynamic cost recorded and `instrumented:
|
|
120
|
+
* false` so the zero is not mistaken for a measurement.
|
|
121
|
+
* 2. Backtracking that is not a choice arm — a failed `many` element, a failed
|
|
122
|
+
* `optional`, a rolled-back `attempt` — is not attributed. Those bytes are real
|
|
123
|
+
* but they are not an ORDERING decision, which is what this instrument exists to
|
|
124
|
+
* rank.
|
|
125
|
+
* 3. An arm that SUCCEEDS and is then rejected by the `autoNot` check is recorded as
|
|
126
|
+
* a success, because the rejection happens inside the choice loop after the arm
|
|
127
|
+
* has returned. Its rescan is invisible here.
|
|
128
|
+
* 4. `wastedBytes` is input bytes re-scanned, not CPU. An arm that fails after one
|
|
129
|
+
* byte but allocated on the way is cheap by this metric and not by the clock.
|
|
130
|
+
* This ranks ORDERING, and is deliberately not a profiler.
|
|
131
|
+
*
|
|
132
|
+
* SET EXPECTATIONS ACCORDINGLY, because this has been measured. A jess lane acted
|
|
133
|
+
* on a finding from this report and cut rescanned bytes at one route from 27,678
|
|
134
|
+
* to 8,367 — a 69.8% reduction, exactly as this instrument predicts — for ZERO
|
|
135
|
+
* measurable wall-clock change. A large byte win that produces no time win is the
|
|
136
|
+
* expected outcome, not a failure of the fix: re-scanning is cheap per byte, and
|
|
137
|
+
* what makes a grammar slow is usually allocation and node construction, which
|
|
138
|
+
* this metric cannot see. Use it to find and rank ORDERING defects and to prove a
|
|
139
|
+
* restructure did what it claimed. Do not use it to predict a speedup, and do not
|
|
140
|
+
* let a flat benchmark be read as evidence the finding was wrong.
|
|
141
|
+
* 5. Reach is measured by the furthest position at which a TERMINAL was attempted
|
|
142
|
+
* (`literal`/`regex`/`keywords`/`scanTo`). A combinator that consumes without
|
|
143
|
+
* going through one of those would under-report; none exists today.
|
|
144
|
+
*/
|
|
145
|
+
import type { Combinator } from '../types.ts';
|
|
146
|
+
import type { ChoiceStrategyTag } from './gating.ts';
|
|
147
|
+
import type { FirstSet } from '../types.ts';
|
|
148
|
+
/** A combinator's location in the grammar: owning rule plus structural path. */
|
|
149
|
+
export type ChoiceSite = {
|
|
150
|
+
/** Nearest enclosing `_ruleName`, or the rule-map key it was reached under. */
|
|
151
|
+
rule: string;
|
|
152
|
+
/** Structural path inside that rule, e.g. `seq[2] › node(AtRule) › choice[0]`. */
|
|
153
|
+
path: string;
|
|
154
|
+
};
|
|
155
|
+
/** The stable identity of a site. Used as the sort key and the baseline key, so it
|
|
156
|
+
* must be derived only from grammar structure — never from a file path or a run. */
|
|
157
|
+
export declare const choiceSiteKey: (s: ChoiceSite) => string;
|
|
158
|
+
/** Why one ARM contributed no shareable leading term. */
|
|
159
|
+
export type ArmDeclineReason =
|
|
160
|
+
/** The arm is not a (wrapper-peeled) `sequence` — e.g. a bare ref, a nested
|
|
161
|
+
* `choice`, an `optional`. `leadingTermOfArm` peels only node/grammar/transform/
|
|
162
|
+
* label, because those are the wrappers that consume nothing before the sequence. */
|
|
163
|
+
'not-a-sequence'
|
|
164
|
+
/** A `sequence` of one term: there is no residual to factor out from. */
|
|
165
|
+
| 'sequence-shorter-than-2'
|
|
166
|
+
/** The leading term is a case-INSENSITIVE literal. Excluded deliberately: the
|
|
167
|
+
* matched text differs from the literal's own value, so a replayed leaf would
|
|
168
|
+
* carry the wrong string. */
|
|
169
|
+
| 'lead-case-insensitive-literal'
|
|
170
|
+
/** The leading term is not a bare literal/regex — a ref, a node, a label, a
|
|
171
|
+
* transform, another choice. Factoring through it would change the value or
|
|
172
|
+
* capture shape of the arm. */
|
|
173
|
+
| 'lead-not-concrete-terminal';
|
|
174
|
+
/** Why the SITE as a whole was not left-factored. */
|
|
175
|
+
export type SiteDeclineReason =
|
|
176
|
+
/** First-char dispatch already selects exactly one arm; there is nothing to factor.
|
|
177
|
+
* Not a backlog entry — this is the good state. */
|
|
178
|
+
'disjoint-dispatch'
|
|
179
|
+
/** At least one arm carries a runtime gate; per-arm predicates are incompatible
|
|
180
|
+
* with the factoring strategies. */
|
|
181
|
+
| 'gated-arms'
|
|
182
|
+
/** `greedyClassify` or `literalsLongestFirst` matched first. Both are stronger than
|
|
183
|
+
* `sharedPrefix` (neither backtracks), so this is also not a backlog entry. */
|
|
184
|
+
| 'strategy-preempted'
|
|
185
|
+
/** Fewer than two arms. */
|
|
186
|
+
| 'fewer-than-two-arms'
|
|
187
|
+
/** At least one arm produced no shareable leading term. See `armDeclines` for which
|
|
188
|
+
* arm and why. THIS is the backlog: a subset of arms may still share a prefix that
|
|
189
|
+
* the all-or-nothing detector never records. */
|
|
190
|
+
| 'arms-not-factorable'
|
|
191
|
+
/** Every arm produced a leading term, but they are not all the same term. Also the
|
|
192
|
+
* backlog: two arms out of nine sharing `@` is real, repeated work. */
|
|
193
|
+
| 'leads-differ';
|
|
194
|
+
/** A maximal set of arms at one site sharing an identical concrete leading term. */
|
|
195
|
+
export type PrefixGroup = {
|
|
196
|
+
/** Structural key of the shared term. Injective by construction (JSON-encoded), so
|
|
197
|
+
* two structurally different regexes can never collide onto one group. */
|
|
198
|
+
key: string;
|
|
199
|
+
/** Human rendering, e.g. `"@"` or `/[-\w]+/`. */
|
|
200
|
+
render: string;
|
|
201
|
+
/** Arm indices, ascending. */
|
|
202
|
+
members: readonly number[];
|
|
203
|
+
};
|
|
204
|
+
export type ChoiceInventoryEntry = {
|
|
205
|
+
site: ChoiceSite;
|
|
206
|
+
siteKey: string;
|
|
207
|
+
arity: number;
|
|
208
|
+
strategy: ChoiceStrategyTag;
|
|
209
|
+
disjoint: boolean;
|
|
210
|
+
gated: boolean;
|
|
211
|
+
/** Every group of >= 2 arms sharing a concrete leading term, ordered by member
|
|
212
|
+
* count descending then key. Empty when no two arms share one. */
|
|
213
|
+
groups: readonly PrefixGroup[];
|
|
214
|
+
/** Per-arm reasons, ascending by arm index. Only arms that produced no key. */
|
|
215
|
+
armDeclines: readonly {
|
|
216
|
+
arm: number;
|
|
217
|
+
reason: ArmDeclineReason;
|
|
218
|
+
detail: string;
|
|
219
|
+
}[];
|
|
220
|
+
factored: boolean;
|
|
221
|
+
/** Present iff `factored` is false. */
|
|
222
|
+
declineReason?: SiteDeclineReason;
|
|
223
|
+
/** Arms that sit in some group but whose site was NOT factored — the count of
|
|
224
|
+
* alternatives currently re-scanning a prefix a sibling already scanned. */
|
|
225
|
+
unfactoredArms: number;
|
|
226
|
+
};
|
|
227
|
+
export type ChoiceInventoryReport = {
|
|
228
|
+
readonly schema: 'parseman.choice-inventory/1';
|
|
229
|
+
rules: number;
|
|
230
|
+
/** Distinct `choice` combinator instances reachable from the rule map. */
|
|
231
|
+
choiceSites: number;
|
|
232
|
+
factoredSites: number;
|
|
233
|
+
/** Sites with >= 1 prefix group that were NOT factored. The backlog. */
|
|
234
|
+
backlogSites: number;
|
|
235
|
+
backlogArms: number;
|
|
236
|
+
/**
|
|
237
|
+
* Rule-map entries that are unresolvable references — a `g.X` hole that only
|
|
238
|
+
* `compose()` binds. Their subtrees were NOT walked, so this report is partial by
|
|
239
|
+
* exactly this much. Ascending. Empty is the only value that means "complete".
|
|
240
|
+
*/
|
|
241
|
+
unresolvedRoots: readonly string[];
|
|
242
|
+
/** Ascending by `siteKey`. Complete — every reachable choice, including the ones
|
|
243
|
+
* with nothing to report. */
|
|
244
|
+
entries: readonly ChoiceInventoryEntry[];
|
|
245
|
+
};
|
|
246
|
+
export type WastedWorkArm = {
|
|
247
|
+
siteKey: string;
|
|
248
|
+
site: ChoiceSite;
|
|
249
|
+
arm: number;
|
|
250
|
+
/** Short rendering of the arm's head, so the ranked list reads without opening
|
|
251
|
+
* the grammar. */
|
|
252
|
+
label: string;
|
|
253
|
+
/** INTERPRETED: every entry, because the interpreter's firstMatch loop gates nothing. */
|
|
254
|
+
attempts: number;
|
|
255
|
+
failures: number;
|
|
256
|
+
/** INTERPRETED: input bytes re-scanned by this arm's FAILED attempts, summed over the
|
|
257
|
+
* corpus. For one attempt: (furthest position a terminal was tried) - (entry position). */
|
|
258
|
+
wastedBytes: number;
|
|
259
|
+
/** True when codegen emits a first-char guard for this arm, i.e. the shipped parser
|
|
260
|
+
* enters it less often than the interpreter does. */
|
|
261
|
+
firstCharGated: boolean;
|
|
262
|
+
/** COMPILED MODEL: entries that survive codegen's first-char guard. This is the
|
|
263
|
+
* number the shipped parser actually pays. Equals `attempts` when `firstCharGated`
|
|
264
|
+
* is false. */
|
|
265
|
+
gatedAttempts: number;
|
|
266
|
+
gatedFailures: number;
|
|
267
|
+
/** COMPILED MODEL: the ranking column. Bytes re-scanned by failed attempts that
|
|
268
|
+
* codegen's guard would NOT have skipped. */
|
|
269
|
+
gatedWastedBytes: number;
|
|
270
|
+
};
|
|
271
|
+
export type WastedWorkSite = {
|
|
272
|
+
siteKey: string;
|
|
273
|
+
site: ChoiceSite;
|
|
274
|
+
strategy: ChoiceStrategyTag;
|
|
275
|
+
arity: number;
|
|
276
|
+
/** False when the strategy cannot be instrumented; then `wastedBytes` is 0 because
|
|
277
|
+
* nothing was measured, NOT because nothing was wasted. */
|
|
278
|
+
instrumented: boolean;
|
|
279
|
+
attempts: number;
|
|
280
|
+
failures: number;
|
|
281
|
+
wastedBytes: number;
|
|
282
|
+
gatedAttempts: number;
|
|
283
|
+
gatedFailures: number;
|
|
284
|
+
gatedWastedBytes: number;
|
|
285
|
+
};
|
|
286
|
+
export type WastedWorkReport = {
|
|
287
|
+
readonly schema: 'parseman.wasted-work/1';
|
|
288
|
+
corpusFiles: number;
|
|
289
|
+
corpusBytes: number;
|
|
290
|
+
parsedOk: number;
|
|
291
|
+
parsedFailed: number;
|
|
292
|
+
/** Sites the profiler installed instrumentation on. */
|
|
293
|
+
instrumentedSites: number;
|
|
294
|
+
/** Reachable choice sites whose strategy cannot be instrumented (see the module
|
|
295
|
+
* header, blind spot 1). Reported so a low total is not read as a clean grammar. */
|
|
296
|
+
uninstrumentableSites: number;
|
|
297
|
+
/** Rule-map entries that are unresolvable references; their subtrees carry no
|
|
298
|
+
* instrumentation, so the total below is a LOWER BOUND by exactly this much. */
|
|
299
|
+
unresolvedRoots: readonly string[];
|
|
300
|
+
/** INTERPRETED total. Read `totalGatedWastedBytes` for what the shipped parser pays. */
|
|
301
|
+
totalWastedBytes: number;
|
|
302
|
+
/** COMPILED MODEL total — the headline number, and the one a gate should use. */
|
|
303
|
+
totalGatedWastedBytes: number;
|
|
304
|
+
/** Descending by `gatedWastedBytes`, then `wastedBytes`, then `siteKey`, then `arm`. */
|
|
305
|
+
arms: readonly WastedWorkArm[];
|
|
306
|
+
/**
|
|
307
|
+
* ORDERING INVERSIONS: arms that were attempted at least `inversionMinAttempts`
|
|
308
|
+
* times and failed EVERY time, while a later arm at the same site matched.
|
|
309
|
+
*
|
|
310
|
+
* A second ranking, because bytes alone answer the wrong question for the clearest
|
|
311
|
+
* class of defect. Measured on jess's CSS grammar: `StylesheetAtRule › dispatch[3]`
|
|
312
|
+
* has arm 0 failing 19 of 19 attempts while arm 1 matches — an unambiguous ordering
|
|
313
|
+
* bug — yet it is only the 14th largest site by bytes, because the prelude it
|
|
314
|
+
* re-scans is short. Bytes rank what costs most; this ranks what is most obviously
|
|
315
|
+
* WRONG. Both are in the report and neither is derived from the other.
|
|
316
|
+
*
|
|
317
|
+
* Computed from the GATED columns, so an arm codegen already skips is not reported
|
|
318
|
+
* as an inversion in a parser that never enters it.
|
|
319
|
+
*
|
|
320
|
+
* Descending by `gatedAttempts` — NOT by bytes. An arm can fail 100% of its attempts
|
|
321
|
+
* and re-scan zero bytes, because it fails on its own first terminal; jess's `Value`
|
|
322
|
+
* arm 8 `CustomPropertyValue` does exactly that, 925 times, and is the one ungated arm
|
|
323
|
+
* at that site. Ranked by bytes it is invisible; ranked by attempts it is a finding.
|
|
324
|
+
*/
|
|
325
|
+
inversions: readonly WastedWorkArm[];
|
|
326
|
+
/** Descending by `wastedBytes`, then ascending by `siteKey`. */
|
|
327
|
+
sites: readonly WastedWorkSite[];
|
|
328
|
+
};
|
|
329
|
+
/** A short, deterministic rendering of an arm's head, for the ranked list. */
|
|
330
|
+
export declare function armLabel(arm: Combinator<unknown>): string;
|
|
331
|
+
/**
|
|
332
|
+
* Every `choice` reachable from `ruleMap`, with its shared-prefix groups and whether
|
|
333
|
+
* the compiler factored the site.
|
|
334
|
+
*
|
|
335
|
+
* Complete by construction: the walk visits every reachable combinator instance and
|
|
336
|
+
* emits an entry for each `choice`, whether or not it has anything to report. A site
|
|
337
|
+
* missing from this report is a site the walk could not reach, never a site that was
|
|
338
|
+
* judged uninteresting.
|
|
339
|
+
*/
|
|
340
|
+
export declare function analyzeChoiceInventory(ruleMap: ReadonlyArray<readonly [string, Combinator<unknown>]>): ChoiceInventoryReport;
|
|
341
|
+
/** Exposed so the fidelity test can compare the model against emitted guards. */
|
|
342
|
+
export declare function modelledFirstCharGate(p: Combinator<unknown>): FirstSet | null;
|
|
343
|
+
export type WastedWorkCorpusEntry = {
|
|
344
|
+
/** Stable identifier. Use a repo-relative path, never an absolute one — it appears
|
|
345
|
+
* in the report, and an absolute path would make the report machine-dependent. */
|
|
346
|
+
id: string;
|
|
347
|
+
text: string;
|
|
348
|
+
};
|
|
349
|
+
export type ProfileWastedWorkOptions = {
|
|
350
|
+
/** The combinator rule map, for site naming and instrumentation. */
|
|
351
|
+
rules: ReadonlyArray<readonly [string, Combinator<unknown>]>;
|
|
352
|
+
/** The rule to start each parse at. A key of `rules`, or a combinator. */
|
|
353
|
+
entry: string | Combinator<unknown>;
|
|
354
|
+
corpus: ReadonlyArray<WastedWorkCorpusEntry>;
|
|
355
|
+
/** Passed through to `run()`. Must not contain anything machine-dependent. */
|
|
356
|
+
runOptions?: Record<string, unknown>;
|
|
357
|
+
/**
|
|
358
|
+
* How to parse one corpus entry. Defaults to `run()` in interpreted mode.
|
|
359
|
+
*
|
|
360
|
+
* Overridable because a grammar can need a driver of its own — jess's Less dialect,
|
|
361
|
+
* for instance, requires `state: { source: input }` because its reducers read it —
|
|
362
|
+
* and because a caller who has already built a driver should not have to duplicate
|
|
363
|
+
* it here. It must be a plain interpreted parse; anything compiled defeats the
|
|
364
|
+
* instrumentation silently, since a compiled artifact never reads `def.parsers`.
|
|
365
|
+
*/
|
|
366
|
+
runner?: (entry: Combinator<unknown>, input: string, options: Record<string, unknown>) => {
|
|
367
|
+
ok: boolean;
|
|
368
|
+
};
|
|
369
|
+
/** Minimum attempts before an always-failing arm counts as an ordering inversion.
|
|
370
|
+
* Default 4 — below that, "failed every time" is a sample size, not a finding. */
|
|
371
|
+
inversionMinAttempts?: number;
|
|
372
|
+
};
|
|
373
|
+
/**
|
|
374
|
+
* Parse `corpus` with `rules` in INTERPRETED mode, counting input bytes re-scanned
|
|
375
|
+
* by failed choice alternatives.
|
|
376
|
+
*
|
|
377
|
+
* Fails closed on every way of measuring nothing: an empty rule map, an unknown entry
|
|
378
|
+
* rule, an empty corpus, an empty corpus file, or a grammar in which no instrumentable
|
|
379
|
+
* choice site exists. Each of those would otherwise produce a report of zero wasted
|
|
380
|
+
* bytes, which reads as a clean grammar.
|
|
381
|
+
*/
|
|
382
|
+
export declare function profileWastedWork(opts: ProfileWastedWorkOptions): WastedWorkReport;
|
|
383
|
+
//# sourceMappingURL=choice-cost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choice-cost.d.ts","sourceRoot":"","sources":["../../src/analysis/choice-cost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+IG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAwC,MAAM,aAAa,CAAA;AACnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAIpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAI3C,gFAAgF;AAChF,MAAM,MAAM,UAAU,GAAG;IACvB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAA;IACZ,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;qFACqF;AACrF,eAAO,MAAM,aAAa,MAAO,UAAU,KAAG,MACI,CAAA;AAIlD,yDAAyD;AACzD,MAAM,MAAM,gBAAgB;AAC1B;;sFAEsF;AACpF,gBAAgB;AAClB,yEAAyE;GACvE,yBAAyB;AAC3B;;8BAE8B;GAC5B,+BAA+B;AACjC;;gCAEgC;GAC9B,4BAA4B,CAAA;AAEhC,qDAAqD;AACrD,MAAM,MAAM,iBAAiB;AAC3B;oDACoD;AAClD,mBAAmB;AACrB;qCACqC;GACnC,YAAY;AACd;gFACgF;GAC9E,oBAAoB;AACtB,2BAA2B;GACzB,qBAAqB;AACvB;;iDAEiD;GAC/C,qBAAqB;AACvB;wEACwE;GACtE,cAAc,CAAA;AAElB,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG;IACxB;+EAC2E;IAC3E,GAAG,EAAE,MAAM,CAAA;IACX,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAA;IACd,8BAA8B;IAC9B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,OAAO,CAAA;IACd;uEACmE;IACnE,MAAM,EAAE,SAAS,WAAW,EAAE,CAAA;IAC9B,+EAA+E;IAC/E,WAAW,EAAE,SAAS;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,gBAAgB,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACjF,QAAQ,EAAE,OAAO,CAAA;IACjB,uCAAuC;IACvC,aAAa,CAAC,EAAE,iBAAiB,CAAA;IACjC;iFAC6E;IAC7E,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,MAAM,EAAE,6BAA6B,CAAA;IAC9C,KAAK,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC;kCAC8B;IAC9B,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAA;CACzC,CAAA;AAID,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,UAAU,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX;uBACmB;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB;gGAC4F;IAC5F,WAAW,EAAE,MAAM,CAAA;IACnB;0DACsD;IACtD,cAAc,EAAE,OAAO,CAAA;IACvB;;oBAEgB;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB;kDAC8C;IAC9C,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb;gEAC4D;IAC5D,YAAY,EAAE,OAAO,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAA;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,uDAAuD;IACvD,iBAAiB,EAAE,MAAM,CAAA;IACzB;yFACqF;IACrF,qBAAqB,EAAE,MAAM,CAAA;IAC7B;qFACiF;IACjF,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,wFAAwF;IACxF,gBAAgB,EAAE,MAAM,CAAA;IACxB,iFAAiF;IACjF,qBAAqB,EAAE,MAAM,CAAA;IAC7B,wFAAwF;IACxF,IAAI,EAAE,SAAS,aAAa,EAAE,CAAA;IAC9B;;;;;;;;;;;;;;;;;;OAkBG;IACH,UAAU,EAAE,SAAS,aAAa,EAAE,CAAA;IACpC,gEAAgE;IAChE,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;CACjC,CAAA;AA2KD,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,MAAM,CAwBzD;AAID;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAC7D,qBAAqB,CAmFvB;AAsFD,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,QAAQ,GAAG,IAAI,CAE7E;AAiBD,MAAM,MAAM,qBAAqB,GAAG;IAClC;uFACmF;IACnF,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,oEAAoE;IACpE,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAC5D,0EAA0E;IAC1E,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;IACnC,MAAM,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAA;IAC5C,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK;QAAE,EAAE,EAAE,OAAO,CAAA;KAAE,CAAA;IACzG;uFACmF;IACnF,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B,CAAA;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,gBAAgB,CAkNlF"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMMITMENT ANALYSIS — where a construct can still fail after it has consumed
|
|
3
|
+
* input or dirtied the capture buffers.
|
|
4
|
+
*
|
|
5
|
+
* This is a whole-grammar property of the rule graph, and it has exactly two
|
|
6
|
+
* consumers: the compiler, which bakes the decisions into the emitted source,
|
|
7
|
+
* and the interpreter, which must reach the SAME decisions at load time. It
|
|
8
|
+
* lives here, in one module, for that reason. Two hand-written copies of a
|
|
9
|
+
* predicate like `mayFail` would drift, and a drift here is not a size
|
|
10
|
+
* regression — it is the compiled and interpreted parsers accepting different
|
|
11
|
+
* languages. One module, two consumers.
|
|
12
|
+
*
|
|
13
|
+
* Every predicate in this file is a sound OVER-approximation of "something can
|
|
14
|
+
* go wrong": each MUST err toward `true`. A `false` is a proof obligation
|
|
15
|
+
* discharged on the caller's behalf, and callers delete code on the strength of
|
|
16
|
+
* it. Elide only where non-failure is PROVEN; when in doubt, say `true` and keep
|
|
17
|
+
* the machinery.
|
|
18
|
+
*/
|
|
19
|
+
import type { Combinator } from '../types.ts';
|
|
20
|
+
/**
|
|
21
|
+
* Can `p` FAIL at all?
|
|
22
|
+
*
|
|
23
|
+
* `false` needs a construct whose definition is total: the empty literal,
|
|
24
|
+
* trivia (a scan of width 0 is a match), and the repeats — but the repeats only
|
|
25
|
+
* conditionally, see below.
|
|
26
|
+
*
|
|
27
|
+
* Everything else stays `true`, including two cases that look elidable and are
|
|
28
|
+
* not. A `choice` whose last arm is infallible is NOT infallible, because
|
|
29
|
+
* first-set gating decides at runtime which arms are entered at all and the
|
|
30
|
+
* total arm may be skipped. And a re-entered cycle is `true` rather than
|
|
31
|
+
* `false`: a recursive rule's own fallibility is exactly what the recursion is
|
|
32
|
+
* being asked about, so the safe fixpoint seed is the conservative one.
|
|
33
|
+
*
|
|
34
|
+
* TODO(0.47): `expect` is conservative here. It converts its inner parser's
|
|
35
|
+
* failure into a zero-width success carrying a parse-error node and therefore
|
|
36
|
+
* never fails, but it currently reports its inner parser's fallibility. Making
|
|
37
|
+
* it `false` would elide further; it needs its own pass through the tree-diff
|
|
38
|
+
* gate first, because `expect` sits at exactly the closing-delimiter positions
|
|
39
|
+
* where a wrong answer is most visible.
|
|
40
|
+
*/
|
|
41
|
+
export declare function mayFail(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Does `p`, WHEN IT SUCCEEDS, always consume at least one character?
|
|
44
|
+
*
|
|
45
|
+
* The mirror of `mayFail`, and the opposite polarity from
|
|
46
|
+
* `first-set.ts`'s `matchesEmpty`: this one MUST err toward `false`. A `true`
|
|
47
|
+
* is a proof that the success path advanced the position, and the sequence
|
|
48
|
+
* emitter deletes a trivia rewind on the strength of it.
|
|
49
|
+
*
|
|
50
|
+
* It cannot be written as `!matchesEmpty(p)`. `matchesEmpty` answers a
|
|
51
|
+
* first-set question and is allowed to under-report nullability; for `expect`
|
|
52
|
+
* it does, and that case is exactly the one that matters here. `expect(X)`
|
|
53
|
+
* turns X's FAILURE into a zero-width SUCCESS carrying a parse-error node —
|
|
54
|
+
* so `expect(literal('}'))` succeeds having consumed nothing, while
|
|
55
|
+
* `matchesEmpty` looks through to the non-nullable literal and says "always
|
|
56
|
+
* consumes". Eliding on that answer moves a rule's span end past trailing
|
|
57
|
+
* trivia (measured: 38 tree mismatches across the css corpus, spans absorbing
|
|
58
|
+
* whitespace their legacy build excluded). `recover` manufactures the same
|
|
59
|
+
* zero-width success, and both are `false` here.
|
|
60
|
+
*
|
|
61
|
+
* `dispatch` is `false` rather than deferring to its selector: the selector's
|
|
62
|
+
* consumption is not unconditionally part of the dispatch's own span, and the
|
|
63
|
+
* few bytes are not worth the proof obligation.
|
|
64
|
+
*/
|
|
65
|
+
export declare function alwaysConsumes(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* True when parsing `p` may push a capture (leaf/child/trivia) into the active
|
|
68
|
+
* buffers and THEN fail, leaving partial state that an enclosing node() would
|
|
69
|
+
* wrongly absorb. Used to decide whether a fallible block needs CST-rollback.
|
|
70
|
+
*
|
|
71
|
+
* Sound over-approximation: the ONLY constructs that capture-then-fail are
|
|
72
|
+
* - a sequence whose non-final term captures before a later term can fail
|
|
73
|
+
* - a sepBy/oneOrMore item-then-separator partial (handled by their own
|
|
74
|
+
* dedicated rollback, so still covered conservatively here)
|
|
75
|
+
* Atomic terminals (literal/regex/keywords/charClass/guard/not) fail without
|
|
76
|
+
* having captured. node() buffers into a private sub-scope and discards it on
|
|
77
|
+
* failure, so it never leaks. choice/firstMatch roll back each failed arm
|
|
78
|
+
* internally. optional/many never "fail" with partial output. Delegating
|
|
79
|
+
* wrappers (transform/label/grammar/withCtx/expect) pass through to inner.
|
|
80
|
+
*/
|
|
81
|
+
export declare function mayLeavePartialCapture(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>, triviaActive?: boolean): boolean;
|
|
82
|
+
/** True when `p` can push a leaf/node into the capture buffers on success. */
|
|
83
|
+
export declare function capturesLeaf(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Does this combinator tree contain a node() anywhere (following ref/lazy
|
|
86
|
+
* thunks)? Determines whether the compile emits CST capture — so non-node
|
|
87
|
+
* grammars stay byte-identical. `seen` guards against recursion cycles.
|
|
88
|
+
*/
|
|
89
|
+
export declare function hasNodeDef(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Whether a grammar tree owns a DIRECT semantic node reduction — a `node(..., build)`
|
|
92
|
+
* whose callback produces the value itself, as opposed to a purely structural
|
|
93
|
+
* `node(parser)`.
|
|
94
|
+
*
|
|
95
|
+
* It is the predicate behind `hostBranchElided`: an artifact only drops a
|
|
96
|
+
* positioned-CST branch if there was a direct builder to drop, so an all-structural
|
|
97
|
+
* grammar stays usable with either host (`cst/host-mode.ts`).
|
|
98
|
+
*
|
|
99
|
+
* It belongs in THIS module for the reason stated at the top of it: both lowerings
|
|
100
|
+
* must reach the same answer, and a stamp they disagree about is a driver that
|
|
101
|
+
* accepts a host it should refuse. It previously lived in `compiler/codegen.ts`,
|
|
102
|
+
* which forced `table/compile-rule-map.ts` to import the engine the table replaced.
|
|
103
|
+
*
|
|
104
|
+
* The descent mirrors the source lowering's own `childrenOf` exactly — including a
|
|
105
|
+
* `routed()` fallback and a `dispatch` matcher arm, both of which are real emit
|
|
106
|
+
* sites and neither of which `hasNodeDef` above walks.
|
|
107
|
+
*/
|
|
108
|
+
export declare function hasDirectBuildDef(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>): boolean;
|
|
109
|
+
/** True when `p` can report a committed failure through emitFallible's failure channel. */
|
|
110
|
+
export declare function mayCommitFailure(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* `hasDirectBuilders` / `isRecognitionOnly` for a rule map WITHOUT lowering it.
|
|
113
|
+
*
|
|
114
|
+
* `composeLeaf()` gates on both: every pre-final grammar must prove recognition-only,
|
|
115
|
+
* and the local leaf's direct builders decide whether the recognition pieces need
|
|
116
|
+
* terminal capture. Both were only ever available as fields on `LinkablePieces`, so
|
|
117
|
+
* the gate forced a full `compileLinkable()` of every piece purely to read two
|
|
118
|
+
* booleans off the result — which is why the table lowering appeared to be blocked on
|
|
119
|
+
* porting the source lowering wholesale.
|
|
120
|
+
*
|
|
121
|
+
* They are not lowering products. Both are predicates over the COMBINATOR GRAPH, and
|
|
122
|
+
* this computes them from the graph directly, with the SAME `externalRefs` rule the
|
|
123
|
+
* lowering applies (`:6008`): a named `lazy` whose thunk throws is a HOLE, bound by
|
|
124
|
+
* name at fuse time, and is therefore not evidence of unknown semantics. An UNNAMED
|
|
125
|
+
* unresolved `ref()` stays semantic — nobody can bind it, so it fails closed.
|
|
126
|
+
*/
|
|
127
|
+
export declare function classifyRuleMap(ruleMap: ReadonlyArray<readonly [string, Combinator<unknown>]>): {
|
|
128
|
+
hasDirectBuilders: boolean;
|
|
129
|
+
isRecognitionOnly: boolean;
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=commitment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commitment.d.ts","sourceRoot":"","sources":["../../src/analysis/commitment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AAIxD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAqCnG;AAkCD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAiC1G;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,EAAE,YAAY,UAAO,GAAG,OAAO,CAwGvI;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAkDxG;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CA6BtG;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAkC7G;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAqC5G;AAwCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAC7D;IAAE,iBAAiB,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,CAwB5D"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SECOND world.
|
|
3
|
+
*
|
|
4
|
+
* A type error has one source to point at. A grammar finding has two — the ordered
|
|
5
|
+
* choice whose arms cost the time, and the input that pays for it — and relating them is
|
|
6
|
+
* the whole diagnostic. `gating.ts` owns the first world and is entirely static. This
|
|
7
|
+
* module owns the second, and it is deliberately the smallest honest thing that can be
|
|
8
|
+
* said about a corpus without instrumenting a parse.
|
|
9
|
+
*
|
|
10
|
+
* WHAT IS MEASURED, EXACTLY
|
|
11
|
+
* -------------------------
|
|
12
|
+
* For a choice, every corpus POSITION whose character is in some arm's first set. That
|
|
13
|
+
* is a count of characters, not of times the choice was reached, and the difference
|
|
14
|
+
* matters: a choice nested three rules deep is reached far less often than its first
|
|
15
|
+
* characters occur. So the number is reported as what it is — an upper bound on entries,
|
|
16
|
+
* derived from the same first sets the compiler dispatches on — and never as "this
|
|
17
|
+
* choice ran N times". Naming it precisely is what keeps it useful; a number that
|
|
18
|
+
* overstates itself is worse than no number, because the reader stops trusting all of
|
|
19
|
+
* them.
|
|
20
|
+
*
|
|
21
|
+
* The one thing this DOES settle, exactly and without any modelling: an arm whose first
|
|
22
|
+
* set is ANY is entered at every one of those positions, because no first character can
|
|
23
|
+
* exclude it. That is the cost the fix removes, and it is arithmetic, not a guess.
|
|
24
|
+
*
|
|
25
|
+
* Determinism: counts and the located example are a pure function of (report, corpus).
|
|
26
|
+
* No timings, no paths beyond the caller's own sample names.
|
|
27
|
+
*/
|
|
28
|
+
import type { Combinator, FirstSet } from '../types.ts';
|
|
29
|
+
import type { ChoiceGating } from './gating.ts';
|
|
30
|
+
export type CorpusSample = {
|
|
31
|
+
name: string;
|
|
32
|
+
text: string;
|
|
33
|
+
};
|
|
34
|
+
/** A located input position: the caller's sample name plus 1-based line/column. */
|
|
35
|
+
export type CorpusSite = {
|
|
36
|
+
sample: string;
|
|
37
|
+
line: number;
|
|
38
|
+
column: number;
|
|
39
|
+
/** The source line, untrimmed, for a caret rendering. */
|
|
40
|
+
lineText: string;
|
|
41
|
+
};
|
|
42
|
+
export type ArmCorpusCost = {
|
|
43
|
+
index: number;
|
|
44
|
+
/** ANY first set — no character excludes this arm. */
|
|
45
|
+
any: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Corpus positions whose character this arm's first set accepts. For an `any` arm this
|
|
48
|
+
* equals the choice total, which is the point.
|
|
49
|
+
*/
|
|
50
|
+
positions: number;
|
|
51
|
+
/** The first such position, for the two-world rendering. Absent when there are none. */
|
|
52
|
+
firstSite?: CorpusSite;
|
|
53
|
+
};
|
|
54
|
+
export type ChoiceCorpusCost = {
|
|
55
|
+
choiceId: string;
|
|
56
|
+
/** Positions whose character SOME arm accepts — the choice's own reach, bounded. */
|
|
57
|
+
positions: number;
|
|
58
|
+
/** Every position in the corpus, so a share can be read. */
|
|
59
|
+
corpusPositions: number;
|
|
60
|
+
arms: ArmCorpusCost[];
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Measure one choice against a corpus. `choice.anyArms` already knows which arms are
|
|
64
|
+
* broad; this adds how much input that costs.
|
|
65
|
+
*/
|
|
66
|
+
export declare function measureChoiceCost(c: ChoiceGating, samples: readonly CorpusSample[], arms: readonly {
|
|
67
|
+
firstSet: FirstSet;
|
|
68
|
+
}[]): ChoiceCorpusCost;
|
|
69
|
+
/** The per-arm first sets a choice dispatches on, in arm order. */
|
|
70
|
+
export declare function armFirstSets(choiceArms: readonly Combinator<unknown>[]): {
|
|
71
|
+
firstSet: FirstSet;
|
|
72
|
+
}[];
|
|
73
|
+
//# sourceMappingURL=corpus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpus.d.ts","sourceRoot":"","sources":["../../src/analysis/corpus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzD,mFAAmF;AACnF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,GAAG,EAAE,OAAO,CAAA;IACZ;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB,wFAAwF;IACxF,SAAS,CAAC,EAAE,UAAU,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAA;IACjB,4DAA4D;IAC5D,eAAe,EAAE,MAAM,CAAA;IACvB,IAAI,EAAE,aAAa,EAAE,CAAA;CACtB,CAAA;AAyBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS;IAAE,QAAQ,EAAE,QAAQ,CAAA;CAAE,EAAE,GAAG,gBAAgB,CAiC9I;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,UAAU,EAAE,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAA;CAAE,EAAE,CAEjG"}
|