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
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
550
layerx-fde-practices
cipepser
6
3.3k
NIKKEI Tech Talk#38
cipepser
0
1.2k
LayerXにおけるFDEについて
cipepser
4
3.4k
20250725-bet-ai-day
cipepser
4
670
Criterion-rs
cipepser
0
180
Practical Anonify
cipepser
2
920
Move for Libra written in Rust
cipepser
2
3.4k
How IBLT Works
cipepser
0
270
Other Decks in Technology
See All in Technology
SREとQA 二人三脚で進めるSLO運用/sre-qa-slo
sugitak
0
360
環境凍結という Toil を倒す -セルフサービス型 Ephemeral テスト環境の 設計と実践
shirouz
1
2.2k
最適な自走を最小限の支援で — M&Aで拡大する組織で少人数SREが挑んだ1年 / SRE NEXT 2026
genda
0
980
Oracle Exadata Database Service on Cloud@Customer X11M (ExaDB-C@C) サービス概要
oracle4engineer
PRO
2
8.4k
AWS Blocks を触ってみた/first-tach-aws-blocks
fossamagna
2
160
生成AIの活用/high_school2026
okana2ki
0
120
はじめてのWDM
miyukichi_ospf
1
140
DMM.com 購入改善推進チーム におけるCodeRabbitを用いた レビューフロー改善の一例
ysknsid25
2
590
クラウド上のデータ復旧で見落としがちな制約: 医療系 SaaS の BCP 設計から得た教訓
kakehashi
PRO
0
3.2k
ボーイスカウトルールでメモリやスキルを改善しよう
azukiazusa1
1
280
Kaggleで成長するために意識したこと
prgckwb
1
200
オブザーバビリティ、本当に活用できてる? 〜API連携×生成AIで成熟度を自動評価〜
dmmsre
1
2.8k
Featured
See All Featured
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
WENDY [Excerpt]
tessaabrams
11
38k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.6k
Google's AI Overviews - The New Search
badams
0
1.1k
Agile that works and the tools we love
rasmusluckow
331
22k
Designing for Timeless Needs
cassininazir
1
290
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.4k
Exploring anti-patterns in Rails
aemeredith
3
440
How to train your dragon (web standard)
notwaldorf
97
6.7k
Thoughts on Productivity
jonyablonski
76
5.2k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
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ページを刻んでいきます。