Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b32f18e

Browse files
committed
[add] 文脈マクロ内で文脈付き呼び出しが行えるようにした
1 parent a6d46ba commit b32f18e

File tree

4 files changed

+68
-3
lines changed

4 files changed

+68
-3
lines changed

‎crates/macros/src/impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod modifier;
2+
pub mod modifier_caller;

‎crates/macros/src/impl/modifier.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,20 @@ pub fn proc_macro_impl(_args: TokenStream, ast: ItemTrait) -> TokenStream {
99
let macro_ident = as_macro_ident(trait_name);
1010

1111
quote! {
12+
// トレイト本体
1213
#ast
1314

15+
// 文脈マクロ
1416
macro_rules! #macro_ident {
1517
($($body:tt)*) => {{
16-
fn __mymodifier_callee() {
18+
// 文脈付き呼び出しへの変換
19+
#[modifier_caller(#trait_name)]
20+
fn __mymodifier_caller() {
1721
$($body)*
1822
}
19-
__mymodifier_callee();
23+
24+
// 呼び出し
25+
__mymodifier_caller();
2026
}};
2127
}
2228
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use proc_macro2::TokenStream;
2+
use quote::{quote, ToTokens};
3+
use syn::{Expr, ItemFn, Stmt};
4+
5+
/// 対象: 関数
6+
/// 動作: 文脈付き呼び出しを行うための前準備を生成 & 文脈付き呼び出しへの変換
7+
pub fn proc_macro_impl(args: TokenStream, ast: ItemFn) -> TokenStream {
8+
let target_trait = args;
9+
10+
let fn_visibility = ast.vis;
11+
let fn_ident = ast.sig.ident;
12+
let fn_ret_type = ast.sig.output;
13+
let fn_stmts = &ast
14+
.block
15+
.stmts
16+
.iter()
17+
.map(append_ctx_if_calling)
18+
.collect::<Vec<_>>();
19+
20+
quote! {
21+
// マクロ適用関数
22+
#fn_visibility fn #fn_ident () #fn_ret_type {
23+
// 前準備
24+
#[allow(non_local_definitions)]
25+
impl #target_trait for Ctx {}
26+
27+
// 関数本体
28+
#(#fn_stmts);*
29+
}
30+
}
31+
}
32+
33+
fn append_ctx_if_calling(stmt: &Stmt) -> TokenStream {
34+
let append_ctx = |expr: &Expr| {
35+
if let Expr::Call(call) = expr {
36+
let func = call.func.to_token_stream();
37+
let args = call.args.to_token_stream();
38+
quote! { #func (Ctx, #args) }
39+
} else {
40+
stmt.to_token_stream()
41+
}
42+
};
43+
44+
match stmt {
45+
Stmt::Expr(expr, _) => append_ctx(expr),
46+
_ => stmt.to_token_stream(),
47+
}
48+
}

‎crates/macros/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
mod r#impl;
22

33
use proc_macro2::TokenStream;
4-
use syn::{parse_macro_input, ItemTrait};
4+
use syn::{parse_macro_input, ItemFn,ItemTrait};
55

66
#[proc_macro_attribute]
77
pub fn modifier(
@@ -12,3 +12,13 @@ pub fn modifier(
1212
let ast = parse_macro_input!(item as ItemTrait);
1313
r#impl::modifier::proc_macro_impl(args, ast).into()
1414
}
15+
16+
#[proc_macro_attribute]
17+
pub fn modifier_caller(
18+
attr: proc_macro::TokenStream,
19+
item: proc_macro::TokenStream,
20+
) -> proc_macro::TokenStream {
21+
let args: TokenStream = attr.into();
22+
let ast = parse_macro_input!(item as ItemFn);
23+
r#impl::modifier_caller::proc_macro_impl(args, ast).into()
24+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /