タイトルの通り、コンパイラを作り始めました。
先日、 転職のお知らせ にも書いたのですが、低レイヤーを勉強していきたいとここ最近考えていました。
正直、僕が考えていた低レイヤーというのは、AWS上でインフラを構築できるようになることやRDBのチューニングでした(前職ではアプリケーションのコードを書くこと以外、あまり気にしなくてよかったのでこのへんをやりたかった)。
しかし、会社の同僚の方たちと飲んでいるときに、エモい低レイヤーの話を聞き、ちょっとやってみるか!という気持ちになったのでコンパイラを作り始めてみました。
作っているもの
9ccというCコンパイラを作っています。
Cを書いた経験はなく、けっこう苦しいところもあります...
Cコンパイラとは、C言語で書かれたプログラムをアセンブリ言語に変換するものです。
例えば 5+20-4
の場合、以下のようなアセンブリを出力します(僕の現時点のコードでは)
.intel_syntax noprefix .global main main: push 5 push 20 pop rdi pop rax add rax, rdi push rax push 4 pop rdi pop rax sub rax, rdi push rax pop rax ret
9ccという名前を聞いて、ピンと来る方もいるかもしれませんが、8cc や 9cc 作者の Rui Ueyama さんが書かれている 低レイヤを知りたい人のためのCコンパイラ作成入門 を参考にしながら(現時点ではほぼ写経しながら)作っています。
実装が完了しているもの
- 足し算、引き算
- 空白を含む足し算、引き算
- 加減乗算、優先順位のカッコを含む計算
- 単項プラス、単項マイナス
と、書いてもよくわからないと思うので、テストコードを見てもらうのがわかりやすいです。
tryという関数に期待値と入力値を渡し、実際の結果が期待値と一致するかをチェックしています。
try {期待値} {入力値}
# 整数1個だけコンパイルできる try 0 0 try 42 42 # 足し算、引き算対応 try 21 '5+20-4' # 空白対応 try 41 ' 12 + 34 - 5 ' # 加減乗算と優先順位のカッコからなる式に対応 try 47 '5+6*7' try 15 '5*(9-6)' try 4 '(3+5)/2' # 単項プラスと単項マイナス try 5 '-10+15' try 15 '14+-(-7)-(+6)'
地道にやっていく感じですね。 できることが増えてくると面白いです。
実装中の箇所
- 比較演算子 (
==
!=
<=
>=
)- ちょっとハマっている...
これから実装すること
- ファイルを分けて分割コンパイルできるようにする
- 変数、関数に対応
基本、 低レイヤを知りたい人のためのCコンパイラ作成入門 に沿って実装していく予定です。
挫折しなければ😂
最後に
APIなどのアプリケーションのコード書くのとは全然違いますが、ちょっと楽しいので地道に続けていきたいです。
そして、いつかGoでGoのコンパイラ作ってみたいです