Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
明日の私を救う proc_macro
Search
kiokuless
September 24, 2025
38
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
明日の私を救う proc_macro
kiokuless
September 24, 2025
More Decks by kiokuless
See All by kiokuless
Cloudflare Tunnelを使ってMinecraftサーバを公開する
kiokuless
0
330
Featured
See All Featured
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
450
Game over? The fight for quality and originality in the time of robots
wayneb77
1
310
The SEO identity crisis: Don't let AI make you average
varn
0
590
AI Search: Where Are We & What Can We Do About It?
aleyda
0
8.1k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
270
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
1
280
From π to Pie charts
rasagy
1
400
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
68
59k
The Pragmatic Product Professional
lauravandoore
37
7.5k
First, design no harm
axbom
PRO
2
1.3k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
990
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Transcript
明日以降の私を恐らく救うと思う proc_macro による DSL 実装 明日の私を救う proc_macro - kiokuless 1
こんにちは〜 明日の私を救う proc_macro - kiokuless 2
自己紹介 kiokuless と申します フリーランスのエンジニア 趣味: パソカタ ファミコンのソフトウェアエミ ュレータ実装をやっている 明日の私を救う proc_macro
- kiokuless 3
ファミコンのエミュレータ CPU APU PPU カートリッジ ... 明日の私を救う proc_macro - kiokuless
4
ファミコンのエミュレータ => 今日は CPU の話だけ 明日の私を救う proc_macro - kiokuless 5
導入 #[test] fn test_adc_immediate() { let mut cpu = CPU::new();
// LDA #$50 ; A = 0x50 // ADC #$30 ; A = A + 0x30 = 0x80 let program = vec![0xa9, 0x50, 0x69, 0x30]; cpu.load_and_run(program); assert_eq!(cpu.register_a, 0x80); assert_eq!(cpu.get_carry(), 0); assert_eq!(cpu.get_negative(), 1); } 明日の私を救う proc_macro - kiokuless 6
バイト列で命令思い出すの辛い let program = vec![ // LDA #$50 ; A
= 0x50 0xa9, 0x50, // ADC #$30 ; A = A + 0x30 = 0x80 0x69, 0x30 ]; ファミコンで使われた 6502 の機械語はとても簡単な構造 命令は 1-3 バイトで決まっている オペコードを見るとオペランドの見るべきバイト数が定まる コメントや関数名でまあわかるけど・・・ -> なんか イケてない 明日の私を救う proc_macro - kiokuless 7
実現したいこと let program = asm![ LDA imm 50; // 厳密に言うと6502
" 風" の命令になっている ADC imm 30; CLC ]; 明日の私を救う proc_macro - kiokuless 8
実現したいこと let program = asm![ LDA imm 50; // 厳密に言うと6502
" 風" の命令になっている ADC imm 30; CLC ]; LDA で即値 50 を A レジスタに代入 ADC で即値 30 を A レジスタに += CLC で carry フラグをオフにする( 命令トークンの長さは 1-3) 明日の私を救う proc_macro - kiokuless 9
実現したいこと let program = asm![ LDA imm 50; // 厳密に言うと6502
" 風" の命令になっている ADC imm 30; CLC ]; LDA で即値 50 を A レジスタに代入 ADC で即値 30 を A レジスタに += CLC で carry フラグをオフにする( 命令トークンの長さは 1-3) => めっちゃ見やすくなった 明日の私を救う proc_macro - kiokuless 10
最初は macro_rules! で... macro_rules! asm { ($($tokens:tt);*) => { vec![
$(instruction!($($tokens)*)),* ] }; } macro_rules! instruction { // パースして構造体に変換... } ここで大ハマり 明日の私を救う proc_macro - kiokuless 11
問題は ; (セミコロン) macro_rules! instruction { ($($token:tt)*) => { ...
}; } LDA 0x80; NOP; みたいなコードをパースしようとすると... 明日の私を救う proc_macro - kiokuless 12
明日の私を救う proc_macro - kiokuless 13
問題は ; (セミコロン) macro_rules! instruction { ($($token:tt)*;) => { ...
}; } LDA 0x80; NOP; みたいなコードをパースしようとすると... コンパイラが混乱! 「 ; って、token-tree の一部?それともマクロの区切り文字?」 => パースの曖昧性が発生する 明日の私を救う proc_macro - kiokuless 14
tt とかいう フラグ指定子 が強すぎ・・・ Qiita: Rust のマクロを覚える - k5n 明日の私を救う
proc_macro - kiokuless 15
対処法? [] / () / {} で命令毎にを囲む asm![ (LDA 0x80)
(CLC) (NOP) // ... ] 明日の私を救う proc_macro - kiokuless 16
対処法? [] / () / {} で命令毎にを囲む asm![ (LDA 0x80)
(CLC) (NOP) // ... ] => 絶対にやりたくない こんなのやるくらいなら人間デコンパイラになるほうがマシ 明日の私を救う proc_macro - kiokuless 17
declarative macro じゃ無理!! macro_rules! asm { // こういうやつ // ...
} 明日の私を救う proc_macro - kiokuless 18
対処法をググった 明日の私を救う proc_macro - kiokuless 19
これだ!!!!!!!!!!!!! 明日の私を救う proc_macro - kiokuless 20
proc_macro に手を出す [lib] proc_macro = true 注意: マクロの定義/ 実装をするだけの Cargo
workspace を別に用意 する必要がある 明日の私を救う proc_macro - kiokuless 21
実装と結果 pub struct AsmInput { pub asm: Vec<InstructionInput>, } //
セミコロン区切りで残りの命令を解析 while input.peek(Token![;]) { input.parse::<Token![;]>()?; // セミコロンを消費 // セミコロンの後に何もない場合は終了 if input.is_empty() { break; } // 細かい1 命令単位のパースは InstructionInput に任せる asm.push(input.parse::<InstructionInput>()?); } 明日の私を救う proc_macro - kiokuless 22
結果は... Before: vec![0xA9, 0x01, 0x8D, 0x00, 0x02] // ??? After:
asm!( LDA imm 0x01; // 即値1 をA レジスタに読み込み STA abs 0x0200 // $0200 番地に保存 -> エンディアンも気にしなくていいぞ!!! ) 明日の私を救う proc_macro - kiokuless 23
ここまで聞いたみなさんの気持ちを エスパーします 明日の私を救う proc_macro - kiokuless 24
「CPU なんて実装しないし・・・」 「アセンブリ自作しないし・・・」 明日の私を救う proc_macro - kiokuless 25
proc_macro の威力はこれだけじゃない Rust 上で手書きだと面倒なオブジェクト、なんでも簡潔に書けるよう になります AST (抽象構文木) ast!(if x >
0 { return x } else { return -x }) グラフ構造 graph!(A -> B -> C; A -> C; B -> D) 明日の私を救う proc_macro - kiokuless 26
まとめ 「毎回同じような構造を手書きしてる... 」と思うことありませんか? それ、proc_macro で解決できるかもしれません 明日の私を救う proc_macro - kiokuless 27
まとめ 「毎回同じような構造を手書きしてる... 」と思うことありませんか? それ、proc_macro で解決できるかもしれません いま Claude Code に勝ちたいなら †Rust
のマクロの理解度† で挑め!!!!!!! 明日の私を救う proc_macro - kiokuless 28