コンパイラをつくってみよう / How to make a compiler

7b606c5039f083d13e2d2320ce6ddcfa?s=47 DQNEO
August 30, 2019

コンパイラをつくってみよう / How to make a compiler

Builderscon 2019 の発表資料です。
ライブコーディングでフルスクラッチでコンパイラを書くというのをやりました。

コンパイラのソースコードはこちらです
https://github.com/DQNEO/HowToWriteACompiler

7b606c5039f083d13e2d2320ce6ddcfa?s=128

DQNEO

August 30, 2019
Tweet

Transcript

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

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

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

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

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

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

  7. 今日つくるコンパイラ

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

  9. 今日つくるコンパイラ(環境) • ターゲット環境: ◦ Linux ◦ x86-64: 一般的なPCのCPU (Intel, AMD)

    ◦ アセンブリ(GNU Assembler)を吐く
  10. 今日つくるコンパイラ(仕様) • 足し算引き算をコンパイルできる • 結果の数値でexit ◦ 例 ‘ 30 +

    12 ‘ → 42 でexit • ソースコードを標準入力から受け取る • アセンブリを標準出力に吐く
  11. ゴール 30 + 12 .global main main: movq $30, %rax

    movq $12, %rcx addq %rcx, %rax ret ソース言語 ターゲット言語 足し算は実行時に行う
  12. 使用する言語 • Go言語で書く ◦ slice, map, for-rangeなどが便利 ◦ 標準ライブラリが便利 •

    何言語で書いてもよいです
  13. つくってみよう!!

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

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

  16. 自作スクリプトの説明

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

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

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

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

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

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

  23. I say I write a compiler “I” “ “ “s”

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

    Tokenizerさん(字句解析)
  25. I say I write a compiler say I write a

    compiler 文 文 Parserさん(構文解析) I 主語 動詞
  26. -12 ソースコード

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

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

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

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

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

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

  33. Token分割する STEP 3

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

  35. Parse (構文解析)する STEP 4

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

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

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

    expression
  39. 二項式 (Binary Expression) STEP 7 30 + left operator binary

    expression 12 right
  40. None
  41. この勢いで1万行書けば、 コンパイラ自身を コンパイルできる!

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

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

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

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

  46. まずつくってみよう • 学ぶ → つくる ではなく • つくりながら学ぶ を提唱したい ◦ 私はそうやって学んだ (8ccの写経・移植)

    ◦ 今なら chibicc がオススメ
  47. よくある誤解 • C言語で書く必要がある → 何言語のコンパイラを何言語で書いても OK • 特殊な拡張・ライブラリが必要 → 不要

    • コンピュータ・サイエンスの知識がいる → なくても始められる
  48. 参考資料: Cコンパイラ https://github.com/rui314/8cc https://github.com/rui314/chibicc Sip Special thanks to rui さん

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

  50. コンパイラはいいぞ

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