連鎖性言語を作る11

原因がまったく想像できない難解なバグに遭遇した場合、怪しいところから調べるのではなく、当たり前に大丈夫なはずのところから本当に大丈夫であることを確定していくほうが結果的に速く原因に辿り着けることがある。急がば回れという話だが、真剣におかしいところが不明な時はどこか見落としがあるはずで、見落とすということはそれはつまり大丈夫だと思い込んでいる場所なわけなので、このアプローチはそれなりに正しい。
という前振りとはぜんぜん関係ないのだが、言語を(というか実際にやっているのは言語処理系を)作るのもやったことないことの塊なので、地道にひとつひとつ積み上げて、それが可能なこと、それから問題が発生するなら解決法の模索を、踏みしめるようにじっくりと進めることが大切である。言語処理系開発の疑似体験とでも言おうか。この経験が今後何かに生きるとも思えないし、このシリーズの記事が誰かの役に立つともイマイチ思えないのだが、まあ、これが趣味なので。
ということで今回は地味に半歩ほど進める感じで、Rubyからオレ言語を呼び出すインターフェイスを考える。

アプリ組み込み

スクリプト言語は、という区分でいいのかどうかはよくわからないが、例えばRubyはクラス定義もメソッド定義も実行時に行われる。これは、例えばCの構造体宣言のように、コンパイル時にサイズや相対位置などが全て解決されて実行ファイルになる頃には構造体のコの字も残っていないような、ネイティブにコンパイルする言語とは根本的に違って、バイトコードコンパイルしようがどうしようが、それらを定義する命令がVMに存在し、それを実行したときに定義される(っていうか生成されて定数に格納される)。RubyをCに変換するようなプログラムがもしあったとしても、Rubyは動的なので、Class.newでクラスを実行時に作ることもできるし、すべてを静的なコードに落とすことは原理的に不可能である。と思う。たぶん。知らんけど。
mrubyなどはアプリ組み込みもやりやすいように作られているが、提供される組み込みクラス、メソッドがすべてCで実装されているわけではなく、Rubyで書かれたものもあり、それらはバイトコードとしてライブラリに組み込まれ、VMインスタンス生成後に実行されて、定義される。アプリ組み込みをする場合はそこから更にアプリ用のクラスやメソッドの定義用バイトコードを実行してVMをセットアップし、そのVMインスタンスでアプリの設定コードなどを実行する、という形になる。

オレ言語では

Rubyから呼び出す、というのはすなわちRubyアプリに組み込む、という話と同義で、VMインスタンスを生成してオレ言語で書かれたシステムレベルワードを定義する必要があり、更にユーザの定義コードを実行してセットアップしたVMインスタンスに対して、何かしらの操作をする、という感じになる。
そう考えると今の作りでもVMインスタンスがあれば別にASTを渡せば追加で実行できるし、特にやることも無いような気がしないでもない。

別の切り口

アプリ組み込みとは別の考え方もある。例えばJRubyJVMで動作するRubyだが、Javaとは相互の接続が可能となっている。すなわち、Javaで書かれたライブラリをJRubyから呼び出すことができるし、JRubyで書かれたライブラリをJavaから呼び出すこともできる。
同様に、オレ言語で書かれた機能(=ワード)をRubyから自然に呼び出すことができると嬉しい。今後もしオレ言語がちょーすげーサイコーな使いやすい言語になったならば、これでライブラリを書いてRubyからも自然に使えればそれはすばらしいことである。しかし自然に使えるというのはたぶんRubyのメソッドとして呼べるような形であり、VMインスタンスを必要とする形は理想的ではない。つまりこの方向での最終的な目標はRubyのメソッド定義としてRubyのコードを出力するようなトランスレータ、ということになる。きわめて動的なオレ言語をVMインスタンスをいちいち作らずにRubyのメソッドとして定義することが可能なのかどうか、というのは現状では不明で、これは今後のネタということで。

Quotationが邪魔

レジスタマシン化することなども色々考えてはいるのだが、上記のトランスレータについても同様に、どうもQuotationの存在が壁になる。Quotationは実行可能なデータ(Rubyの配列)であり、これをサポートする限り、どうやっても動的な動作を削除することができない。まあ、Rubyだってevalが存在する限り実行時の処理系からRubyコンパイラを削除することはできないし、それと似たような話である。
難しいから消しちゃおうかなあーとか思ったりもするが、これを無くすとそれはそれで面白みが無くなってしまうので残しておいて、オレ言語toRuby動的トランスレータトランスレータの出力コードに実装するみたいなOpal-parser的な何かを作れるのかどうかみたいな方向で考えていきたい。

おしまい

それにしてもせいぜい100行ちょいのしょぼしょぼ言語なのに処理系を作るのはほんとに大変である。