Skip to main content

fp_macros/
lib.rs

1#![warn(missing_docs)]
2#![allow(clippy::tabs_in_doc_comments)]
3
4//! Procedural macros for the [`fp-library`](https://docs.rs/fp-library/latest/fp_library/) crate.
5//!
6//! This crate provides macros for generating and working with Higher-Kinded Type (HKT) traits.
7
8pub(crate) mod a_do; // Applicative do-notation
9pub(crate) mod analysis; // Type and trait analysis
10pub(crate) mod codegen; // Code generation (includes re-exports)
11pub(crate) mod core; // Core infrastructure (config, error, result)
12pub(crate) mod documentation; // Documentation generation macros
13pub(crate) mod hkt; // Higher-Kinded Type macros
14pub(crate) mod hm; // Hindley-Milner type conversion
15pub(crate) mod m_do; // Monadic do-notation
16pub(crate) mod resolution; // Type resolution
17pub(crate) mod support; // Support utilities (attributes, syntax, validation, errors)
18
19#[cfg(test)]
20#[expect(
21	clippy::unwrap_used,
22	clippy::indexing_slicing,
23	reason = "Tests use panicking operations for brevity and clarity"
24)]
25mod property_tests;
26
27use {
28	crate::core::ToCompileError,
29	a_do::a_do_worker,
30	codegen::{
31		FunctionFormatter,
32		ReExportInput,
33		TraitFormatter,
34		generate_re_exports_worker,
35	},
36	documentation::{
37		document_examples_worker,
38		document_module_worker,
39		document_parameters_worker,
40		document_returns_worker,
41		document_signature_worker,
42		document_type_parameters_worker,
43	},
44	hkt::{
45		ApplyInput,
46		AssociatedTypes,
47		ImplKindInput,
48		apply_worker,
49		generate_inferable_brand_name,
50		generate_name,
51		impl_kind_worker,
52		kind_attr_worker,
53		resolve_inferable_brand,
54		trait_kind_worker,
55	},
56	m_do::{
57		DoInput,
58		m_do_worker,
59	},
60	proc_macro::TokenStream,
61	quote::quote,
62	syn::parse_macro_input,
63};
64
65/// Generates the name of a `Kind` trait based on its signature.
66///
67/// This macro takes a list of associated type definitions, similar to a trait definition.
68///
69/// ### Syntax
70///
71/// ```ignore
72/// Kind!(
73///     type AssocName<Params>: Bounds;
74///     // ...
75/// )
76/// ```
77///
78/// * `Associated Types`: A list of associated type definitions (e.g., `type Of<T>;`) that define the signature of the Kind.
79///
80/// ### Generates
81///
82/// The name of the generated `Kind` trait (e.g., `Kind_0123456789abcdef`).
83/// The name is deterministic and based on a hash of the signature.
84///
85/// ### Examples
86///
87/// ```ignore
88/// // Invocation
89/// let name = Kind!(type Of<T>;);
90///
91/// // Expanded code
92/// let name = Kind_...; // e.g., Kind_a1b2c3d4e5f67890
93/// ```
94///
95/// ```ignore
96/// // Invocation
97/// let name = Kind!(type Of<'a, T: Display>: Debug;);
98///
99/// // Expanded code
100/// let name = Kind_...; // Unique hash based on signature
101/// ```
102///
103/// ```ignore
104/// // Invocation
105/// let name = Kind!(
106///     type Of<T>;
107///     type SendOf<T>: Send;
108/// );
109///
110/// // Expanded code
111/// let name = Kind_...; // Unique hash based on signature
112/// ```
113///
114/// ### Limitations
115///
116/// Due to Rust syntax restrictions, this macro cannot be used directly in positions where a
117/// concrete path is expected by the parser, such as:
118/// * Supertrait bounds: `trait MyTrait: Kind!(...) {}` (Invalid)
119/// * Type aliases: `type MyKind = Kind!(...);` (Invalid)
120/// * Trait aliases: `trait MyKind = Kind!(...);` (Invalid)
121///
122/// For supertrait bounds, use the [`kind`] attribute macro instead:
123/// ```ignore
124/// #[kind(type Of<'a, A: 'a>: 'a;)]
125/// pub trait Functor { ... }
126/// ```
127///
128/// For other positions, you must use the generated name directly (e.g., `Kind_...`).
129#[proc_macro]
130#[expect(non_snake_case, reason = "Matches the PascalCase type-level concept it represents")]
131pub fn Kind(input: TokenStream) -> TokenStream {
132	let input = parse_macro_input!(input as AssociatedTypes);
133	let name = match generate_name(&input) {
134		Ok(name) => name,
135		Err(e) => return e.to_compile_error().into(),
136	};
137	quote!(#name).into()
138}
139
140/// Generates the name of an `InferableBrand` trait based on its signature.
141///
142/// This macro is analogous to [`Kind!`] but produces `InferableBrand_{hash}`
143/// identifiers instead of `Kind_{hash}`. Both macros use the same content
144/// hash, so a `Kind` trait and its corresponding `InferableBrand` trait
145/// always share the same hash suffix.
146///
147/// ### Syntax
148///
149/// ```ignore
150/// InferableBrand!(
151///     type AssocName<Params>: Bounds;
152///     // ...
153/// )
154/// ```
155///
156/// * `Associated Types`: A list of associated type definitions (e.g., `type Of<T>;`) that define the signature of the InferableBrand.
157///
158/// ### Generates
159///
160/// The name of the generated `InferableBrand` trait (e.g., `InferableBrand_0123456789abcdef`).
161/// The name is deterministic and based on the same hash as the corresponding `Kind` trait.
162///
163/// ### Examples
164///
165/// ```ignore
166/// // Invocation
167/// let name = InferableBrand!(type Of<'a, A: 'a>: 'a;);
168///
169/// // Expanded code
170/// let name = InferableBrand_...; // e.g., InferableBrand_cdc7cd43dac7585f
171/// ```
172///
173/// ```ignore
174/// // Inside Apply! (the primary use case)
175/// Apply!(<<FA as InferableBrand!(type Of<'a, A: 'a>: 'a;)>::Brand as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
176/// ```
177///
178/// ### Limitations
179///
180/// Due to Rust syntax restrictions, this macro cannot be used directly in positions where a
181/// concrete path is expected by the parser, such as:
182/// * Trait bounds: `FA: InferableBrand!(...) {}` (Invalid)
183/// * Qualified paths: `<FA as InferableBrand!(...)>::Brand` (Invalid)
184///
185/// In these positions, use the generated name directly (e.g., `InferableBrand_cdc7cd43dac7585f`).
186/// Inside `Apply!()`, the macro is supported and resolved automatically via preprocessing.
187#[proc_macro]
188#[expect(non_snake_case, reason = "Matches the PascalCase type-level concept it represents")]
189pub fn InferableBrand(input: TokenStream) -> TokenStream {
190	let input = parse_macro_input!(input as AssociatedTypes);
191	let name = match generate_inferable_brand_name(&input) {
192		Ok(name) => name,
193		Err(e) => return e.to_compile_error().into(),
194	};
195	quote!(#name).into()
196}
197
198/// Defines a new `Kind` trait.
199///
200/// This macro generates a trait definition for a Higher-Kinded Type signature.
201///
202/// ### Syntax
203///
204/// ```ignore
205/// trait_kind!(
206///     type AssocName<Params>: Bounds;
207///     // ...
208/// )
209/// ```
210///
211/// * `Associated Types`: A list of associated type definitions (e.g., `type Of<T>;`) that define the signature of the Kind.
212///
213/// ### Generates
214///
215/// Two public trait definitions with unique names derived from the signature:
216///
217/// 1. `Kind_{hash}`: The HKT trait with the specified associated types.
218/// 2. `InferableBrand_{hash}`: A reverse-mapping trait for brand inference,
219///    with a blanket `impl for &T`. Both share the same content hash.
220///
221/// ### Examples
222///
223/// ```ignore
224/// // Invocation
225/// trait_kind!(type Of<T>;);
226///
227/// // Expanded code
228/// pub trait Kind_a1b2... {
229///     type Of<T>;
230/// }
231/// pub trait InferableBrand_a1b2... {
232///     type Brand: Kind_a1b2...;
233/// }
234/// impl<T: InferableBrand_a1b2... + ?Sized> InferableBrand_a1b2... for &T {
235///     type Brand = T::Brand;
236/// }
237/// ```
238///
239/// ```ignore
240/// // Invocation
241/// trait_kind!(type Of<'a, T: Display>: Debug;);
242///
243/// // Expanded code (same pattern: Kind trait + InferableBrand trait + blanket ref impl)
244/// pub trait Kind_cdef... {
245///     type Of<'a, T: Display>: Debug;
246/// }
247/// pub trait InferableBrand_cdef... {
248///     type Brand: Kind_cdef...;
249/// }
250/// impl<T: InferableBrand_cdef... + ?Sized> InferableBrand_cdef... for &T { ... }
251/// ```
252#[proc_macro]
253pub fn trait_kind(input: TokenStream) -> TokenStream {
254	let input = parse_macro_input!(input as AssociatedTypes);
255	match trait_kind_worker(input) {
256		Ok(tokens) => tokens.into(),
257		Err(e) => e.to_compile_error().into(),
258	}
259}
260
261/// Implements a `Kind` trait for a brand.
262///
263/// This macro simplifies the implementation of a generated `Kind` trait for a specific
264/// brand type. It infers the correct `Kind` trait to implement based on the signature
265/// of the associated types provided in the block.
266///
267/// The signature (names, parameters, and bounds) of the associated types must match
268/// the definition used in [`trait_kind!`] or [`Kind!`] to ensure the correct trait is implemented.
269///
270/// ### Syntax
271///
272/// ```ignore
273/// impl_kind! {
274///     // Optional impl generics
275///     impl<Generics> for BrandType
276///     // Optional where clause
277///     where Bounds
278///     {
279///         type AssocName<Params> = ConcreteType;
280///         // ... more associated types
281///     }
282/// }
283/// ```
284///
285/// * `Generics`: Optional generic parameters for the implementation.
286/// * `BrandType`: The brand type to implement the Kind for.
287/// * `Bounds`: Optional where clause bounds.
288/// * `Associated Types`: The associated type assignments (e.g., `type Of<A> = Option<A>;`).
289///
290/// ### Generates
291///
292/// 1. An implementation of the appropriate `Kind_{hash}` trait for the brand.
293/// 2. An `InferableBrand_{hash}` impl for the target type, mapping it back to
294///    the brand. This enables brand inference for free functions like `map`,
295///    `bind`, etc.
296///
297/// The `InferableBrand` impl is suppressed when:
298/// - `#[no_inferable_brand]` is present (for types with multiple brands).
299/// - The target type is a projection (contains `Apply!` or `::`).
300/// - Multiple associated types are defined.
301///
302/// ### Attributes
303///
304/// Inside the `impl_kind!` block, you can use these attributes:
305///
306/// * `#[no_inferable_brand]`: Suppresses `InferableBrand` impl generation. Use this for
307///   types reachable through multiple brands (e.g., `Result` at arity 1).
308/// * `#[document_default]`: Marks this associated type as the default for resolving bare `Self` in
309///   the generated documentation for this brand within the module.
310///
311/// ### Examples
312///
313/// ```ignore
314/// // Invocation
315/// impl_kind! {
316///     for OptionBrand {
317///         #[document_default]
318///         type Of<A> = Option<A>;
319///     }
320/// }
321///
322/// // Expanded code (Kind impl + InferableBrand impl)
323/// impl Kind_a1b2... for OptionBrand {
324///     type Of<A> = Option<A>;
325/// }
326/// impl<A> InferableBrand_a1b2... for Option<A> {
327///     type Brand = OptionBrand;
328/// }
329/// ```
330///
331/// ```ignore
332/// // Invocation with impl generics
333/// impl_kind! {
334///     impl<E> for ResultBrand<E> {
335///         type Of<A> = Result<A, E>;
336///     }
337/// }
338///
339/// // Expanded code
340/// impl<E> Kind_... for ResultBrand<E> {
341///     type Of<A> = Result<A, E>;
342/// }
343/// impl<A, E> InferableBrand_... for Result<A, E> {
344///     type Brand = ResultBrand<E>;
345/// }
346/// ```
347///
348/// ```ignore
349/// // Suppressing InferableBrand generation for multi-brand types
350/// impl_kind! {
351///     #[no_inferable_brand]
352///     impl<E> for ResultErrAppliedBrand<E> {
353///         type Of<'a, A: 'a>: 'a = Result<A, E>;
354///     }
355/// }
356///
357/// // Expanded code (only Kind impl, no InferableBrand)
358/// impl<E> Kind_... for ResultErrAppliedBrand<E> {
359///     type Of<'a, A: 'a>: 'a = Result<A, E>;
360/// }
361/// ```
362///
363/// ```ignore
364/// // Multiple associated types: InferableBrand skipped automatically
365/// impl_kind! {
366///     impl<E> for MyBrand<E> where E: Clone {
367///         type Of<A> = MyType<A, E>;
368///         type SendOf<A> = MySendType<A, E>;
369///     }
370/// }
371///
372/// // Expanded code (only Kind impl)
373/// impl<E> Kind_... for MyBrand<E> where E: Clone {
374///     type Of<A> = MyType<A, E>;
375///     type SendOf<A> = MySendType<A, E>;
376/// }
377/// ```
378#[proc_macro]
379pub fn impl_kind(input: TokenStream) -> TokenStream {
380	let input = parse_macro_input!(input as ImplKindInput);
381	match impl_kind_worker(input) {
382		Ok(tokens) => tokens.into(),
383		Err(e) => e.to_compile_error().into(),
384	}
385}
386
387/// Applies a brand to type arguments.
388///
389/// This macro projects a brand type to its concrete type using the appropriate
390/// `Kind` trait. It uses a syntax that mimics a fully qualified path, where the
391/// `Kind` trait is specified by its signature.
392///
393/// `InferableBrand!(SIG)` invocations within the brand position are resolved
394/// automatically via preprocessing, enabling readable signatures like:
395/// `Apply!(<<FA as InferableBrand!(type Of<'a, A: 'a>: 'a;)>::Brand as Kind!(...)>::Of<'a, B>)`
396///
397/// ### Syntax
398///
399/// ```ignore
400/// Apply!(<Brand as Kind!( KindSignature )>::AssocType<Args>)
401/// ```
402///
403/// * `Brand`: The brand type (e.g., `OptionBrand`). May contain `InferableBrand!(SIG)` invocations.
404/// * `KindSignature`: A list of associated type definitions defining the `Kind` trait schema.
405/// * `AssocType`: The associated type to project (e.g., `Of`).
406/// * `Args`: The concrete arguments to apply.
407///
408/// ### Generates
409///
410/// The concrete type resulting from applying the brand to the arguments.
411///
412/// ### Examples
413///
414/// ```ignore
415/// // Invocation
416/// // Applies MyBrand to lifetime 'static and type String.
417/// type Concrete = Apply!(<MyBrand as Kind!( type Of<'a, T>; )>::Of<'static, String>);
418///
419/// // Expanded code
420/// type Concrete = <MyBrand as Kind_...>::Of<'static, String>;
421/// ```
422///
423/// ```ignore
424/// // Invocation
425/// // Applies MyBrand to a generic type T with bounds.
426/// type Concrete = Apply!(<MyBrand as Kind!( type Of<T: Clone>; )>::Of<T>);
427///
428/// // Expanded code
429/// type Concrete = <MyBrand as Kind_...>::Of<T>;
430/// ```
431///
432/// ```ignore
433/// // Invocation
434/// // Complex example with lifetimes, types, and output bounds.
435/// type Concrete = Apply!(<MyBrand as Kind!( type Of<'a, T: Clone + Debug>: Display; )>::Of<'a, T>);
436///
437/// // Expanded code
438/// type Concrete = <MyBrand as Kind_...>::Of<'a, T>;
439/// ```
440///
441/// ```ignore
442/// // Invocation
443/// // Use a custom associated type for projection.
444/// type Concrete = Apply!(<MyBrand as Kind!( type Of<T>; type SendOf<T>; )>::SendOf<T>);
445///
446/// // Expanded code
447/// type Concrete = <MyBrand as Kind_...>::SendOf<T>;
448/// ```
449///
450/// ```ignore
451/// // InferableBrand! in the brand position (resolved via preprocessing)
452/// Apply!(<<FA as InferableBrand!(type Of<'a, A: 'a>: 'a;)>::Brand as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
453///
454/// // Expanded code (InferableBrand! resolved to InferableBrand_cdc7...)
455/// <FA as InferableBrand_cdc7...>::Brand as Kind_cdc7...>::Of<'a, B>
456/// ```
457#[proc_macro]
458#[expect(non_snake_case, reason = "Matches the PascalCase type-level concept it represents")]
459pub fn Apply(input: TokenStream) -> TokenStream {
460	// Resolve any InferableBrand!(SIG) invocations before parsing.
461	let preprocessed: proc_macro2::TokenStream = input.into();
462	let preprocessed = match resolve_inferable_brand(preprocessed) {
463		Ok(ts) => ts,
464		Err(e) => return e.to_compile_error().into(),
465	};
466	let input = match syn::parse2::<ApplyInput>(preprocessed) {
467		Ok(input) => input,
468		Err(e) => return e.to_compile_error().into(),
469	};
470	match apply_worker(input) {
471		Ok(tokens) => tokens.into(),
472		Err(e) => e.to_compile_error().into(),
473	}
474}
475
476/// Adds a `Kind` supertrait bound to a trait definition.
477///
478/// This attribute macro parses a Kind signature and adds the corresponding
479/// `Kind_` trait as a supertrait bound, avoiding the need to reference
480/// hash-based trait names directly.
481///
482/// ### Syntax
483///
484/// ```ignore
485/// #[kind(type AssocName<Params>: Bounds;)]
486/// pub trait MyTrait {
487///     // ...
488/// }
489/// ```
490///
491/// ### Examples
492///
493/// ```ignore
494/// // Invocation
495/// #[kind(type Of<'a, A: 'a>: 'a;)]
496/// pub trait Functor {
497///     fn map<'a, A: 'a, B: 'a>(
498///         f: impl Fn(A) -> B + 'a,
499///         fa: Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, A>),
500///     ) -> Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>);
501/// }
502///
503/// // Expanded code
504/// pub trait Functor: Kind_cdc7cd43dac7585f {
505///     // body unchanged
506/// }
507/// ```
508///
509/// ```ignore
510/// // Works with existing supertraits
511/// #[kind(type Of<'a, A: 'a>: 'a;)]
512/// pub trait Monad: Applicative {
513///     // Kind_ bound is appended: Monad: Applicative + Kind_...
514/// }
515/// ```
516#[proc_macro_attribute]
517pub fn kind(
518	attr: TokenStream,
519	item: TokenStream,
520) -> TokenStream {
521	let attr = parse_macro_input!(attr as AssociatedTypes);
522	let item = parse_macro_input!(item as syn::ItemTrait);
523	match kind_attr_worker(attr, item) {
524		Ok(tokens) => tokens.into(),
525		Err(e) => e.to_compile_error().into(),
526	}
527}
528
529/// Generates re-exports for all public free functions in a directory.
530///
531/// This macro scans the specified directory for Rust files, parses them to find public free functions,
532/// and generates `pub use` statements for them. It supports aliasing to resolve name conflicts
533/// and exclusions to suppress specific functions from being re-exported.
534///
535/// ### Syntax
536///
537/// ```ignore
538/// generate_function_re_exports!("path/to/directory", {
539///     "module::name": aliased_name,
540///     ...
541/// }, exclude {
542///     "module::name",
543///     ...
544/// })
545/// ```
546///
547/// * `path/to/directory`: The path to the directory containing the modules, relative to the crate root.
548/// * `aliases` (optional): A map of function names to their desired aliases. Keys can be
549///   qualified (`"module::function"`) or unqualified (`"function"`). When aliased, the function
550///   is exported under the alias name only.
551/// * `exclude` (optional): A set of function names to suppress entirely. Keys use the same
552///   qualified/unqualified format as aliases. Excluded functions are not re-exported at all,
553///   but remain available in their original modules.
554///
555/// ### Generates
556///
557/// `pub use` statements for each public function found in the directory, except those
558/// listed in the `exclude` block.
559///
560/// ### Examples
561///
562/// ```ignore
563/// generate_function_re_exports!("src/classes", {
564///     "category::identity": category_identity,
565///     "filterable::filter": filterable_filter,
566/// }, exclude {
567///     "ref_filterable::ref_filter",
568///     "ref_filterable::ref_filter_map",
569/// });
570///
571/// // Expanded: re-exports all public functions except ref_filter and ref_filter_map.
572/// // category::identity is exported as category_identity.
573/// // filterable::filter is exported as filterable_filter.
574/// ```
575#[proc_macro]
576pub fn generate_function_re_exports(input: TokenStream) -> TokenStream {
577	let input = parse_macro_input!(input as ReExportInput);
578	generate_re_exports_worker(&input, &FunctionFormatter).into()
579}
580
581/// Generates re-exports for all public traits in a directory.
582///
583/// This macro scans the specified directory for Rust files, parses them to find public traits,
584/// and generates `pub use` statements for them. Supports the same aliasing and exclusion
585/// syntax as [`generate_function_re_exports!`].
586///
587/// ### Syntax
588///
589/// ```ignore
590/// generate_trait_re_exports!("path/to/directory", {
591///     "module::TraitName": AliasedName,
592///     ...
593/// }, exclude {
594///     "module::TraitName",
595///     ...
596/// })
597/// ```
598///
599/// * `path/to/directory`: The path to the directory containing the modules, relative to the crate root.
600/// * `aliases` (optional): A map of trait names to their desired aliases.
601/// * `exclude` (optional): A set of trait names to suppress from re-export.
602///
603/// ### Generates
604///
605/// `pub use` statements for each public trait found in the directory, except those
606/// listed in the `exclude` block.
607///
608/// ### Examples
609///
610/// ```ignore
611/// generate_trait_re_exports!("src/classes", {});
612///
613/// // Expanded code
614/// pub use src::classes::functor::Functor;
615/// pub use src::classes::monad::Monad;
616/// // ... other re-exports
617/// ```
618#[proc_macro]
619pub fn generate_trait_re_exports(input: TokenStream) -> TokenStream {
620	let input = parse_macro_input!(input as ReExportInput);
621	generate_re_exports_worker(&input, &TraitFormatter).into()
622}
623
624/// Generates a Hindley-Milner style type signature for a function.
625///
626/// This macro analyzes the function signature and generates a documentation comment
627/// containing the corresponding Hindley-Milner type signature.
628///
629/// When used within a module annotated with [`#[document_module]`](macro@document_module),
630/// it automatically resolves `Self` and associated types based on the module's projection map.
631///
632/// ### Syntax
633///
634/// ```ignore
635/// // Auto-generate from the function signature
636/// #[document_signature]
637/// pub fn function_name<Generics>(params) -> ReturnType { ... }
638///
639/// // Manual override with an explicit signature string
640/// #[document_signature("forall A B. (A -> B) -> A -> B")]
641/// pub fn function_name<Generics>(params) -> ReturnType { ... }
642/// ```
643///
644/// When a string argument is provided, it is emitted directly as the
645/// signature without any analysis. This is useful for functions whose
646/// signatures cannot be inferred automatically.
647///
648/// When applying this macro to a method inside a trait, you can provide the trait name
649/// as an argument to correctly generate the `Trait self` constraint.
650///
651/// ### Generates
652///
653/// A documentation comment with the generated signature, prepended to the function definition.
654///
655/// ### Examples
656///
657/// ```ignore
658/// // Invocation
659/// #[document_signature]
660/// pub fn map<F: Functor, A, B>(f: impl Fn(A) -> B, fa: F::Of<A>) -> F::Of<B> { ... }
661///
662/// // Expanded code
663/// /// ### Type Signature
664/// /// `forall f a b. Functor f => (a -> b, f a) -> f b`
665/// pub fn map<F: Functor, A, B>(f: impl Fn(A) -> B, fa: F::Of<A>) -> F::Of<B> { ... }
666/// ```
667///
668/// ```ignore
669/// // Invocation
670/// #[document_signature]
671/// pub fn foo(x: impl Iterator<Item = String>) -> i32 { ... }
672///
673/// // Expanded code
674/// /// ### Type Signature
675/// /// `iterator -> i32`
676/// pub fn foo(x: impl Iterator<Item = String>) -> i32 { ... }
677/// ```
678///
679/// ```ignore
680/// // Invocation
681/// trait Functor {
682///     #[document_signature]
683///     fn map<A, B>(f: impl Fn(A) -> B, fa: Self::Of<A>) -> Self::Of<B>;
684/// }
685///
686/// // Expanded code
687/// trait Functor {
688///     /// ### Type Signature
689///     /// `forall self a b. Functor self => (a -> b, self a) -> self b`
690///     fn map<A, B>(f: impl Fn(A) -> B, fa: Self::Of<A>) -> Self::Of<B>;
691/// }
692/// ```
693///
694/// Manual override:
695///
696/// ```ignore
697/// // Invocation
698/// #[document_signature("forall F A B. Contravariant F => (B -> A, F A) -> F B")]
699/// pub fn contramap<FA, A, B>(f: impl Fn(B) -> A, fa: FA) -> FA::Of<B> { ... }
700///
701/// // Expanded code
702/// /// ### Type Signature
703/// /// `forall F A B. Contravariant F => (B -> A, F A) -> F B`
704/// pub fn contramap<FA, A, B>(f: impl Fn(B) -> A, fa: FA) -> FA::Of<B> { ... }
705/// ```
706///
707/// ### Dispatch-aware generation
708///
709/// When used inside a module annotated with
710/// [`#[document_module]`](macro@document_module), this macro benefits
711/// from dispatch trait analysis. If the function references a dispatch
712/// trait (via `impl *Dispatch<...>` or a where-clause bound), the
713/// macro builds a synthetic signature that replaces dispatch machinery
714/// with semantic equivalents (branded types, closure arrows, type
715/// class constraints). This produces cleaner signatures like
716/// `forall Brand A B. Functor Brand => (A -> B, Brand A) -> Brand B`
717/// instead of the raw Rust signature with `InferableBrand` and
718/// `Kind_*` bounds.
719///
720/// ### Configuration
721///
722/// This macro can be configured via `Cargo.toml` under `[package.metadata.document_signature]`.
723///
724/// * `brand_mappings`: A map of brand struct names to their display names in the signature.
725/// * `apply_macro_aliases`: A list of macro names that should be treated as `Apply!`.
726/// * `ignored_traits`: A list of traits to ignore in the signature constraints.
727///
728/// Example:
729/// ```toml
730/// [package.metadata.document_signature]
731/// brand_mappings = { "OptionBrand" = "Option", "VecBrand" = "Vec" }
732/// apply_macro_aliases = ["MyApply"]
733/// ignored_traits = ["Clone", "Debug"]
734/// ```
735#[proc_macro_attribute]
736pub fn document_signature(
737	attr: TokenStream,
738	item: TokenStream,
739) -> TokenStream {
740	match document_signature_worker(attr.into(), item.into()) {
741		Ok(tokens) => tokens.into(),
742		Err(e) => e.to_compile_error().into(),
743	}
744}
745
746/// Generates documentation for type parameters.
747///
748/// This macro analyzes the item's signature (function, struct, enum, impl block, etc.)
749/// and generates a documentation comment list based on the provided descriptions.
750///
751/// When used within a module annotated with [`#[document_module]`](macro@document_module),
752/// it benefits from automatic `Self` resolution and is applied as part of the module-level
753/// documentation pass.
754///
755/// ### Syntax
756///
757/// ```ignore
758/// #[document_type_parameters(
759///     "Description for first parameter",
760///     ("OverriddenName", "Description for second parameter"),
761///     ...
762/// )]
763/// pub fn function_name<Generics>(params) -> ReturnType { ... }
764/// ```
765///
766/// It can also be used on other items like `impl` blocks:
767///
768/// ```ignore
769/// #[document_type_parameters("Description for T")]
770/// impl<T> MyType<T> { ... }
771/// ```
772///
773/// * `Descriptions`: A comma-separated list. Each entry can be either a string literal
774///   or a tuple of two string literals `(Name, Description)`.
775///
776/// ### Generates
777///
778/// A list of documentation comments, one for each generic parameter, prepended to the
779/// function definition.
780///
781/// ### Examples
782///
783/// ```ignore
784/// // Invocation
785/// #[document_type_parameters(
786///     "The type of the elements.",
787///     ("E", "The error type.")
788/// )]
789/// pub fn map<T, ERR>(...) { ... }
790///
791/// // Expanded code
792/// /// ### Type Parameters
793/// /// * `T`: The type of the elements.
794/// /// * `E`: The error type.
795/// pub fn map<T, ERR>(...) { ... }
796/// ```
797///
798/// ### Constraints
799///
800/// * The number of arguments must exactly match the number of generic parameters
801///   (including lifetimes, types, and const generics) in the function signature.
802#[proc_macro_attribute]
803pub fn document_type_parameters(
804	attr: TokenStream,
805	item: TokenStream,
806) -> TokenStream {
807	match document_type_parameters_worker(attr.into(), item.into()) {
808		Ok(tokens) => tokens.into(),
809		Err(e) => e.to_compile_error().into(),
810	}
811}
812
813/// Generates documentation for a function's parameters.
814///
815/// This macro analyzes the function signature and generates a documentation comment
816/// list based on the provided descriptions. It also handles curried return types.
817///
818/// It can also be used on `impl` blocks to provide a common description for the receiver (`self`)
819/// parameter of methods within the block.
820///
821/// ### Syntax
822///
823/// For functions:
824/// ```ignore
825/// #[document_parameters(
826///     "Description for first parameter",
827///     ("overridden_name", "Description for second parameter"),
828///     ...
829/// )]
830/// pub fn function_name(params) -> impl Fn(...) { ... }
831/// ```
832///
833/// For `impl` blocks:
834/// ```ignore
835/// #[document_parameters("Description for receiver")]
836/// impl MyType {
837///     #[document_parameters]
838///     pub fn method_with_receiver(&self) { ... }
839///
840///     #[document_parameters("Description for arg")]
841///     pub fn method_with_args(&self, arg: i32) { ... }
842/// }
843/// ```
844///
845/// * `Descriptions`: A comma-separated list. Each entry can be either a string literal
846///   or a tuple of two string literals `(Name, Description)`.
847/// * For `impl` blocks: Exactly one string literal describing the receiver parameter.
848///
849/// ### Generates
850///
851/// A list of documentation comments, one for each parameter, prepended to the
852/// function definition.
853///
854/// ### Examples
855///
856/// ```ignore
857/// // Invocation
858/// #[document_parameters(
859///     "The first input value.",
860///     ("y", "The second input value.")
861/// )]
862/// pub fn foo(x: i32) -> impl Fn(i32) -> i32 { ... }
863///
864/// // Expanded code
865/// /// ### Parameters
866/// /// * `x`: The first input value.
867/// /// * `y`: The second input value.
868/// pub fn foo(x: i32) -> impl Fn(i32) -> i32 { ... }
869/// ```
870///
871/// ```ignore
872/// // Invocation on impl block
873/// #[document_parameters("The list instance")]
874/// impl<A> MyList<A> {
875///     #[document_parameters("The element to push")]
876///     pub fn push(&mut self, item: A) { ... }
877/// }
878///
879/// // Expanded code
880/// impl<A> MyList<A> {
881///     /// ### Parameters
882///     /// * `&mut self`: The list instance
883///     /// * `item`: The element to push
884///     pub fn push(&mut self, item: A) { ... }
885/// }
886/// ```
887///
888/// ### Constraints
889///
890/// * The number of arguments must exactly match the number of function parameters
891///   (excluding `self` but including parameters from curried return types).
892///
893/// ### Configuration
894///
895/// This macro can be configured via `Cargo.toml` under `[package.metadata.document_signature]`.
896///
897/// * `apply_macro_aliases`: A list of macro names that should be treated as `Apply!` for curried parameter extraction.
898///
899/// Example:
900/// ```toml
901/// [package.metadata.document_signature]
902/// apply_macro_aliases = ["MyApply"]
903/// ```
904#[proc_macro_attribute]
905pub fn document_parameters(
906	attr: TokenStream,
907	item: TokenStream,
908) -> TokenStream {
909	match document_parameters_worker(attr.into(), item.into()) {
910		Ok(tokens) => tokens.into(),
911		Err(e) => e.to_compile_error().into(),
912	}
913}
914
915/// Generates documentation for the return value of a function.
916///
917/// This macro adds a "Returns" section to the function's documentation.
918///
919/// ### Syntax
920///
921/// ```ignore
922/// #[document_returns("Description of the return value.")]
923/// pub fn foo() -> i32 { ... }
924/// ```
925///
926/// ### Generates
927///
928/// A documentation comment describing the return value.
929///
930/// ### Examples
931///
932/// ```ignore
933/// // Invocation
934/// #[document_returns("The sum of x and y.")]
935/// pub fn add(x: i32, y: i32) -> i32 { ... }
936///
937/// // Expanded code
938/// /// ### Returns
939/// /// The sum of x and y.
940/// pub fn add(x: i32, y: i32) -> i32 { ... }
941/// ```
942#[proc_macro_attribute]
943pub fn document_returns(
944	attr: TokenStream,
945	item: TokenStream,
946) -> TokenStream {
947	match document_returns_worker(attr.into(), item.into()) {
948		Ok(tokens) => tokens.into(),
949		Err(e) => e.to_compile_error().into(),
950	}
951}
952
953/// Inserts a `### Examples` heading and validates doc comment code blocks.
954///
955/// This attribute macro expands in-place to a `### Examples` heading. Example
956/// code is written as regular doc comments using fenced code blocks after the
957/// attribute. Every Rust code block must contain at least one assertion macro
958/// invocation (e.g., `assert_eq!`, `assert!`).
959///
960/// ### Syntax
961///
962/// ```ignore
963/// #[document_examples]
964/// ///
965/// /// ```
966/// /// let result = add(1, 2);
967/// /// assert_eq!(result, 3);
968/// /// ```
969/// pub fn add(x: i32, y: i32) -> i32 { ... }
970/// ```
971///
972/// ### Generates
973///
974/// A `### Examples` heading is inserted at the attribute's position. The code
975/// blocks in the doc comments are validated but not modified.
976///
977/// ### Examples
978///
979/// ```ignore
980/// // Invocation
981/// #[document_examples]
982/// ///
983/// /// ```
984/// /// let x = my_fn(1, 2);
985/// /// assert_eq!(x, 3);
986/// /// ```
987/// pub fn my_fn(a: i32, b: i32) -> i32 { a + b }
988///
989/// // Expanded code
990/// /// ### Examples
991/// ///
992/// /// ```
993/// /// let x = my_fn(1, 2);
994/// /// assert_eq!(x, 3);
995/// /// ```
996/// pub fn my_fn(a: i32, b: i32) -> i32 { a + b }
997/// ```
998///
999/// ### Errors
1000///
1001/// * Arguments are provided to the attribute.
1002/// * No Rust code block is found in the doc comments.
1003/// * A Rust code block does not contain an assertion macro invocation.
1004/// * The attribute is applied more than once to the same function.
1005#[proc_macro_attribute]
1006pub fn document_examples(
1007	attr: TokenStream,
1008	item: TokenStream,
1009) -> TokenStream {
1010	match document_examples_worker(attr.into(), item.into()) {
1011		Ok(tokens) => tokens.into(),
1012		Err(e) => e.to_compile_error().into(),
1013	}
1014}
1015
1016/// Orchestrates documentation generation for an entire module.
1017///
1018/// This macro provides a centralized way to handle documentation for Higher-Kinded Type (HKT)
1019/// implementations. It performs a two-pass analysis of the module:
1020///
1021/// 1. **Context Extraction**: It scans for `impl_kind!` invocations and standard `impl` blocks
1022///    to build a comprehensive mapping of associated types (a "projection map").
1023/// 2. **Documentation Generation**: It processes all methods annotated with [`#[document_signature]`](macro@document_signature)
1024///    or [`#[document_type_parameters]`](macro@document_type_parameters), resolving `Self` and associated types
1025///    using the collected context.
1026/// 3. **Validation** (Optional): Checks that impl blocks and methods have appropriate documentation
1027///    attributes and emits compile-time warnings for missing documentation.
1028///
1029/// ### Syntax
1030///
1031/// Due to inner macro attributes being unstable, use the following wrapper pattern:
1032///
1033/// ```ignore
1034/// #[fp_macros::document_module]
1035/// mod inner {
1036///     // ... module content ...
1037/// }
1038/// pub use inner::*;
1039/// ```
1040///
1041/// To disable validation warnings:
1042///
1043/// ```ignore
1044/// #[fp_macros::document_module(no_validation)]
1045/// mod inner {
1046///     // ... module content ...
1047/// }
1048/// pub use inner::*;
1049/// ```
1050///
1051/// ### Generates
1052///
1053/// In-place replacement of [`#[document_signature]`](macro@document_signature) and
1054/// [`#[document_type_parameters]`](macro@document_type_parameters) attributes with generated documentation
1055/// comments. It also resolves `Self` and `Self::AssocType` references to their concrete
1056/// types based on the module's projection map.
1057///
1058/// ### Attributes
1059///
1060/// The macro supports several documentation-specific attributes for configuration:
1061///
1062/// * `#[document_default]`: (Used inside `impl` or `impl_kind!`) Marks an associated type as the
1063///   default to use when resolving bare `Self` references.
1064/// * `#[document_use = "AssocName"]`: (Used on `impl` or `fn`) Explicitly specifies which
1065///   associated type definition to use for resolution within that scope.
1066///
1067/// ### Validation
1068///
1069/// By default, `document_module` validates that impl blocks and methods have appropriate
1070/// documentation attributes and emits compile-time warnings for missing documentation.
1071///
1072/// To disable validation, use `#[document_module(no_validation)]`.
1073///
1074/// #### Validation Rules
1075///
1076/// An impl block or trait definition should have:
1077/// * `#[document_type_parameters]` if it has type parameters
1078/// * `#[document_parameters]` if it contains methods with receiver parameters (self, &self, &mut self)
1079///
1080/// A method should have:
1081/// * `#[document_signature]` - always recommended for documenting the Hindley-Milner signature
1082/// * `#[document_type_parameters]` if it has type parameters
1083/// * `#[document_parameters]` if it has non-receiver parameters
1084/// * `#[document_returns]` if it has a return type
1085/// * `#[document_examples]` - always recommended
1086///
1087/// A free function should have:
1088/// * `#[document_examples]` - always recommended
1089///
1090/// Documentation attributes must not be duplicated and must appear in canonical order:
1091/// `#[document_signature]` -> `#[document_type_parameters]` -> `#[document_parameters]` ->
1092/// `#[document_returns]` -> `#[document_examples]`.
1093///
1094/// Additionally, a lint warns when a named generic type parameter could be replaced with
1095/// `impl Trait` (i.e., it has trait bounds, appears in exactly one parameter position, does
1096/// not appear in the return type, and is not cross-referenced by other type parameters).
1097/// This lint skips trait implementations. Suppress it on individual functions or methods
1098/// with `#[allow_named_generics]`.
1099///
1100/// #### Examples of Validation
1101///
1102/// ```ignore
1103/// // This will emit warnings:
1104/// #[fp_macros::document_module]
1105/// mod inner {
1106///     pub struct MyType;
1107///
1108///     // WARNING: Impl block contains methods with receiver parameters
1109///     // but no #[document_parameters] attribute
1110///     impl MyType {
1111///         // WARNING: Method should have #[document_signature] attribute
1112///         // WARNING: Method has parameters but no #[document_parameters] attribute
1113///         // WARNING: Method has a return type but no #[document_returns] attribute
1114///         // WARNING: Method should have a #[document_examples] attribute
1115///         pub fn process(&self, x: i32) -> i32 { x }
1116///     }
1117/// }
1118/// ```
1119///
1120/// ```ignore
1121/// // Properly documented (no warnings):
1122/// #[fp_macros::document_module]
1123/// mod inner {
1124///     pub struct MyType;
1125///
1126///     #[document_parameters("The MyType instance")]
1127///     impl MyType {
1128///         #[document_signature]
1129///         #[document_parameters("The input value")]
1130///         #[document_returns("The input value unchanged.")]
1131///         #[document_examples]
1132///         ///
1133///         /// ```
1134///         /// # use my_crate::MyType;
1135///         /// let t = MyType;
1136///         /// assert_eq!(t.process(42), 42);
1137///         /// ```
1138///         pub fn process(&self, x: i32) -> i32 { x }
1139///     }
1140/// }
1141/// ```
1142///
1143/// ```ignore
1144/// // Disable validation to suppress warnings:
1145/// #[fp_macros::document_module(no_validation)]
1146/// mod inner {
1147///     // ... undocumented code won't produce warnings ...
1148/// }
1149/// ```
1150///
1151/// ### Hierarchical Configuration
1152///
1153/// When resolving the concrete type of `Self`, the macro follows this precedence:
1154///
1155/// 1. **Method Override**: `#[document_use = "AssocName"]` on the method.
1156/// 2. **Impl Block Override**: `#[document_use = "AssocName"]` on the `impl` block.
1157/// 3. **(Type, Trait)-Scoped Default**: `#[document_default]` on the associated type definition
1158///    in a trait `impl` block.
1159/// 4. **Module Default**: `#[document_default]` on the associated type definition in `impl_kind!`.
1160///
1161/// ### Examples
1162///
1163/// ```ignore
1164/// // Invocation
1165/// #[fp_macros::document_module]
1166/// mod inner {
1167///     use super::*;
1168///
1169///     impl_kind! {
1170///         for MyBrand {
1171///             #[document_default]
1172///             type Of<'a, T: 'a>: 'a = MyType<T>;
1173///         }
1174///     }
1175///
1176///     impl Functor for MyBrand {
1177///         #[document_signature]
1178///         fn map<'a, A: 'a, B: 'a, Func>(
1179///             f: Func,
1180///             fa: Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, A>),
1181///         ) -> Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
1182///         where
1183///             Func: Fn(A) -> B + 'a
1184///         {
1185///             todo!()
1186///         }
1187///     }
1188/// }
1189/// pub use inner::*;
1190///
1191/// // Expanded code
1192/// mod inner {
1193///     use super::*;
1194///
1195///     // ... generated Kind implementations ...
1196///
1197///     impl Functor for MyBrand {
1198///         /// ### Type Signature
1199///         /// `forall a b. (a -> b, MyType a) -> MyType b`
1200///         fn map<'a, A: 'a, B: 'a, Func>(
1201///             f: Func,
1202///             fa: Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, A>),
1203///         ) -> Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
1204///         where
1205///             Func: Fn(A) -> B + 'a
1206///         {
1207///             todo!()
1208///         }
1209///     }
1210/// }
1211/// pub use inner::*;
1212/// ```
1213#[proc_macro_attribute]
1214pub fn document_module(
1215	attr: TokenStream,
1216	item: TokenStream,
1217) -> TokenStream {
1218	match document_module_worker(attr.into(), item.into()) {
1219		Ok(tokens) => tokens.into(),
1220		Err(e) => e.to_compile_error().into(),
1221	}
1222}
1223
1224/// Monadic do-notation.
1225///
1226/// Desugars flat monadic syntax into nested `bind` calls, matching
1227/// Haskell/PureScript `do` notation. Supports both explicit-brand and
1228/// inferred-brand modes.
1229///
1230/// ### Syntax
1231///
1232/// ```ignore
1233/// // Explicit mode: brand specified, pure() rewritten automatically
1234/// m_do!(Brand {
1235///     x <- expr;            // Bind: extract value from monadic computation
1236///     y: Type <- expr;      // Typed bind: with explicit type annotation
1237///     _ <- expr;            // Discard bind: sequence, discarding the result
1238///     expr;                 // Sequence: discard result (shorthand for `_ <- expr;`)
1239///     let z = expr;         // Let binding: pure, not monadic
1240///     let w: Type = expr;   // Typed let binding
1241///     pure(z)               // pure() rewritten to pure::<Brand, _>(z)
1242/// })
1243///
1244/// // Inferred mode: brand inferred from container types
1245/// m_do!({
1246///     x <- Some(5);         // Brand inferred from Some(5) via InferableBrand
1247///     y <- Some(x + 1);
1248///     Some(x + y)           // Write concrete constructor (pure() not available)
1249/// })
1250///
1251/// // By-reference modes:
1252/// m_do!(ref Brand { ... })  // Explicit, ref dispatch
1253/// m_do!(ref { ... })        // Inferred, ref dispatch
1254/// ```
1255///
1256/// * `Brand` (optional): The monad brand type. When omitted, the brand is inferred
1257///   from container types via `InferableBrand`.
1258/// * `ref` (optional): Enables by-reference dispatch. Closures receive `&A`
1259///   instead of `A`, routing through `RefSemimonad::ref_bind`. Typed binds
1260///   use the type as-is (include `&` in the type annotation). Untyped binds
1261///   get `: &_` added automatically.
1262/// * In explicit mode, bare `pure(args)` calls are rewritten to `pure::<Brand, _>(args)`
1263///   (or `ref_pure::<Brand, _>(&args)` in ref mode).
1264/// * In inferred mode, bare `pure(args)` calls emit a `compile_error!` because
1265///   `pure` has no container argument to infer the brand from. Write concrete
1266///   constructors instead (e.g., `Some(x)` instead of `pure(x)`).
1267///
1268/// ### Statement Forms
1269///
1270/// | Syntax | Explicit expansion | Inferred expansion |
1271/// |--------|--------------------|--------------------|
1272/// | `x <- expr;` | `explicit::bind::<Brand, _, _, _, _>(expr, move \|x\| { ... })` | `bind(expr, move \|x\| { ... })` |
1273/// | `x: Type <- expr;` | Same with `\|x: Type\|` | Same with `\|x: Type\|` |
1274/// | `expr;` | `explicit::bind::<Brand, _, _, _, _>(expr, move \|_\| { ... })` | `bind(expr, move \|_\| { ... })` |
1275/// | `let x = expr;` | `{ let x = expr; ... }` | `{ let x = expr; ... }` |
1276/// | `expr` (final) | Emitted as-is | Emitted as-is |
1277///
1278/// ### Examples
1279///
1280/// ```ignore
1281/// // Inferred mode (primary API for single-brand types)
1282/// let result = m_do!({
1283///     x <- Some(5);
1284///     y <- Some(x + 1);
1285///     let z = x * y;
1286///     Some(z)
1287/// });
1288/// assert_eq!(result, Some(30));
1289///
1290/// // Expands to:
1291/// let result = bind(Some(5), move |x| {
1292///     bind(Some(x + 1), move |y| {
1293///         let z = x * y;
1294///         Some(z)
1295///     })
1296/// });
1297/// ```
1298///
1299/// ```ignore
1300/// // Explicit mode (for ambiguous types or to use pure())
1301/// let result = m_do!(VecBrand {
1302///     x <- vec![1, 2];
1303///     y <- vec![10, 20];
1304///     pure(x + y)
1305/// });
1306/// assert_eq!(result, vec![11, 21, 12, 22]);
1307///
1308/// // Expands to:
1309/// let result = explicit::bind::<VecBrand, _, _, _, _>(vec![1, 2], move |x| {
1310///     explicit::bind::<VecBrand, _, _, _, _>(vec![10, 20], move |y| {
1311///         pure::<VecBrand, _>(x + y)
1312///     })
1313/// });
1314/// ```
1315///
1316/// ### Ref mode: multi-bind limitation
1317///
1318/// In ref mode, each bind generates a `move` closure that receives `&A`.
1319/// Inner closures cannot capture references from outer binds because the
1320/// reference lifetime is scoped to the outer closure. Attempting to use a
1321/// ref-bound variable in a later bind produces a lifetime error.
1322///
1323/// **Workaround:** use `let` bindings to dereference or clone values so
1324/// they become owned and can be captured by later closures:
1325///
1326/// ```ignore
1327/// m_do!(ref LazyBrand {
1328///     x: &i32 <- lazy_a;
1329///     let x_val = *x;          // dereference into owned value
1330///     y: &i32 <- lazy_b;
1331///     pure(x_val + *y)         // x_val is owned, safe to use here
1332/// })
1333/// ```
1334///
1335/// When all binds are independent (no bind uses the result of another),
1336/// prefer [`a_do!`] instead. Applicative do-notation evaluates all
1337/// expressions independently, so there is no closure nesting and no
1338/// capture issue.
1339#[proc_macro]
1340pub fn m_do(input: TokenStream) -> TokenStream {
1341	let input = parse_macro_input!(input as DoInput);
1342	match m_do_worker(input) {
1343		Ok(tokens) => tokens.into(),
1344		Err(e) => e.to_compile_error().into(),
1345	}
1346}
1347
1348/// Applicative do-notation.
1349///
1350/// Desugars flat applicative syntax into `pure` / `map` / `lift2`-`lift5`
1351/// calls, matching PureScript `ado` notation. Unlike [`m_do!`], bindings are
1352/// independent: later bind expressions cannot reference earlier bound variables.
1353/// Supports both explicit-brand and inferred-brand modes.
1354///
1355/// ### Syntax
1356///
1357/// ```ignore
1358/// // Explicit mode
1359/// a_do!(Brand {
1360///     x <- expr;            // Bind: independent applicative computation
1361///     y: Type <- expr;      // Typed bind: with explicit type annotation
1362///     _ <- expr;            // Discard bind: compute for effect
1363///     expr;                 // Sequence: shorthand for `_ <- expr;`
1364///     let z = expr;         // Let binding: placed inside the combining closure
1365///     expr                  // Final expression: the combining body
1366/// })
1367///
1368/// // Inferred mode (brand inferred from container types)
1369/// a_do!({
1370///     x <- Some(3);
1371///     y <- Some(4);
1372///     x + y
1373/// })
1374///
1375/// // By-reference modes:
1376/// a_do!(ref Brand { ... })  // Explicit, ref dispatch
1377/// a_do!(ref { ... })        // Inferred, ref dispatch
1378/// ```
1379///
1380/// * `Brand` (optional): The applicative brand type. When omitted, the brand is
1381///   inferred from container types via `InferableBrand`.
1382/// * `ref` (optional): Enables by-reference dispatch. The combining closure
1383///   receives references (`&A`, `&B`, etc.) via `RefLift::ref_lift2`. Typed
1384///   binds use the type as-is (include `&`). Untyped binds get `: &_`.
1385/// * Bind expressions are evaluated independently (applicative, not monadic).
1386/// * `let` bindings before any `<-` are hoisted outside the combinator call.
1387/// * `let` bindings after a `<-` are placed inside the combining closure.
1388/// * In explicit mode, bare `pure(args)` calls are rewritten to `pure::<Brand, _>(args)`.
1389/// * In inferred mode, bare `pure(args)` calls emit a `compile_error!`.
1390/// * In inferred mode with 0 binds, a `compile_error!` is emitted because
1391///   `pure()` requires a brand. Write the concrete constructor directly.
1392///
1393/// ### Desugaring
1394///
1395/// | Binds | Explicit expansion | Inferred expansion |
1396/// |-------|--------------------|--------------------|
1397/// | 0 | `pure::<Brand, _>(final_expr)` | `compile_error!` |
1398/// | 1 | `explicit::map::<Brand, _, _, _, _>(\|x\| body, expr)` | `map(\|x\| body, expr)` |
1399/// | N (2-5) | `explicit::liftN::<Brand, ...>(\|x, y, ...\| body, ...)` | `liftN(\|x, y, ...\| body, ...)` |
1400///
1401/// ### Examples
1402///
1403/// ```ignore
1404/// use fp_library::functions::*;
1405/// use fp_macros::a_do;
1406///
1407/// // Inferred mode: two independent computations combined with lift2
1408/// let result = a_do!({
1409///     x <- Some(3);
1410///     y <- Some(4);
1411///     x + y
1412/// });
1413/// assert_eq!(result, Some(7));
1414///
1415/// // Expands to:
1416/// let result = lift2(|x, y| x + y, Some(3), Some(4));
1417///
1418/// // Inferred mode: single bind uses map
1419/// let result = a_do!({ x <- Some(5); x * 2 });
1420/// assert_eq!(result, Some(10));
1421///
1422/// // Expands to:
1423/// let result = map(|x| x * 2, Some(5));
1424/// ```
1425///
1426/// ```ignore
1427/// // Explicit mode: zero-bind block uses pure (requires brand)
1428/// let result: Option<i32> = a_do!(OptionBrand { 42 });
1429/// assert_eq!(result, Some(42));
1430///
1431/// // Expands to:
1432/// let result: Option<i32> = pure::<OptionBrand, _>(42);
1433///
1434/// // Explicit mode: single bind
1435/// let result = a_do!(OptionBrand { x <- Some(5); x * 2 });
1436///
1437/// // Expands to:
1438/// let result = explicit::map::<OptionBrand, _, _, _, _>(|x| x * 2, Some(5));
1439/// ```
1440#[proc_macro]
1441pub fn a_do(input: TokenStream) -> TokenStream {
1442	let input = parse_macro_input!(input as DoInput);
1443	match a_do_worker(input) {
1444		Ok(tokens) => tokens.into(),
1445		Err(e) => e.to_compile_error().into(),
1446	}
1447}