プログラミング言語のインタープリタを「ゼロから」作るとしたら、どこまで小さく始められるでしょうか。PlanckForthというプロジェクトが出した答えは、たった1KBの手書きELFバイナリでした。
このプロジェクトがHacker Newsで話題になっていたので、実際に中身を見てみたところ、コンピュータサイエンスの基礎を学ぶ教材としてもかなり面白い内容でした。今回はその仕組みと魅力について紹介してみます。
PlanckForthの概要 — 究極のミニマリズム
PlanckForthは、nineties氏が開発したオープンソースプロジェクトです。i386 Linux向けの手書きELFバイナリ(わずか1KB)から、完全なForthインタープリタをブートストラップするという試みになっています。
ビルドに必要なのはxxdコマンドだけ。gccもmakeも不要で、16進数ダンプからバイナリを復元するだけで実行可能ファイルが生成されます。この徹底したミニマリズムが個人的にはすごく好きですね。
Forthとは?スタックベースのプログラミング言語
Forthは1970年代にCharles Mooreが開発したスタックベースのプログラミング言語です。現在のメジャー言語と比べるとかなり異質な見た目をしていますが、組み込みシステムやブートローダーの世界では今でも現役で使われています。
特徴的なのは、すべての演算がスタック上で行われる点。たとえば「3 + 4」を計算する場合、Forthでは「3 4 +」と書きます。逆ポーランド記法(RPN)と呼ばれる表記法で、慣れると非常にシンプルに感じられるようになります。
PlanckForthのブートストラップの仕組み
ブートストラップとは、最小限の機能しかない状態から段階的に機能を追加して、最終的に完全なシステムを構築するプロセスのことです。PlanckForthの場合、以下のような段階を踏んでいきます。
ステージ1:1KBの種(手書きバイナリ)
最初の種となるバイナリには、約30個のプリミティブワード(基本命令)が実装されています。文字の読み書き、メモリ操作、算術演算、条件分岐といった最低限の機能だけです。
この段階でのHello Worldは kHtketkltkltkotk tkWtkotkrtkltkdtk!tk:k0-tk0k0-Q という暗号のような見た目になります。1文字ずつkeyとtypeで読み書きしている状態ですね。
ステージ2:bootstrap.fsによる自己拡張
ここからが面白いところです。bootstrap.fsというForthスクリプトを読み込ませることで、インタープリタ自身が自分を拡張していきます。文字列処理、制御構造、関数定義といった高レベルの機能が次々と追加されていく様子は、まるで種から木が育つのを見ているようです。
ブートストラップ後のHello Worldは ." Hello World!" cr と、人間が読める形になります。同じインタープリタなのに、自己拡張によってまったく違う姿に変わるわけです。
PlanckForthから学べること
実用的なプロジェクトではありませんが、リバースエンジニアリングやコンパイラの基礎を学ぶには最適な教材だと感じました。特に以下の概念を実際に手を動かして理解できる点が素晴らしいですね。
- ELFバイナリフォーマットの構造
- スタックマシンの動作原理
- ブートストラップの概念と実装
- 自己拡張システムの設計
Ghidraのようなリバースエンジニアリングツールを使う際にも、バイナリフォーマットの基礎知識があると理解が深まります。PlanckForthはその入門として最適なサイズ感だと思います。
他の言語での実装も用意されている
PlanckForthのリポジトリには、手書きELFバイナリ版の他にC言語版やPython版も用意されています。手書きバイナリがハードルが高いと感じる場合は、まずC版やPython版から始めるのも良い選択です。
ベンチマークも公開されており、各実装のパフォーマンス比較ができるようになっています。当然ながら手書きバイナリ版が最速で、言語処理系のオーバーヘッドの大きさを実感できる良い比較材料ですね。
まとめ
PlanckForthは「プログラミング言語のインタープリタはどこまで小さく始められるか」という問いに対する美しい回答です。1KBという極限のサイズから完全なForthインタープリタが立ち上がる過程は、コンピュータサイエンスの面白さを凝縮したようなプロジェクトだと感じました。
実用性はありませんが、低レベルプログラミングに興味がある方には非常に刺激的な題材になるはずです。参考になれば幸いです。
