手っ取り早く実用的なプログラミング言語を作るために

何でもかんでも自分で一から作っていると人生が何回あっても足りない。なので、ありものをいかに活用していくかが重要となる。

この記事では、プログラミング言語を作る上で既存の資産を活用することについて考えてみたい。

続きを読む

バイトコードVMのための調査

LunarMLの今年の目標に「REPLとインタープリターを実装する」というのがある。これまではLunarMLをLuaやJavaScriptをターゲットとするコンパイラーとして実装してきたけど、

  • REPLによるインタラクティブな実行
  • 書いたSMLコードを直接実行(一旦LuaやJavaScriptコードを生成するのではなく)

できると嬉しいよね、という話だ。(REPLを備えたStandard ML処理系は色々あるが、LunarMLとコンパチブルなREPLが欲しければ自分で作るしかない。)

つまりインタープリターだが、構文木を走査するインタープリターは遅そうだ。効率的な実行のためには、バイトコードとVMを設計したい。

バイトコードへのコンパイラーはSMLで、VM(ランタイム)はSMLによる実装とC言語による実装の両方を用意することをイメージしている。

C言語による実装を用意することで、高速な実行が期待できるだけではなく、「コンパイル済みバイトコード+C言語で書かれたランタイムによるbootstrap問題の解決」もできる。つまり、現状の「LunarMLを動かすためにはSMLコンパイラーが必要」という状態から「CコンパイラーまたはSMLコンパイラーがあればLunarMLが動く」という状態にできる。

ではバイトコードと抽象機械はどうやって設計するか?

続きを読む

C言語でクロージャーを実現したい、あるいは実行時のコード生成によるクロージャー

導入:クロージャーについて

昨今ではクロージャーを使えるプログラミング言語は珍しくなくなった。クロージャーとは、関数の引数だけではなく、外のスコープにある変数を参照できる関数のことである。

例えば、次のJavaScriptコードでは、関数を返す関数 f を定義している。 f の中で定義された無名関数は、外側の変数 x を参照できている。

function f(x) {
    return function(y) {
        return x + y;
    };
}

JavaScriptではネストした関数を使わなくても、bindメソッドによって同等の処理を記述することができる:

function g(x, y) {
    return x + y;
}
function f(x) {
    return g.bind(null, x); // gの第1引数を束縛する
}

残念ながらC言語にはクロージャーはない。関数の中に関数を書けないからだ。

しかし、クロージャーと同等のこと、つまり関数に追加の引数を渡すことはできないのだろうか?

続きを読む

LunarMLが自身をコンパイルできるようになった

LunarML進捗報告、号外です。前回の記事

からそんなに時間が経っていませんが、「自分自身をコンパイルできるようにする」という重要なマイルストーンを達成したので報告します。

続きを読む