Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
procedural-macros
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
cipepser
June 16, 2020
Technology
210
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
procedural-macros
cipepser
June 16, 2020
More Decks by cipepser
See All by cipepser
long-running-tasks
cipepser
3
510
layerx-fde-practices
cipepser
6
3.1k
NIKKEI Tech Talk#38
cipepser
0
1.2k
LayerXにおけるFDEについて
cipepser
3
3.2k
20250725-bet-ai-day
cipepser
3
660
Criterion-rs
cipepser
0
170
Practical Anonify
cipepser
2
910
Move for Libra written in Rust
cipepser
2
3.3k
How IBLT Works
cipepser
0
270
Other Decks in Technology
See All in Technology
機械学習を「社会実装」するということ 2026年夏版 / Social Implementation of Machine Learning June 2026 Version
moepy_stats
6
2.4k
人材育成分科会.pdf
_awache
4
260
エンジニアリング戦略の作り方 / Crafting Engineering Strategy
iwashi86
21
7k
小さくはじめるSLI/SLO ~育てながら組織に定着させる実践知~ / Starting Small with SLI/SLOs: Building Adoption Through Continuous Growth
nari_ex
7
2k
2026TECHFRESH畢業分享會 - Lightning Talk - 打造精準高效的 MCP 設計模式與測試實務
line_developers_tw
PRO
0
1.1k
AIっぽい文章を採点して人間らしく直すアプリを作ってみた
yama3133
2
200
2026TECHFRESH畢業分享會 - Lightning Talk - 資料也要 CI/CD? 用 Airbyte 自動化資料同步
line_developers_tw
PRO
0
1.1k
Chainlitで作るお手軽チャットUI
ynt0485
0
260
脆弱性対応、どこで線を引くか
rymiyamoto
1
400
いまさら聞けない「仕様駆動開発入門」 〜AI活用時代の開発プロセスを考える〜
findy_eventslides
2
130
Agent Skills設計で柔軟性と硬さのバランスが難しい話
nassy20
0
130
なぜ Platform Engineering の土台に Kubernetes を選ぶのか
r4ynode
2
650
Featured
See All Featured
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.6k
Exploring anti-patterns in Rails
aemeredith
3
410
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
How to Talk to Developers About Accessibility
jct
2
230
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
240
Git: the NoSQL Database
bkeepers
PRO
432
67k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
3.4k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
180
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Transcript
Procedural macros入門 cipepser 2020/6/16 下町.rs #2
自己紹介 • cipepser(さいぺ) • リードエンジニア@LayerX ◦ R&Dチーム • 経歴 ◦
SIerで証券系システムのネットワーク設計、構築 ◦ Fintech会社で新規事業の立ち上げ • 趣味プロジェクト ◦ コンパイラ ◦ 正規表現ジェネレータ ◦ protocol buffersデコーダ ◦ (多くがやりかけ...)
Anonifyをリリースしました ソースコード ホワイトペーパー https://github.com/LayerXcom/anonify https://layerx.co.jp/wp-content/uploads/2020/06/anonify.pdf ドキュメント https://layerxcom.github.io/anonify-book/ スライド https://speakerdeck.com/layerx/anonify TEE内のテストにProcedural
macrosを利用している
アジェンダ 1. Procedural macros概要 2. 通常のRustマクロ 3. Procedural macrosでよく利用される3つマクロたち 4.
Custom Attributeの実装
Procedural macros概要
Procedural macrosをざっくりと理解する • Rust edition 2018から使えるようになった • 通常のRustマクロ ◦ macro_rules!
◦ パターンマッチ • Procedural macros ◦ Function-like macros ▪ custom!(...) ◦ Derive macros ▪ #[derive(CustomDerive)] ◦ Attribute macros ▪ #[CustomAttribute]
通常のRustマクロ
macro_rules! vec { () => ( $crate::vec::Vec::new() ); ($elem:expr; $n:expr)
=> ( $crate::vec::from_elem($elem, $n) ); ($($x:expr),+ $(,)?) => ( <[_]>::into_vec(box [$($x),+]) ); } Proceduralでない通常のRustマクロはパターンマッチがベース https://github.com/rust-lang/rust/blob/master/src/liballoc/macros.rs • (pattern) => (template); • *, +による繰り返し ◦ 参照は$で対になっている必要がある • exprやtyなどのフラグメント型 vec![]: vec![“a”; 3]: vec![1,2,3]:
Procedural macrosでよく利用される 3つマクロたち
proc_macro • Procedural macrosの実装をサポートするラ イブラリ • Cargo.tomlのlibで有効化して使う • proc_macro2というwrapperもある ◦
build.rsやmain.rsのような別のコンテキストに proc_macroの機能を持ち込みたいときに使う • TokenStreamを操作する ◦ ASTを直接操作するわけではない ◦ Vec<TokenTree>をcloneしやすくしたもの ◦ TokenTree = lexical token https://doc.rust-lang.org/proc_macro/
syn • 文字列を入力に構文解析 • validなRustコードであることを保証 • Structsでもろもろ定義されている ◦ 次ページでItemFnを例にみてみます https://docs.rs/syn/1.0.31/syn/
例)synで関数名を取得する pub struct ItemFn { pub attrs: Vec<Attribute>, pub vis:
Visibility, pub sig: Signature, pub block: Box<Block>, } pub struct Signature { pub constness: Option<Token![const]>, pub asyncness: Option<Token![async]>, pub unsafety: Option<Token![unsafe]>, pub abi: Option<Abi>, pub fn_token: Token![fn], pub ident: Ident, pub generics: Generics, pub paren_token: token::Paren, pub inputs: Punctuated<FnArg, Token![,]>, pub variadic: Option<Variadic>, pub output: ReturnType, } 関数名を持つ
quote • synのデータ構造を受け取り、トークン列に 変換し直す • #varで補完 ◦ 例)取得した関数名を利用したいとき https://docs.rs/quote/1.0.7/quote/ let
f = parse_macro_input!(input as ItemFn); let f_ident = &f.sig.ident; let q = quote!( #f_ident .. };
Custom Attributeの実装
Attributeの復習 #[test] fn check() { let x = 1; assert_eq!(x,
1); } #[test]を付与することで、check()に 「cargo test時に実行される」という意味を付与
やること:Custom Attributeで、cargo runでテストを走らせます use utils::{test_case, run_inventory_tests}; #[test_case] fn check() {
let x = 1; assert_eq!(x, 1); } #[test_case] fn fail() { let x = 1; assert_eq!(x, 2); } fn main() { run_inventory_tests!(); } • #[test_case] attributeを自作 • cargo runで実行 ◦ ✖ cargo test
ディレクトリ構造とCargo.toml [lib] proc-macro = true [dependencies] proc-macro2 = "1.0" quote
= "1.0" syn = "1.0" main関数を実装 標準出力の調整など Procedural macrosを実装 proc-macroを有効化
#[proc_macro_attribute] pub fn test_case(_attr: TokenStream, input: TokenStream) -> TokenStream {
let f = parse_macro_input!(input as ItemFn); let f_ident = &f.sig.ident; let q = quote!( #f inventory::submit!( utils::TestCase( concat!(module_path!(), "::", stringify!(#f_ident)).to_string(), #f_ident ) ); ); q.into() } Attributeを実装する TokenStreamをItemFnとしてparse 失敗したらコンパイルエラー attributeの名前を関数名にする 関数(check()やfail())が展開される
pub struct TestCase(pub String, pub fn() -> ()); inventory::collect!(TestCase); #[macro_export]
macro_rules! run_inventory_tests { () => { utils::test_start(); let mut ntestcases: u64 = 0u64; let mut failurecases: Vec<String> = Vec::new(); for t in inventory::iter::<utils::TestCase>.into_iter() { utils::test(&mut ntestcases, &mut failurecases, t.1, &t.0); } utils::test_end(ntestcases, failurecases) }; } #[test_case] attrを付与した関数を集める submit!した関数たちを集めてくる utils::test内でt.0を実行する
custom attributesを使ってみる use utils::{test_case, run_inventory_tests}; #[test_case] fn check() { let
x = 1; assert_eq!(x, 1); } #[test_case] fn fail() { let x = 1; assert_eq!(x, 2); } fn main() { run_inventory_tests!(); } attrを設定 attrを設定 main関数内でテストを実行
`cargo test`ではなく、`cargo run`でテストを実行する 関数名(checkやfail)も出力できた
• Procedural macrosと通常のマクロを紹介 • Procedural macrosでよく利用される3つマクロたち ◦ proc_macroで、Procedural macrosが有効になる ◦
synで、文字列からRustコードに構文解析する ◦ quoteで、synのデータ構造からRustコードに変換し直す • Custom Attributeを実装した ◦ 自分でも動かしたい!という方は以下にソースコードを公開してます。 ◦ https://github.com/cipepser/rust-custom-attribute まとめ
References • proc_macro - Rust https://doc.rust-lang.org/proc_macro/ • O'Reilly Japan -
プログラミングRust https://www.oreilly.co.jp/books/9784873118550/ • Procedural Macros - The Rust Reference https://doc.rust-lang.org/reference/procedural-macros.html • D - マクロ - The Rust Programming Language https://doc.rust-jp.rs/book/second-edition/appendix-04-macros.html • proc_macro2 - Rust https://docs.rs/proc-macro2/1.0.18/proc_macro2/ • syn - Rust https://docs.rs/syn/1.0.31/syn/ • quote - Rust https://docs.rs/quote/1.0.7/quote/ • inventory - Rust https://docs.rs/inventory/0.1.6/inventory/ • Procedural Macros に入門していたずらしてみた - Don't Repeat Yourself https://yuk1tyd.hatenablog.com/entry/2018/12/25/192041 • Procedural macros 雑入門 - slideship.com https://slideship.com/users/@statiolake/presentations/2019/07/CZ9wX4Zi8R93MhxN7jRBK5/?p=2
ブロックチェーン技術をもとに、「新たな経済基盤」をつくりだす。 それは、信用や評価のあり方を変え、 業務や生産をはじめとした経済活動の摩擦を解消し、 この国の課題である生産性向上を実現する。 私たちは、そう信じて行動し続けます。 ブロックチェーンが実装された社会、 そこには、これまでの延⻑にはないまったく新しい可能性が広がっている。 LayerXは、デジタル社会への発展を後押しすることで、 経済史に新たな1ページを刻んでいきます。