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