LLVMでForthを動かしてみた - 初めての言語処理系実装

ここ最近趣味として、LLVM を使って Forth 処理系を実装するというのをやっていました。ようやく一区切り(ここまではやりたい)と思っていたものができたので、コードを公開しつつブログを書いてます。

本編は英語でどうぞ

本質的に書きたい内容は英語で Medium および Wiki に書いてしまったので、そちらをご覧下さい。

落ち穂拾い

Low-Level Programming マジオススメ

この本がなければ LLForth はできなかった。x86_64 を理解したい人だけでなく、そもそもコンピュータってどうやって動いてるの?というのを理解するのに激しくオススメ(といいつつまだ読了してない) Amazon.com のリンクをどうぞ。

Forth 面白い

すごくシンプルな仕組みなのに、Colon words のおかげでいくらでも自然に拡張できる。でも仕組みがシンプルなので実装はそこまで難しくない(もちろんどこまで本気でやるかに依存するが)。超単純な stack machine として計算機程度を実装するだけだと、1 日もかからずにできてしまって面白くないけど、辞書をやろうとするとそこそこいいボリュームになると思うのでオススメ。僕は 2 ヶ月くらいでここまでできました。

そんなことより、スペースシャトルでも使われてたとか、そういうのにワクワクしませんか?!

C++17 いいけど C++はやっぱり辛い

今回生まれて初めて C++11 を使ってみて、autolambda最高だなと感じました。ついでに C++17 に途中で変えて、std::variantstd::optionalも使ってみて、他の言語で普通にやってることが自然にできるようになってきたなぁとは感じました。

とはいえ、pattern matching が無いのはやっぱり書きづらいなと感じるし、print debug のために operator めっちゃ定義するのとかだるいし、積極的に使いたいとはまだ感じられなかった。今回のように LLVM API が C++で提供されるみたいな理由が無い限り。(もちろん他の言語 binding はあるのは知ってるけど、一番資料が豊富な C++を使っていなかったら、そもそも API も知らない状態では完成できなかった。)

Rust はとても興味深い

たまたま Rust にも手をだしたけど、とても良い。何がいいって、まずrustupcargoのおかげで環境構築〜プロジェクト開始に全くつまづかないし選ぶ必要もない。それから、言語的にはメモリ管理を本当に大切にしていて、僕の浅はかな CS 知識ではコンパイルが全く通らない。でも、コンパイルを通すまでの過程で、なるほどここは確かにまずいな、というのを修正できるのはとても気持ちが良い。システムよりな何かを書くなら、次は間違いなく Rust を選択しますね。

FFI 楽しいけど辛い

FFI を通して Rust で作ったライブラリを LLVM や C++から呼び出す実装もしました。確かに C のインタフェースを実装すれば自由に呼び出せるのはいいと思うけど、C 的な型を取り扱うのが激しく面倒だった。

一方で、なんで今まで触ったことのある FFI がああいう面倒なインタフェースになってるのかがよーく理解できたのはとても良かった。例えば、create/destroy がなぜ必要なのかとか。最初は Rust 上でlazy_static使って保持しようとしてたんだけど、どう考えても Rust と相性が悪すぎだった。以下のブログが最高でした。

まとめ

LLVM から Rust まで学べて、俺得でした。みなさんも Forth 処理系の実装おもしろいのでぜひ。

次は、データベースの実装でもやってみようかなぁ。