Slide 1

Slide 1 text

コンパイラを つくってみよう @DQNEO (ドキュネオ) builderscon 2019.8

Slide 2

Slide 2 text

コンパイラ書いてみたいと 思ったことありますか?

Slide 3

Slide 3 text

本日のゴール ● 「コンパイラやってみよう!」 と思ってもらうこと

Slide 4

Slide 4 text

はじめに ● 今日はライブコーディングをします ● フルスクラッチでコンパイラ作ります ● 失敗したらごめんなさい ○ (成功したら拍手お願いします)

Slide 5

Slide 5 text

はじめに ● 文字が見づらい場合は教えてください ○ 特に後部座席の方 ● タイポ/エンバグしてたら教えてください

Slide 6

Slide 6 text

はじめに ● 手が震えてたらそれは仕様です

Slide 7

Slide 7 text

今日つくるコンパイラ

Slide 8

Slide 8 text

今日つくるコンパイラは 履歴つきで公開しています https://github.com/DQNEO/HowToWriteACompiler

Slide 9

Slide 9 text

今日つくるコンパイラ(環境) ● ターゲット環境: ○ Linux ○ x86-64: 一般的なPCのCPU (Intel, AMD) ○ アセンブリ(GNU Assembler)を吐く

Slide 10

Slide 10 text

今日つくるコンパイラ(仕様) ● 足し算引き算をコンパイルできる ● 結果の数値でexit ○ 例 ‘ 30 + 12 ‘ → 42 でexit ● ソースコードを標準入力から受け取る ● アセンブリを標準出力に吐く

Slide 11

Slide 11 text

ゴール 30 + 12 .global main main: movq $30, %rax movq $12, %rcx addq %rcx, %rax ret ソース言語 ターゲット言語 足し算は実行時に行う

Slide 12

Slide 12 text

使用する言語 ● Go言語で書く ○ slice, map, for-rangeなどが便利 ○ 標準ライブラリが便利 ● 何言語で書いてもよいです

Slide 13

Slide 13 text

つくってみよう!!

Slide 14

Slide 14 text

素のアセンブリを 書いて実行 STEP 0

Slide 15

Slide 15 text

CPU内にある超高速な一時記憶装置 CPU ← レジスタ レジスタ 出典: http://ftp.procmail.org/~sskulrat/Courses/2006F-170/lectures/chap14/part1.html

Slide 16

Slide 16 text

自作スクリプトの説明

Slide 17

Slide 17 text

Goプログラムから アセンブリを吐く STEP 1

Slide 18

Slide 18 text

標準入力から ソースコードを受け取る STEP 2

Slide 19

Slide 19 text

現状確認 ソース コード アセンブリ ほぼ仕事してない

Slide 20

Slide 20 text

ソースコードを 「解釈」 するとは

Slide 21

Slide 21 text

3つの視点 全てはByte列 全てはトークン列 全ては構造

Slide 22

Slide 22 text

I say I write a compiler この英文をどう解釈するか?

Slide 23

Slide 23 text

I say I write a compiler “I” “ “ “s” 0x49, 0x20, 0x73... ByteReaderさん

Slide 24

Slide 24 text

I say I write a compiler “I”, “say”, “I” ... Tokenizerさん(字句解析)

Slide 25

Slide 25 text

I say I write a compiler say I write a compiler 文 文 Parserさん(構文解析) I 主語 動詞

Slide 26

Slide 26 text

-12 ソースコード

Slide 27

Slide 27 text

ByteReaderさん Byteが 3個並んでいる 0x2d 0x31 0x32 - 1 2 -12

Slide 28

Slide 28 text

Tokenizerさん - 12 演算子トークン 数値トークン トークンが 2個並んでいる -12

Slide 29

Slide 29 text

Parserさん 単項演算子 数値リテラル式 式の中に式がある 12 - 単項式 -12

Slide 30

Slide 30 text

それぞれのフェーズの成果物 ソースコード バイト列 トークン列 文法構造(式・文) バイト列 トークン列

Slide 31

Slide 31 text

コード生成さん 文法構造 (式・文) 文法構造を アセンブリに変換 アセンブリ

Slide 32

Slide 32 text

Unix パイプのように連携 ソース コード アセンブリ

Slide 33

Slide 33 text

Token分割する STEP 3

Slide 34

Slide 34 text

現状確認 ソース コード トークン列

Slide 35

Slide 35 text

Parse (構文解析)する STEP 4

Slide 36

Slide 36 text

数値リテラル式 STEP 5 42 int literal expression

Slide 37

Slide 37 text

現状確認 ソース コード アセンブリ

Slide 38

Slide 38 text

単項式 (Unary Expression) STEP 6 1 - operand operator unary expression

Slide 39

Slide 39 text

二項式 (Binary Expression) STEP 7 30 + left operator binary expression 12 right

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

この勢いで1万行書けば、 コンパイラ自身を コンパイルできる!

Slide 42

Slide 42 text

自己紹介 @DQNEO ドキュネオ ● アメリカ版メルカリを開発しています ● 趣味でGoコンパイラ自作 https://github.com/DQNEO/minigo

Slide 43

Slide 43 text

minigoの最初の7コミットを 丁寧に再現したのが 今日の内容です https://github.com/DQNEO/HowToWriteACompiler

Slide 44

Slide 44 text

コンパイラを書けると何がいいのか ● プログラミング言語が動く仕組みがわかる ● 既存のコンパイラが読めるようになる ● コンピュータの動きがチョットわかる

Slide 45

Slide 45 text

コンパイラづくり最大の壁 ● 「はじめ方がわからない」 →  これを解決したかった

Slide 46

Slide 46 text

まずつくってみよう ● 学ぶ → つくる ではなく ● つくりながら学ぶ を提唱したい ○ 私はそうやって学んだ (8ccの写経・移植) ○ 今なら chibicc がオススメ

Slide 47

Slide 47 text

よくある誤解 ● C言語で書く必要がある → 何言語のコンパイラを何言語で書いても OK ● 特殊な拡張・ライブラリが必要 → 不要 ● コンピュータ・サイエンスの知識がいる → なくても始められる

Slide 48

Slide 48 text

参考資料: Cコンパイラ https://github.com/rui314/8cc https://github.com/rui314/chibicc Sip Special thanks to rui さん

Slide 49

Slide 49 text

まとめ ● コンパイラの学び方 ● 字句解析、構文解析の初歩 ● フルスクラッチからコンパイラを書きました

Slide 50

Slide 50 text

コンパイラはいいぞ

Slide 51

Slide 51 text

ご清聴 ありがとう ございました