diff options
Diffstat (limited to 'CHANGELOG.md')
| -rw-r--r-- | CHANGELOG.md | 110 |
1 files changed, 109 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index ea4b737..766090a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,7 +58,26 @@ None #### Optimizations: -None +1. **[`macros`]** Updated `route!` macro to use `Routable` trait instead of `Grouped` trait for error conversion, making the semantics clearer. The `route!` macro now calls `::mingling::Routable::to_chain(e)` on the error branch instead of `::mingling::Grouped::to_chain(e)`. + + Additionally, `ChainProcess<ThisProgram>` now implements `Routable<ThisProgram>`, allowing `route!` to work with `Result<Ok, ChainProcess<ThisProgram>>` patterns — where the error side is already a `ChainProcess` value that should be routed directly: + + When `ChainProcess` implements `Routable`, `to_chain()` re-routes the inner `AnyOutput` to the chain pipeline (preserving the existing `NextProcess::Chain`/`Renderer` flag), while `to_render()` re-routes it to the render pipeline. This enables seamless propagation of already-routed chain process values through the `route!` macro without double-wrapping. + + The `Routable` trait is defined in `mingling_core::asset::routable` and provides unified routing capabilities (`to_chain` / `to_render`) for any type that can be dispatched into the program's pipeline. A blanket implementation is provided for all `T: Grouped<C> + Send`, ensuring backward compatibility — existing types that implement `Grouped` automatically implement `Routable`. + +2. **[`macros`]** Restructured the `mingling_macros` crate's internal module hierarchy. The previously flat module structure has been reorganized into a logical directory-based layout: + + - **`attr/`** — Attribute macro implementations (e.g., `#[chain]`, `#[renderer]`, `#[help]`, `#[completion]`, `#[dispatcher_clap]`, `#[program_setup]`) + - **`derive/`** — Derive macro implementations (e.g., `#[derive(Grouped)]`, `#[derive(EnumTag)]`) + - **`func/`** — Function-like macro implementations (e.g., `pack!`, `group!`, `dispatcher!`, `suggest!`, `entry!`, `node!`, `gen_program!` and its sub-macros) + - **`systems/`** — Cross-cutting systems (e.g., resource injection, dispatch tree generation, structural data derive support) + - **`extensions/`** — Extension point mechanism for attribute macros (unchanged) + - **`utils.rs`** — Shared utility module for future common helpers + + All public API items (`#[proc_macro]`, `#[proc_macro_derive]`, `#[proc_macro_attribute]`) remain at the crate root (`lib.rs`) with identical signatures. Internal function visibility has been tightened from `pub fn` to `pub(crate) fn` for all module-internal functions that were previously publicly accessible only within the crate. + + _No migration is required for downstream code — all macros are re-exported with the same names and signatures as before._ #### Features: @@ -184,6 +203,65 @@ None These methods complement the existing read-only `get_args(&self)` method, providing full control over argument mutation and ownership. +9. **[`macros:chain`]** Relaxed the `#[chain]` return type validation. Previously, `#[chain]` functions were restricted to returning `Next`, `ChainProcess<ThisProgram>`, `()`, or omitting the return type. Now, any return type is accepted, and the generated `proc` function performs an explicit `Into<ChainProcess<ThisProgram>>` conversion using a fully-qualified turbofish based on the user-declared return type. + + This means `#[chain]` functions can now return any pack type directly, without needing an explicit `.into()` call in the function body: + + ```rust + // Before — required explicit .into() + #[chain] + fn handle_greet(args: EntryGreet) -> Next { + let name = /* ... */; + ResultGreeting::new(name).into() + } + + // After — return any pack type directly + #[chain] + fn handle_greet(args: EntryGreet) -> ResultGreeting { + let name = /* ... */; + ResultGreeting::new(name) + } + ``` + + The generated `proc` function now wraps the body result in `<UserReturnType as Into<ChainProcess<ThisProgram>>>::into(...)`, which: + - Works for `Next` / `ChainProcess` via the identity `From<T> for T` implementation. + - Works for any pack type (`ResultGreeting`, etc.) via the `.into()` conversion generated by `pack!` / `#[derive(Grouped)]`. + - Works for `()` via the `From<()>` implementation on `ChainProcess`. + + The return type validation has been removed entirely — any valid Rust return type is accepted. If the type does not implement `Into<ChainProcess<ThisProgram>>`, a standard Rust compilation error will be produced at the call site. + +10. **[`macros`]** **[`extensions`]** Added the `extensions` module to `mingling_macros`, providing an extension point mechanism for attribute macros (`#[chain]`, `#[renderer]`, `#[help]`, `#[completion]`). The extension system allows identifiers in the attribute argument to be extracted and processed before the main macro logic runs. + + Each attribute macro now attempts to redispatch through `extensions::try_redispatch_simple()` (or `try_redispatch_completion` for `#[completion]`) before executing its standard logic. If extension identifiers are detected, the call is re-routed so that extensions are applied via additional `#[...]` attributes stacked on top of the inner core attribute. New extensions can be added without modifying the attribute macros themselves — only the `extensions` module needs to be updated to register new identifiers. + + This system is designed for future extensibility: as new cross-cutting concerns (e.g., logging, metrics, validation) are identified, they can be added as simple extension identifiers without touching the core macro logic. + +11. **[`extensions`]** **[`macros`]** Added the `#[routeify]` extension attribute macro that transforms `expr?` into `route!(expr)`, enabling concise error routing in chain functions using the `?` operator syntax. + + The `#[routeify]` macro can be used: + - **Standalone** — as a direct attribute: `#[routeify] fn handle(...) { ... }` + - **As an extension** — via the extension point system: `#[chain(routeify)] fn handle(...) { ... }` + + When used as a `#[chain]` extension, the `routeify` identifier is detected by the extension point mechanism, stripped from the `#[chain]` attribute arguments, and `#[routeify]` is applied as an outer attribute on top of `#[chain]`. The re-dispatch token stream now correctly generates `#[#exts]*` (i.e., `#[routeify] #[chain]`) instead of the previous bare `#exts` — fixing a bug where extension identifiers were emitted without the `#[...]` attribute delimiter, producing invalid token streams. + + ```rust + use mingling::macros::routeify; + + #[chain(routeify)] + fn handle_calc(args: EntryCalculate) -> Next { + let a = args.pick(&arg![f32]).to_result()?; + let op = args.pick(&arg![Operator]).to_result()?; + StateCalculate { number_a: a, operator: op, ... }.to_chain() + } + ``` + + The `#[routeify]` macro is feature-gated behind `extra_macros` and re-exported as `mingling::macros::routeify`. + + Internal changes: + - Added `mingling_macros/src/extensions/routeify.rs` with `routeify_impl` implementation. + - Updated `try_redispatch_simple` and `try_redispatch_completion` to emit `#[#exts]` instead of bare `#exts`, ensuring proper attribute syntax in the re-dispatched token stream. + - Registered `#[proc_macro_attribute] pub fn routeify` in `mingling_macros/src/lib.rs`. + #### **BREAKING CHANGES** (API CHANGES): 1. **[`macros:renderer`]** **[`macros:help`]** Removed `r_println!` and `r_print!` macros. The `#[renderer]` and `#[help]` macros no longer implicitly inject an internal `RenderResult` variable or provide `r_println!` / `r_print!` macros. @@ -236,6 +314,36 @@ None 3. **[`core`]** **[`ExitCodeSetup`]** Updated `ExitCodeSetup` to only override the exit code when `ResExitCode` has been modified (i.e., `exit_code != 0`). Previously, it unconditionally overrode the exit code, which could interfere with exit codes set by other hooks or the program's default exit flow. The `on_finish` hook now returns `ProgramControlUnit::OverrideExitCode(...)` only when the exit code is non-zero, and `ProgramControls::Empty` otherwise. The import of `ProgramControls` has been added accordingly. +4. **[`core`]** **[`macros`]** Renamed `Groupped` (typo) to `Grouped`. All references to the trait, derive macro, module files, and related types have been corrected throughout the codebase: + + - Trait: `Groupped<Group>` → `Grouped<Group>` + - Derive macro: `#[derive(Groupped)]` → `#[derive(Grouped)]` + - Serialize variant: `GrouppedSerialize` → `GroupedSerialize` + - Source files: `groupped.rs` → `grouped.rs` + - Pattern matcher: `GrouppedDerivePattern` → `GroupedDerivePattern` + - All `use` imports, type annotations, and trait bound references updated accordingly. + + This is a pure rename — no behavioral changes. All functionality remains identical. Downstream code using the old `Groupped` name must migrate to `Grouped`. + +5. **[`core`]** **[`macros`]** Removed `to_chain()` and `to_render()` default methods from the `Grouped` trait. These methods are now exclusively provided by the `Routable` trait. All code that previously called `to_chain()` or `to_render()` via `Grouped` must now call them via `Routable`: + + ```rust + // Before (via Grouped — removed) + use mingling::Grouped; + my_value.to_chain(); + + // After (via Routable) + use mingling::Routable; + my_value.to_chain(); + ``` + + - The `Routable` trait is re-exported in `mingling::prelude` alongside `Grouped`. + - The blanket implementation `impl<T: Grouped<C> + Send> Routable<C> for T` remains, so all types that implement `Grouped` still have `to_chain()` and `to_render()` — they just need to import `Routable` instead of relying on `Grouped` for those methods. + - Internal macro-generated code (in `#[chain]`, `#[renderer]`, `#[dispatcher_clap]`, `gen_program!`, `empty_result!`, etc.) has been updated to reference `::mingling::Routable::<C>::to_chain(...)` / `::mingling::Routable::<C>::to_render(...)` instead of `::mingling::Grouped::<C>::to_chain(...)` / `::mingling::Grouped::<C>::to_render(...)`. + - Downstream crates using `mingling` macros are automatically migrated — the macro output now references `Routable`. Only manual `.to_chain()` / `.to_render()` calls in user code need updating (add `use mingling::Routable;`). + + _No behavioral changes — this is a pure API migration from `Grouped` to `Routable` for routing methods._ + --- ## Release 0.2.2 (2026-07-10) |
