ブートストラッピングの中で起きた問題と解決策

一か月ほど本業に専念していましたが、Rowlの開発を再開しました。
結構忘れているところがあるので、これまでの経過をまとめます。

これまで実装したものの一覧は下図。

問題1: 機能不足

アセンブリ言語で実装したrowl0は機能が貧弱すぎて、次のステップで一気に高級な機能の実装をするのは大変でした。型推論クロージャの実装は途中までやって断念。

そこで、コンパイラ実装用の内部用インタプリタ言語を作成することにしました。インタプリタコンパイラに比べはるかに実装が容易なので、少ない労力で高級な機能を実現できます。S式を用いると非常に容易にインタプリタを作成でき、さらにメタプログラミングも容易にできます。3000行程度で書いたインタプリタで、かなり高級な記述が出来るようになりました。例えば、後で述べるVMのインストラクション定義から、VM本体のeval loopやディスアセンブラの定義を自動生成する等といった事ができるようになりました。

問題2: バックエンドの実装労力が多い

内部用インタプリタで内部用コンパイラを作る訳ですが、レジスタ割り当てやスケジューラの実装はかなり面倒です。そこでスタックマシン型のVMを作成しました。スタックマシン用の命令列は構文木をイテレートしつつ直接生成できるので、実装が大変楽になります。また、ブートストラッピングの世代が進んでもしばらくはこのVMを再利用できます。

後々の事を考えて、このVMにはGCを実装しておきました。

問題3: メモリ不足

内部用インタプリタは実装をサボっていて、ヒープメモリを使い捨てています。従って、それで実装された内部用コンパイラはメモリ不足の為大きなファイルをコンパイルできません。そこで、rowl1のコードを分割コンパイルできるようにする必要があります。そして、そのためにはリンカを作成する必要がありました。現在は主に、このリンカの機能追加中。

問題4: デバッグ

処理系が大きくなって来たらデバッグを考え始めなければなりません。とりあえず、ディスアセンブラを作成しました。コンパイラVMデバッグ用のディスアセンブラが、同コンパイラコンパイルされ同VM上で動くという点がブートストラッピングならではの面白さかもしれません。そのうち、デバッガも作らなければならなくなるはずなんですが、大変すぎるのでしばらくはディスアセンブラのみで乗り切ろうという感じです。