batch_impl/lib.rs
1use proc_macro::TokenStream;
2use proc_macro2::TokenStream as TokenStream2;
3use quote::quote;
4use syn::{parse_macro_input, ItemTrait};
5
6mod core;
7
8use core::codegen::generate_impl;
9use core::parser::parse_top_level;
10use core::types::{err, ParseResult};
11
12// ===========================================================================
13// #[batch_impl(...)]
14// ===========================================================================
15
16/// 为 trait 批量生成 impl 块的属性宏。
17///
18/// # 语法概览
19///
20/// ```text
21/// #[batch_impl( impl-spec [, impl-spec]* [ { body }]? )]
22/// impl-spec = [ <impl-泛型> ] [ Trait名<trait-泛型> ] 目标 [ { body } ]
23/// ```
24///
25/// # `^` 运算符(右结合)
26///
27/// `A^B^C = A^(B^C)`
28///
29/// | 写法 | 展开 |
30/// |------|------|
31/// | `&^T` | `&T` |
32/// | `&mut^T` | `&mut T` |
33/// | `*const^T` | `*const T` |
34/// | `*mut^T` | `*mut T` |
35/// | `self^T` | `T` |
36/// | `A^B` | `A<B>` |
37/// | `A^<X,Y>` | `A<X,Y>` |
38/// | `[A1,A2]^B` | `A1<B>, A2<B>` |
39/// | `A^[B1,B2]` | `A<B1>, A<B2>` |
40/// | `[A1,A2]^[B1,B2]` | 笛卡尔积 `A1<B1>, A1<B2>, A2<B1>, A2<B2>` |
41/// | `Box^Box^T` | `Box<Box<T>>` |
42/// | `Box^[Box^T]` | `Box<[Box<T>]>` |
43/// | `HashMap<K>^V` | `HashMap<K, V>`(预填泛型追加) |
44/// | `[HashMap<K>, Vec<K>]^V` | `HashMap<K, V>, Vec<K, V>` |
45/// | `&^Box^T` | `&Box<T>`(引用类修饰符链式应用) |
46/// | `*const^Vec^T` | `*const Vec<T>` |
47/// | `fn^(A,B)` | `fn(A,B)`(函数类型) |
48/// | `#[attr]^T` | 在 impl 块前添加属性 |
49///
50/// # 元组 `^`(追加/生成)
51///
52/// 追加(右侧是类型):
53/// | 写法 | 展开 |
54/// |------|------|
55/// | `()^T` | `(T,)` |
56/// | `(A,B)^T` | `(A, B, T)` |
57///
58/// 生成(右侧是数字或范围):
59/// | 写法 | 展开 |
60/// |------|------|
61/// | `()^N` | `(A, B, ...)`(带 N 个泛型参数) |
62/// | `(T)^N` | `(T, T, ..., T)`(长度为 N) |
63/// | `(<tr>)^N` | `(A:tr, B:tr, ...)`(带 N 个泛型参数) |
64/// | `()^M..N` | 长度 M 到 N-1 的元组 |
65/// | `()^M..=N` | 长度 M 到 N 的元组 |
66///
67/// 笛卡尔积生成(前缀含逗号):
68/// | 写法 | 展开 |
69/// |------|------|
70/// | `(T1,T2)^N` | 长度为 N 的所有 T1/T2 组合 |
71/// | `(<tr>,T)^N` | 带 bound 的泛型+固定类型组合 |
72///
73/// # fn 类型
74///
75/// | 写法 | 展开 |
76/// |------|------|
77/// | `fn^(A,B)` | `fn(A,B)`(函数类型创建) |
78/// | `fn(A,B)^T` | `fn(A,B)->T`(追加返回类型) |
79/// | `fn-(A,B)^N` | 生成 N 长度组合的函数类型 |
80///
81/// # `-` 运算符(左结合)
82///
83/// `-` 与 `^` 语义完全相同,仅结合方向不同:`A-B = A^B`,`A-B-C = (A-B)-C`
84///
85/// | 写法 | 展开 |
86/// |------|------|
87/// | `Vec-u32` | `Vec<u32>`(同 `Vec^u32`) |
88/// | `HashMap-u32-String` | `HashMap<u32, String>`(左结合,预填泛型追加) |
89/// | `()-[A,B]` | `(A,), (B,)` |
90/// | `()-[A,B]-[C,D]` | `(A,C), (A,D), (B,C), (B,D)` |
91/// | `()-[A]-[B]-[C]` | `(A,B,C)` |
92///
93/// # 优先级
94///
95/// `^` 高于 `-`,`,` 最低
96///
97/// # 其他规则
98///
99/// - **`[]` 歧义**:有逗号是并列列表,无逗号是切片类型
100/// - **`()` 歧义**:`()=空元组`, `(A,)=单元素元组`, `(A)=分组(非元组)`
101/// - **trait 泛型必须显式**:trait 有泛型时必须写 `Trait名<T>`
102/// - **泛型继承**:嵌套 `[...]` 中子项不写泛型则继承父级,写了则追加并去重
103/// - **body 继承**:列表级 `{...}` 被所有子项共享;子项 `{...}` 与共享 body 合并(拼接)
104/// - **目标类型透传**:不解析,原样透传
105///
106/// # 基本示例
107///
108/// ```
109/// # use batch_impl::batch_impl;
110/// #[batch_impl(usize, isize)]
111/// trait Numeric {}
112/// ```
113///
114/// # 类型标注 / const 泛型 / 生命周期
115///
116/// ```
117/// # use batch_impl::batch_impl;
118/// #[batch_impl(<T: Clone + std::fmt::Debug> Vec<T>)]
119/// trait DebugClone {}
120///
121/// #[batch_impl(<const N: usize> [i32; N])]
122/// trait FixedSize {}
123///
124/// #[batch_impl(<'a, T: 'a> &'a T)]
125/// trait RefTrait {}
126/// ```
127///
128/// # trait 自身带泛型参数
129///
130/// ```
131/// # use batch_impl::batch_impl;
132/// #[batch_impl(<T> FromValue<T> i32 {
133/// fn wrap(_val: T) -> Self { 0 }
134/// })]
135/// trait FromValue<T> { fn wrap(val: T) -> Self; }
136///
137/// #[batch_impl(<T> Wrapper<Vec<T>> Vec<T> {
138/// fn inner(self) -> Vec<T> { self }
139/// })]
140/// trait Wrapper<C> { fn inner(self) -> C; }
141/// ```
142///
143/// > **必须显式写 `Trait名<泛型>`**,否则生成的 impl 缺少 trait 泛型。
144///
145/// # 并列列表
146///
147/// ```
148/// # use batch_impl::batch_impl;
149/// #[batch_impl([usize, isize, f32] {
150/// fn tag(&self) -> &'static str { "number" }
151/// })]
152/// trait Tagged { fn tag(&self) -> &'static str; }
153///
154/// // 嵌套泛型合并(<U> 追加到父级 <T>,去重)
155/// # use std::collections::HashMap;
156/// #[batch_impl(<T> Describe<T> [Vec<T>, <U> HashMap<T, U>] {
157/// fn describe(&self) -> String { format!("len={}", self.len()) }
158/// })]
159/// trait Describe<T> { fn describe(&self) -> String; }
160/// // → impl<T> Describe<T> for Vec<T>
161/// // → impl<T, U> Describe<T> for HashMap<T, U>
162/// ```
163///
164/// # 关联类型简洁写法
165///
166/// 在 trait 泛型参数中使用 `Name=value` 语法绑定关联类型:
167///
168/// ```
169/// # use batch_impl::batch_impl;
170/// #[batch_impl(<T> Iter<Item=T> Vec<T> {
171/// fn count(&self) -> usize { self.len() }
172/// })]
173/// trait Iter {
174/// type Item;
175/// fn count(&self) -> usize;
176/// }
177/// // → impl<T> Iter for Vec<T> { type Item = T; ... }
178/// ```
179///
180/// 支持多关联类型:`Pair<First=T, Second=U>`
181///
182/// # 独立/共享 body 合并
183///
184/// 列表项可有独立 body,与共享 body 合并:
185///
186/// ```
187/// # use batch_impl::batch_impl;
188/// #[batch_impl(
189/// [usize { fn name() -> &'static str { "usize" } },
190/// isize { fn name() -> &'static str { "isize" } }]
191/// { fn zero() -> Self { 0 } }
192/// )]
193/// trait Zero {
194/// fn zero() -> Self;
195/// fn name() -> &'static str;
196/// }
197/// ```
198///
199/// # `^` 运算符示例
200///
201/// ```
202/// # use batch_impl::batch_impl;
203/// #[batch_impl([&, self]^u32)]
204/// trait RefOrOwned {}
205///
206/// # use std::collections::HashMap;
207/// #[batch_impl(HashMap^<u32, i32>)]
208/// trait MapMarker {}
209/// ```
210///
211/// # 多项独立 body
212///
213/// ```
214/// # use batch_impl::batch_impl;
215/// #[batch_impl(
216/// usize { fn id(&self) -> usize { *self } },
217/// String { fn id(&self) -> usize { self.len() } }
218/// )]
219/// trait Identifiable { fn id(&self) -> usize; }
220/// ```
221///
222/// # 复杂类型透传
223///
224/// ```
225/// # use batch_impl::batch_impl;
226/// #[batch_impl((i32, String), &str, Box<dyn std::fmt::Display>, dyn Fn() + Send + Sync)]
227/// trait ComplexMarker {}
228/// ```
229///
230/// # 设计约束
231///
232/// - **where 子句**:不在 DSL 内,复杂 bound 写在 trait 定义自身
233/// - **`for<'a>` 高阶 trait bound**:where 子句式范畴;类型内部走 token 透传
234/// - **`<>` 多参不能在 `[]` 内**:Rust `[<` 解析歧义,拆成独立表达式
235#[proc_macro_attribute]
236pub fn batch_impl(attr: TokenStream, item: TokenStream) -> TokenStream {
237 let trait_item = parse_macro_input!(item as ItemTrait);
238 let trait_name = &trait_item.ident;
239 let name_ts = quote! { #trait_name };
240
241 // 检测是否是 unsafe trait
242 let is_unsafe_trait = trait_item.unsafety.is_some();
243
244 let attr_ts: TokenStream2 = attr.into();
245 let specs = parse_top_level(attr_ts, trait_name, trait_name.span());
246
247 let mut output = TokenStream2::new();
248 match specs {
249 ParseResult::Ok(specs) => {
250 for mut spec in specs {
251 // 如果是 unsafe trait,所有 impl 都标记为 unsafe
252 if is_unsafe_trait {
253 spec.is_unsafe = true;
254 }
255 output.extend(generate_impl(&spec, name_ts.clone()));
256 }
257 }
258 ParseResult::Err(e) => output.extend(e),
259 }
260
261 (quote! { #trait_item #output }).into()
262}
263
264// ===========================================================================
265// batch_trait!(Trait: impl-specs; ...)
266// ===========================================================================
267
268/// 对已声明的 trait 批量生成 impl 块的函数式宏。
269///
270/// # 语法
271///
272/// ```text
273/// batch_trait!(Trait路径: impl-specs; Trait路径: impl-specs)
274/// ```
275///
276/// `:` 前是 trait 路径(支持 `sub::MyTrait`),`:` 后是 `#[batch_impl]` 同款参数,
277/// `;` 分隔不同的 trait。
278///
279/// ```
280/// # use batch_impl::batch_trait;
281/// trait A {}
282/// trait B<T> {}
283/// mod foo { pub trait C {} }
284///
285/// batch_trait!(
286/// A: usize, isize;
287/// B: <T> B<T> Vec<T>;
288/// foo::C: u32
289/// );
290/// // → impl A for usize {} + impl A for isize {}
291/// // → impl<T> B<T> for Vec<T> {}
292/// // → impl foo::C for u32 {}
293/// ```
294///
295/// **注意**:trait 有泛型时,必须在 `:` 后的 impl-spec 中显式写出 `Trait名<泛型>`。
296#[proc_macro]
297pub fn batch_trait(input: TokenStream) -> TokenStream {
298 let input_ts: TokenStream2 = input.into();
299 let span = core::utils::tokens_span(&input_ts);
300
301 let segments = match core::utils::split_by(input_ts, ';', span) {
302 Ok(s) => s,
303 Err(e) => return e.into(),
304 };
305
306 let mut output = TokenStream2::new();
307 for seg in segments {
308 let seg_vec: Vec<proc_macro2::TokenTree> = seg.into_iter().collect();
309 if seg_vec.is_empty() {
310 continue;
311 }
312
313 let colon = match core::utils::find_top_level_colon(&seg_vec) {
314 Some(p) => p,
315 None => {
316 output.extend(err(
317 span,
318 "batch_trait! 缺少 `:`(格式:Trait名: impl规格,如 A: usize, isize)",
319 ));
320 continue;
321 }
322 };
323
324 // 检测 unsafe 关键字
325 let (is_unsafe, trait_start) = if colon > 0
326 && matches!(&seg_vec[0], proc_macro2::TokenTree::Ident(id) if id == "unsafe")
327 {
328 (true, 1)
329 } else {
330 (false, 0)
331 };
332
333 let trait_path: TokenStream2 = seg_vec[trait_start..colon].iter().cloned().collect();
334 let specs_ts: TokenStream2 = seg_vec[colon + 1..].iter().cloned().collect();
335
336 let trait_ident = match syn::parse2::<syn::Path>(trait_path.clone()) {
337 Ok(p) => p.segments.last().unwrap().ident.clone(),
338 Err(e) => {
339 output.extend(err(
340 span,
341 &format!(
342 "batch_trait! 中 `:` 左侧不是合法的路径: {}。示例: A, foo::Bar",
343 e
344 ),
345 ));
346 continue;
347 }
348 };
349
350 match parse_top_level(specs_ts, &trait_ident, trait_ident.span()) {
351 ParseResult::Ok(specs) => {
352 for mut spec in specs {
353 if is_unsafe {
354 spec.is_unsafe = true;
355 }
356 output.extend(generate_impl(&spec, trait_path.clone()));
357 }
358 }
359 ParseResult::Err(e) => output.extend(e),
360 }
361 }
362 output.into()
363}