aboutsummaryrefslogtreecommitdiff
path: root/docs/dev/pages
diff options
context:
space:
mode:
Diffstat (limited to 'docs/dev/pages')
-rw-r--r--docs/dev/pages/abouts/ci.md72
-rw-r--r--docs/dev/pages/abouts/code-verify-system.md20
-rw-r--r--docs/dev/pages/issues/_modify-dispatcher-syntax.md2
-rw-r--r--docs/dev/pages/issues/_remove-pack-macros.md2
-rw-r--r--docs/dev/pages/issues/_remove-parser-feature.md2
-rw-r--r--docs/dev/pages/issues/_remove-with-dispatcher.md2
-rw-r--r--docs/dev/pages/issues/_t2_automated-dispatch-tree-optimization.md76
-rw-r--r--docs/dev/pages/issues/t2_automated-dispatch-tree-optimization.md57
8 files changed, 126 insertions, 107 deletions
diff --git a/docs/dev/pages/abouts/ci.md b/docs/dev/pages/abouts/ci.md
index f9a58be..37015eb 100644
--- a/docs/dev/pages/abouts/ci.md
+++ b/docs/dev/pages/abouts/ci.md
@@ -3,7 +3,7 @@
CI workflow and local execution guide for Mingling
</p>
-Mingling's CI process is built into the project itself: the execution logic lives in `mingling_ci/`, a separate crate **built on the Mingling framework** — it dogfoods the very library it validates. You can run it locally via the `cargo ci` command, which produces the same results as the `CI` workflow in GitHub Actions.
+Mingling's CI process is built into the project itself: the execution logic lives in `dev/ci/`, a separate crate **built on the Mingling framework** — it dogfoods the very library it validates. You can run it locally via the `cargo ci` command, which produces the same results as the `CI` workflow in GitHub Actions.
During development, you can run `cargo ci <command>` at any time to verify that your code hasn't introduced regressions.
@@ -13,7 +13,7 @@ An alias is defined in `.cargo/config.toml` at the project root:
```toml
[alias]
-ci = "run --manifest-path mingling_ci/Cargo.toml --bin ci --quiet --"
+ci = "run --manifest-path dev/ci/Cargo.toml --bin ci --quiet --"
```
Run a single step:
@@ -40,38 +40,38 @@ Every CI step is one subcommand. `cargo ci` with no subcommand prints the help p
### UTILS
-| Command | What it does |
-| --------------- | ----------------------------------------------------------------------- |
+| Command | What it does |
+| ---------------- | --------------------------------------------------------------------------------------- |
| `report-collect` | Assembles the collected logs in `.temp/reports/collect/` into `.temp/reports/result.md` |
-| `report-clean` | Deletes all collected logs and the generated report |
-| `git-lock` | Locks the workspace for a CI run (temporary commit, see below) |
-| `git-unlock` | Restores the workspace and checks idempotency (see below) |
-| `show-manifests` | Prints every crate path that CI will check |
-| `show-features` | Prints the `docs.rs` feature list of `mingling` |
+| `report-clean` | Deletes all collected logs and the generated report |
+| `git-lock` | Locks the workspace for a CI run (temporary commit, see below) |
+| `git-unlock` | Restores the workspace and checks idempotency (see below) |
+| `show-manifests` | Prints every crate path that CI will check |
+| `show-features` | Prints the `docs.rs` feature list of `mingling` |
### TOOLS (refresh)
-| Command | What it does |
-| ------------------- | --------------------------------------------------------------------------------- |
-| `example-refresh` | Regenerates `mingling/src/example_docs.rs` and `docs/example-pages/examples.json` |
-| `docsify-refresh` | Fixes docsify code-box blank lines and regenerates `_sidebar.md` files |
-| `features-refresh` | Regenerates `mingling/src/features.rs` from `mingling/Cargo.toml` |
+| Command | What it does |
+| ------------------ | ---------------------------------------------------------------------- |
+| `example-refresh` | Regenerates `mingling/src/example_docs.rs` and `docs/examples.json` |
+| `docsify-refresh` | Fixes docsify code-box blank lines and regenerates `_sidebar.md` files |
+| `features-refresh` | Regenerates `mingling/src/features.rs` from `mingling/Cargo.toml` |
These tools **write files**. Running them inside a `git-lock` / `git-unlock` pair turns them into an up-to-date check: if the generated files are stale, the tree becomes dirty and `git-unlock` fails.
### TASKS (checks)
-| Command | What it does |
-| ----------------------- | ------------------------------------------------------------------------------------------------------------------- |
-| `build-check` | Finds all `Cargo.toml` files (minus `.config/ci-ignored-dirs.txt`) and runs `cargo build` per crate in parallel. |
-| `clippy-check` | Runs `cargo clippy ... -- -D warnings` for every crate in parallel; any warning fails the check. |
-| `test-all` | Runs `cargo test` for every crate in parallel. Each base crate can override its command in its `mingling-ci.toml` (`[test].command`, with `<<<features>>>` expanded from the docs.rs feature list); `arg-picker` uses this to run `cargo test -p arg-picker`. |
-| `example-check` | Builds every example and runs the expected-output tests declared in `examples/<example>/test.toml`. |
-| `docs-check` | Builds the `mingling` API docs with the `[package.metadata.docs.rs]` features and `-D warnings`. |
-| `markdown-check <PATH>` | Verifies the rust code blocks of a single markdown file compile. See [ABOUT_CODE_VERIFY](docs/_ABOUT_CODE_VERIFY.md). |
-| `markdown-check-all` | Verifies all markdown files declared in `.config/verified-docs.toml`. |
-| `markdown-compare <A> <B>` | Compares the *structure* of two markdown files or directories. |
-| `markdown-compare-all` | Checks every translated docs directory mirrors the reference `./docs/pages/` (per `.config/docs-lang.txt`). |
+| Command | What it does |
+| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `build-check` | Finds all `Cargo.toml` files (minus `dev/configs/ci-ignored-dirs.txt`) and runs `cargo build` per crate in parallel. |
+| `clippy-check` | Runs `cargo clippy ... -- -D warnings` for every crate in parallel; any warning fails the check. |
+| `test-all` | Runs `cargo test` for every crate in parallel. Each base crate can override its command in its `mingling-ci.toml` (`[test].command`, with `<<<features>>>` expanded from the docs.rs feature list); `arg-picker` uses this to run `cargo test -p arg-picker`. |
+| `example-check` | Builds every example and runs the expected-output tests declared in `examples/<example>/test.toml`. |
+| `docs-check` | Builds the `mingling` API docs with the `[package.metadata.docs.rs]` features and `-D warnings`. |
+| `markdown-check <PATH>` | Verifies the rust code blocks of a single markdown file compile. See [ABOUT_CODE_VERIFY](docs/_ABOUT_CODE_VERIFY.md). |
+| `markdown-check-all` | Verifies all markdown files declared in `dev/configs/verified-docs.toml`. |
+| `markdown-compare <A> <B>` | Compares the _structure_ of two markdown files or directories. |
+| `markdown-compare-all` | Checks every translated docs directory mirrors the reference `./docs/pages/` (per `dev/configs/docs-lang.txt`). |
## Reports
@@ -122,7 +122,7 @@ cargo ci git-unlock --show-diff
This is what the CI workflow uses: an idempotency failure shows exactly what contaminated the workspace in the job logs.
-> **Warning**: when unlocking a `true` lock, changes made *during* CI are discarded. Anything you had before locking comes back.
+> **Warning**: when unlocking a `true` lock, changes made _during_ CI are discarded. Anything you had before locking comes back.
## GitHub Actions Workflow
@@ -131,16 +131,16 @@ This is what the CI workflow uses: an idempotency failure shows exactly what con
- Triggered on `push` to the `main` branch.
- A `Check` job runs in a **item × platform** matrix (`ubuntu-latest`, `windows-latest`, `macos-latest`), each combination being `cargo ci <command>` inside a `git-lock` / `git-unlock` pair:
-| Matrix item | Command |
-| -------------- | -------------------------------------------------------------- |
-| `build` | `cargo ci build-check` |
-| `clippy` | `cargo ci clippy-check` |
-| `test` | `cargo ci test-all` |
-| `arg-picker` | `cargo ci test-all` (covered via its `mingling-ci.toml` override) |
-| `markdown-code` | `cargo ci markdown-check-all && cargo ci markdown-compare-all` |
-| `examples` | `cargo ci example-check` |
-| `docs-refresh` | `cargo ci example-refresh` + `docsify-refresh` + `features-refresh` |
-| `api-docs` | `cargo ci docs-check` |
+| Matrix item | Command |
+| --------------- | ------------------------------------------------------------------- |
+| `build` | `cargo ci build-check` |
+| `clippy` | `cargo ci clippy-check` |
+| `test` | `cargo ci test-all` |
+| `arg-picker` | `cargo ci test-all` (covered via its `mingling-ci.toml` override) |
+| `markdown-code` | `cargo ci markdown-check-all && cargo ci markdown-compare-all` |
+| `examples` | `cargo ci example-check` |
+| `docs-refresh` | `cargo ci example-refresh` + `docsify-refresh` + `features-refresh` |
+| `api-docs` | `cargo ci docs-check` |
- Every matrix job uploads its `.temp/reports/collect/` as an artifact — **even on failure**, so failures are always collected.
- A `Report` job (runs even when some checks failed) downloads all collect artifacts, runs `cargo ci report-collect`, and publishes `result.md` to the job summary via `$GITHUB_STEP_SUMMARY`.
diff --git a/docs/dev/pages/abouts/code-verify-system.md b/docs/dev/pages/abouts/code-verify-system.md
index c2a9215..f52052f 100644
--- a/docs/dev/pages/abouts/code-verify-system.md
+++ b/docs/dev/pages/abouts/code-verify-system.md
@@ -7,7 +7,7 @@ This system automatically extracts and compiles Rust code blocks from docs, ensu
## Config
-Specify which Markdown files to verify via `.config/verified-docs.toml`:
+Specify which Markdown files to verify via `dev/configs/verified-docs.toml`:
```toml
[verified]
@@ -210,18 +210,18 @@ Use `@@@` for:
## Structure Overview
-| Module | Responsibility |
-| --------------------------------------------- | ----------------------------------------------------------------------------------- |
-| `mingling_ci/src/markdown/project.rs` | Block parsing, Cargo.toml/main.rs generation, FNV-1a dep hash |
-| `mingling_ci/src/markdown/test.rs` | Grouping by dep hash, parallel `cargo check` execution |
-| `mingling_ci/src/task/cmd_markdown_check.rs` | `markdown-check` / `markdown-check-all` commands: read config, collect files, report |
-| `mingling_ci/src/markdown/compare.rs` | Structural signature comparison (for `markdown-compare`) |
-| `mingling_ci/src/task/cmd_markdown_compare.rs`| `markdown-compare` / `markdown-compare-all` commands |
-| `.config/verified-docs.toml` | Specifies which doc files to verify |
+| Module | Responsibility |
+| ----------------------------------------- | ------------------------------------------------------------------------------------ |
+| `dev/ci/src/markdown/project.rs` | Block parsing, Cargo.toml/main.rs generation, FNV-1a dep hash |
+| `dev/ci/src/markdown/test.rs` | Grouping by dep hash, parallel `cargo check` execution |
+| `dev/ci/src/task/cmd_markdown_check.rs` | `markdown-check` / `markdown-check-all` commands: read config, collect files, report |
+| `dev/ci/src/markdown/compare.rs` | Structural signature comparison (for `markdown-compare`) |
+| `dev/ci/src/task/cmd_markdown_compare.rs` | `markdown-compare` / `markdown-compare-all` commands |
+| `dev/configs/verified-docs.toml` | Specifies which doc files to verify |
### Structure Comparison
-`markdown-compare` (two files or directories) and `markdown-compare-all` (all languages from `.config/docs-lang.txt`, whose first line is the reference directory) check that every translated docs directory **mirrors the structure** of the reference docs exactly: one token per line classifying headings, fenced code blocks (with language tag), `@@@` lines, blank lines, blockquotes, lists and plain text. Translated text may differ; the structure may not.
+`markdown-compare` (two files or directories) and `markdown-compare-all` (all languages from `dev/configs/docs-lang.txt`, whose first line is the reference directory) check that every translated docs directory **mirrors the structure** of the reference docs exactly: one token per line classifying headings, fenced code blocks (with language tag), `@@@` lines, blank lines, blockquotes, lists and plain text. Translated text may differ; the structure may not.
## Full Example
diff --git a/docs/dev/pages/issues/_modify-dispatcher-syntax.md b/docs/dev/pages/issues/_modify-dispatcher-syntax.md
index ed409ef..cfee64b 100644
--- a/docs/dev/pages/issues/_modify-dispatcher-syntax.md
+++ b/docs/dev/pages/issues/_modify-dispatcher-syntax.md
@@ -1,4 +1,4 @@
-<h1 align="center">[T1] Modify the dispatcher! Syntax</h1>
+<h1 align="center">[Solved] [T1] Modify the dispatcher! Syntax</h1>
<p align="center">
Breaking: drop the <code>CMD*</code> struct from the explicit form of <code>dispatcher!</code>
</p>
diff --git a/docs/dev/pages/issues/_remove-pack-macros.md b/docs/dev/pages/issues/_remove-pack-macros.md
index 74c21aa..153004e 100644
--- a/docs/dev/pages/issues/_remove-pack-macros.md
+++ b/docs/dev/pages/issues/_remove-pack-macros.md
@@ -1,4 +1,4 @@
-`<h1 align="center">[T0] Remove the pack! Family of Macros</h1>
+`<h1 align="center">[Solved] [T0] Remove the pack! Family of Macros</h1>
<p align="center">
Breaking: retire the entire <code>pack!</code> family in favor of the <code>Grouped</code> derive
</p>
diff --git a/docs/dev/pages/issues/_remove-parser-feature.md b/docs/dev/pages/issues/_remove-parser-feature.md
index c2a11c0..7653c47 100644
--- a/docs/dev/pages/issues/_remove-parser-feature.md
+++ b/docs/dev/pages/issues/_remove-parser-feature.md
@@ -1,4 +1,4 @@
-<h1 align="center">[T0] Remove the parser Feature</h1>
+<h1 align="center">[Solved] [T0] Remove the parser Feature</h1>
<p align="center">
Breaking: retire the legacy argument parsing in favor of <code>picker</code>
</p>
diff --git a/docs/dev/pages/issues/_remove-with-dispatcher.md b/docs/dev/pages/issues/_remove-with-dispatcher.md
index b0d972f..42b12e5 100644
--- a/docs/dev/pages/issues/_remove-with-dispatcher.md
+++ b/docs/dev/pages/issues/_remove-with-dispatcher.md
@@ -1,4 +1,4 @@
-<h1 align="center">[T0] Remove with_dispatcher and with_dispatchers</h1>
+<h1 align="center">[Solved] [T0] Remove with_dispatcher and with_dispatchers</h1>
<p align="center">
Breaking: make <code>Dispatcher</code> registration compile-time collected in all modes
</p>
diff --git a/docs/dev/pages/issues/_t2_automated-dispatch-tree-optimization.md b/docs/dev/pages/issues/_t2_automated-dispatch-tree-optimization.md
new file mode 100644
index 0000000..d2e2473
--- /dev/null
+++ b/docs/dev/pages/issues/_t2_automated-dispatch-tree-optimization.md
@@ -0,0 +1,76 @@
+<h1 align="center">[Solved] [T2] Automated dispatcher_tree Optimization Decisions</h1>
+<p align="center">
+ Feature: let Mingling decide when <code>dispatch_tree</code> pays off (implemented)
+</p>
+
+> [!NOTE]
+>
+> This item is **implemented**. It depends on [Remove with_dispatcher and with_dispatchers](t0_remove-with-dispatcher).
+
+## Background
+
+`dispatch_tree` provides a faster dispatch path, but it is not always a win. Currently users must manually enable the `dispatch_tree` feature and make the trade-off themselves.
+
+After dispatcher registration becomes compile-time collected (see [Remove with_dispatcher and with_dispatchers](t0_remove-with-dispatcher)), Mingling can know the full set and depth of registered commands at compile time — making automated decisions implementable.
+
+## Plan
+
+Mingling can automatically decide whether to use `dispatcher_tree` to optimize dispatch efficiency based on the current number and depth of registered commands, so users no longer need to manually enable the `dispatch_tree` feature.
+
+### Conditions
+
+`dispatch_tree` has an advantage in cases where command depth is too high and the number of commands is too large. However, if the number of commands is too small, the increased CPU prediction failure rate will inevitably make it less efficient than linear lookup; specifics need to be tuned during implementation.
+
+### Resolve the `pathf` + `dispatch_tree` build-dependency issue
+
+Additionally, the issue where `pathf` + `dispatch_tree` must be explicitly specified in `[build-dependencies]` will be resolved:
+
+```toml
+# Before
+[build-dependencies.mingling]
+version = "0.4.0"
+features = [ "build", "pathf", "dispatch_tree" ] # `dispatch_tree` must be explicitly specified for `pathf` to recognize it
+
+# After
+[build-dependencies.mingling]
+version = "0.4.0"
+features = [ "build", "pathf" ] # No `dispatch_tree` feature; `pathf` no longer needs to consider its branches
+```
+
+## Final Implementation
+
+The automated dispatch-strategy selection is now in place. A new `dispatch_auto` module (the default when no dispatch feature is enabled) picks at macro-expansion time from three strategies — **linear list**, **char trie**, and **perfect hash** — based on a cost model calibrated against the `dev/bench/dispatch` benchmark matrix.
+
+### Two new dispatch features
+
+In addition to the existing `dispatch_tree`, two new mutually-exclusive features now exist:
+
+- **`dispatch_linear`** — force linear longest-prefix list (the former default).
+- **`dispatch_phf`** — force a CHD minimal perfect hash (constant-time lookup, O(1) code size).
+- **`dispatch_tree`** — force the char-level trie.
+- **(none)** — **auto mode**: pick the best strategy from the command table.
+
+Enabling more than one triggers a `compile_error!`.
+
+### Auto-selection heuristic
+
+`dispatch_auto::select_strategy` inspects the normalized command table (names, depth, nesting) and picks:
+
+- **deep nested chains at modest sizes** (`max_words ≥ 8`, `n ≤ 128`) → linear list (short memcmps beat the trie's per-level char walk plus fallback calls);
+- **single-word tables with long names** (avg_len ≥ 16–24) → perfect hash (one hash beats the char walk);
+- **small tables** (`n ≤ 64`) → linear vs trie by an internal cost model;
+- **everything else** → char trie (O(depth) hits, linear code size after the fallback-chain refactor).
+
+The heuristic is empirical and may drift as the benchmark matrix grows.
+
+### Benchmark harness
+
+A workspace-internal harness `dev/bench/dispatch` (`cargo dispatch-bench`) measures all four strategies across a `len×count×type` matrix (4/8/16/32 × 128/256 × single/multi/nested4/nested10), reporting per-cell ns/op for hits and misses, geometric means, and how often auto matches the per-cell best / stays within 5%.
+
+### Trie code-size fix
+
+The trie generator was rewritten so the longest-prefix fallback is a single shared `__trie_fallback` method (called, not inlined, per arm) rather than inlined into every arm. This keeps generated code linear in the table size — a 1024×16 nested table previously emitted ~13 MB of tokens.
+
+<p align="center" style="font-size: 0.85em; color: gray;">
+ Written by @Weicao-CatilGrass
+</p>
diff --git a/docs/dev/pages/issues/t2_automated-dispatch-tree-optimization.md b/docs/dev/pages/issues/t2_automated-dispatch-tree-optimization.md
deleted file mode 100644
index 691fd1a..0000000
--- a/docs/dev/pages/issues/t2_automated-dispatch-tree-optimization.md
+++ /dev/null
@@ -1,57 +0,0 @@
-<h1 align="center">[T2] Automated dispatcher_tree Optimization Decisions</h1>
-<p align="center">
- Feature: let Mingling decide when <code>dispatch_tree</code> pays off (under consideration)
-</p>
-
-> [!NOTE]
->
-> This item is **under consideration**. It depends on [Remove with_dispatcher and with_dispatchers](t0_remove-with-dispatcher).
-
-## Background
-
-`dispatch_tree` provides a faster dispatch path, but it is not always a win. Currently users must manually enable the `dispatch_tree` feature and make the trade-off themselves.
-
-After dispatcher registration becomes compile-time collected (see [Remove with_dispatcher and with_dispatchers](t0_remove-with-dispatcher)), Mingling can know the full set and depth of registered commands at compile time — making automated decisions implementable.
-
-## Plan
-
-Mingling can automatically decide whether to use `dispatcher_tree` to optimize dispatch efficiency based on the current number and depth of registered commands, so users no longer need to manually enable the `dispatch_tree` feature.
-
-### Conditions
-
-`dispatch_tree` has an advantage in cases where command depth is too high and the number of commands is too large. However, if the number of commands is too small, the increased CPU prediction failure rate will inevitably make it less efficient than linear lookup; specifics need to be tuned during implementation.
-
-### Resolve the `pathf` + `dispatch_tree` build-dependency issue
-
-Additionally, the issue where `pathf` + `dispatch_tree` must be explicitly specified in `[build-dependencies]` will be resolved:
-
-```toml
-# Before
-[build-dependencies.mingling]
-version = "0.4.0"
-features = [ "build", "pathf", "dispatch_tree" ] # `dispatch_tree` must be explicitly specified for `pathf` to recognize it
-
-# After
-[build-dependencies.mingling]
-version = "0.4.0"
-features = [ "build", "pathf" ] # No `dispatch_tree` feature; `pathf` no longer needs to consider its branches
-```
-
-## Tasks
-
-- [ ] Collect statistics about registered commands (count, depth) at compile time
-- [ ] Benchmark / tune the threshold between linear lookup and `dispatch_tree`
-- [ ] Implement the automatic decision and wire it into dispatch code generation
-- [ ] Remove the manual `dispatch_tree` feature toggle (or keep it as an override?)
-- [ ] Refactor `pathf` so it no longer branches on `dispatch_tree`
-- [ ] Update examples, tests, and docs
-
-## 🕘 Progress
-
-- [ ] Under Consideration
-- [ ] In Progress
-- [ ] Complete
-
-<p align="center" style="font-size: 0.85em; color: gray;">
- Written by @Weicao-CatilGrass
-</p>