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
Goのコンパイラをみてみよう 〜iotaを通じて〜 @MCCMMANCC 2019 / div...
Search
kosui
December 22, 2019
450
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Goのコンパイラをみてみよう 〜iotaを通じて〜 @MCCMMANCC 2019 / dive into go complier with iota
kosui
December 22, 2019
More Decks by kosui
See All by kosui
PdMのためのソフトウェアエンジニアリング入門
kosui
0
210
品質とスピードを両立: TypeScriptの柔軟な型システムをバックエンドで活用する
kosui
8
3.4k
更新”しない”ドキュメント管理 「イミュータブルドキュメントモデル」の実運用
kosui
19
6.1k
Featured
See All Featured
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
790
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
64
56k
Utilizing Notion as your number one productivity tool
mfonobong
4
540
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
530
The SEO identity crisis: Don't let AI make you average
varn
0
530
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
430
Game over? The fight for quality and originality in the time of robots
wayneb77
1
240
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
Bash Introduction
62gerente
615
220k
Leo the Paperboy
mayatellez
8
2.1k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
390
Transcript
Goのコンパイラをみてみよう 〜iotaを通じて〜 MCC 2013年⼊部 株式会社ディー・エヌ・エー 岩佐幸翠
⾃⼰紹介 岩佐 幸翠 (@uniuniunicode) 農⼯⼤ 修⼠課程(情報⼯学)を今年春に卒業 株式会社ディー・エヌ・エー タクシー配⾞アプリ「MOV」のチームに所属 GAE・Go・TypeScriptをやっています
突然ですが 皆さんの好きな⾔語はなんですか Go Ruby Python TypeScript C++ Java Kotlin Swift
Haskell etc...
今⽇伝えたいこと コンパイラのコードを読む⾯⽩さ コンパイラのコードを読むことで、普段何気なく使っている⾔語機能がどのように実装さ れているか知ることができる
コンパイラに興味を持ったきっかけ Goの⾔語機能の⼀つ「iota」の不思議な仕様が気になった でも、既存のドキュメントやブログには詳しい話は書かれていない ➡ ⾃分でコンパイラのコードを読んで調べてみよう!
⽬次 1. iota とは 2. iota の不思議 3. Goコンパイラ gc
の流れ 4. Goコンパイラ gc のコードを追ってみよう
Goの定数の宣⾔ Goでは以下のように定数を宣⾔する // 1 つの定数を宣⾔ const Answer int = 42
// 複数の定数を宣⾔ const ( BadRequest = 400 Unauthorized = 401 Forbidden = 403 NotFound = 404 ) const ( Alice = "alice" // "alice" Bob // "bob"... ではなく "alice" Charlie // "alice" )
iota とは 定数に連番を割り振る機能 type Direction int // Direction の型をint へalias
// iota 無し const ( Up Direction = 0 Down = 1 Left = 2 Right = 3 // いちいち書くのつらい... ) // iota 有り const ( Up Direction = iota // 0 Down // 1 Left // 2 Right // 3 )
iota とは iota のカウンタは const が現れるとリセットされる const ( A int
= iota // 0 B // 1 C // 2 ) const ( D int = iota // 3 ... ではなく 0 ! E // 1 F // 2 )
iota とは 演算を含めることもできる const ( mono int = iota +
1 // 1 di // 2 tri // 3 tetra // 4 )
iota のまとめ 定数を宣⾔する時、連番を⽣成してくれる const が出現する度にカウンタが0に戻る ➡ つまり iota は状態を持っている iota
クイズ iota とは... 1. 定数である 2. 関数である 3. マクロである 4. オブジェクトである
iota クイズのこたえ iota とは... 定数である 関数である マクロである オブジェクトである これマジ?
iota の不思議 なぜ定数であるはずの iota から、どんどん連番が出てくるのか? どうやって const が出現する度に0にリセットする⽅法を実現しているのか?
Goのコンパイラのコードを読んで iotaの不思議を解き明かしましょう! 「定数の宣⾔」と iota が、コンパイラにどのように扱われるのかを追います
Goコンパイラ gc の流れ Goコンパイラにも複数あるが、今回はそのうちの1つ gc の話 今⽇話すのは以下⿊字のみ 1. syntax パッケージ
1.1 ソースコードから字句リストへ 1.2 字句リストを構造化する 2. gc パッケージ 2.1 構造化されたソースコードからASTを⽣成 2.2 型チェック 2.3 SSA(中間表現)へ変換 3. ssa パッケージ 3.1 SSAを最適化する 3.2 機械語を⽣成
Goコンパイラ gc の流れ ASTとは プログラムの構⽂構造を⽊構造で表現したもの gc では型チェックのために使われる
コンパイラの流れ: 1.1 ソースコードから字句リストへ分割 1. syntax パッケージ 1.1 ソースコードから字句リストへ 1.2 字句リストを構造化する
2. gc パッケージ 2.1 構造化されたソースコードからASTを⽣成 2.2 型チェック 2.3 SSA(中間表現)へ変換 3. ssa パッケージ 3.1 SSAを最適化する 3.2 機械語を⽣成
コンパイラの流れ: 1.1 ソースコードから字句リストへ分割 ファイルごとに、ソースコードを左から右へ線形に解析し、 最⼩の意味単位(トークン)ごとに分割する ➡ ここはiotaとは関係なさそう
コンパイラの流れ: 1.2 字句リストを構造化する 1. syntax パッケージ 1.2 字句リストを構造化する 1.1 ソースコードから字句リストへ
2. gc パッケージ 2.1 構造化されたソースコードからASTを⽣成 2.2 型チェック 2.3 SSA(中間表現)へ変換 3. ssa パッケージ 3.1 SSAを最適化する 3.2 機械語を⽣成
コンパイラの流れ: 1.2 字句リストを構造化する ASTへの変換がしやすいように前処理
コンパイラの流れ: 2. 構造化されたソースコードからASTを⽣成 2. gc パッケージ 2.1 構造化されたソースコードからASTを⽣成 1. syntax
パッケージ 1.1 ソースコードを字句リストへ分割 1.2 字句リストを構造化する 2.2 型チェック 2.3 SSA(中間表現)へ変換 3. ssa パッケージ 3.1 SSAを最適化する 3.2 機械語を⽣成
コンパイラの流れ: 2. 構造化されたソースコードからASTを⽣成 File 構造体の declList に格納されていた importDecl , funcDecl
, constDecl , varDecl を、それぞれASTのノードを表す構造体 Node へ変換する type Node struct { // Tree structure. // Generic recursive walks should follow these fields. Left *Node Right *Node Ninit Nodes Nbody Nodes List Nodes Rlist Nodes // ...
コンパイラの流れ: 2. 構造化されたソースコードからASTを⽣成 なんと、 Node 構造体は、⾊々な⽤途の値を格納してしまう XOffset というプロパティを持 っている //
Various. Usually an offset into a struct. // ... Xoffset int64 また、 Node 構造体が持つ SetIota 関数は XOffset にiotaの値を代⼊する func (n *Node) SetIota(x int64) { n.Xoffset = x } ➡ この関数がどこから呼ばれているか調べれば良さそう
カウンタをリセットする犯⼈ 犯⼈: declList 内のconstDeclをASTに変換する処理 最後に処理したconstDeclとGroupが違う場合はiotaのカウンタがリセットされる type constState struct { group
*syntax.Group // 最後にNode へ変換されたconstDecl のGroup // ... iota int64 } func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node { // 最後に処理したConstSpec と今処理しているConstSpec の // Group が異なる場合はiota のカウンタをリセットする if decl.Group == nil || decl.Group != cs.group { *cs = constState{ group: decl.Group, } } // ... cs.iota++ return nn }
まとめ iota iota は定数だけど連番を返したりリセットされたりする iota のカウントを進める処理・リセットする処理はASTの⽣成時に⾏われる iota のロジックはコンパイラのコードにめちゃくちゃゴリゴリ実装されている やっていくぞ Goのコンパイラのコードはわりときれいで読みやすいのでおすすめ
コンパイラのコードを読んで、すぐに何かに役に⽴つことはないけれど、 技術的関⼼を持って⾃分の知⾒を広げることは楽しい