nFact

n!

自作JVM言語Karaffeについて

nokoです。2014年ぐらいから趣味でKaraffe(カラフェと読みます)という自作のJVM言語を開発しています。

この記事は、Karaffeの開発のきっかけと、何をゴールとしているのか?をまとめます。
細かい実装についてはほとんど触れないのでまた別の機会に。

Karaffeとは

Karaffeは、オブジェクト指向(クラスベース)の静的型付けなプログラミング言語です。
Javaバイトコード(classファイル)を生成するので、Java VMで実行することができます。

実行用のコマンドを持っていないので、生成されたclassファイルをそのままjavaコマンドで実行します。
何回か文法の再設計レベルの書き直しをしており、現在も書き直している最中なので、今は文法チェッカのみ存在します。

Karaffe開発のきっかけ

(おそらく)全てはぱらつり氏のこのツイートから始まりました。

このツイートと、その場の雰囲気のノリと勢いでPaLTreeというOrganizationが作られました。 色んな人がいてワイワイと開発やら議論をしていました。(確認したらメンバーは9人も居ました。意外と多かった。。)

Karaffeの前身 = notepad-java

PaLTreeでは「メモ帳言語(notepad-lang)」という枠で様々な実装が出てきました。その中で、notepad-langをJavaで実装したのが私でした。(Javaの他にC#Rubyによる実装がありました)

メモ帳でも書けると言っても普段の環境と違いすぎてあんまりピンと来ないかもしれませんが、現代のプログラミングでは当たり前となっている機能がありません。 例えば、シンタックスハイライトや補完はもちろん、オートインデントも無いのでインデントをしようものならTabやSpaceを連打する必要があります。 なので、インデントやハイライトが無くとも読みやすく、補完なしで全部手打ちしても記述が可能である必要がありました。

その結果生まれたのが、インタプリタにより実行するシンプルな(?)手続き型言語でした。 メモ帳で記述することを前提に考えられていたのと、コンパイラインタプリタも開発したことが無い中での設計だったので、とても奇抜な仕様が爆誕したのは言うまでもありません。

notepad-javaが持っていた仕様の中でも、他のメモ帳言語にも無い一番ユニークだった仕様は「{}や()を使っても入れ子になるとメモ帳だと読みにくいので、改行2つでブロックを直列的に構成する」という仕様だったと思います。

このあたりを記した当時のドキュメントは、現在のnokok/Karaffeには入っていません。 動的言語/静的言語、静的型付け/静的型付け、インタプリタやら何やらを混同したような記述が多数あり、かつ実装もほぼ無く恥ずかしいのでここには載せません。

notepad-langから派生したり、触発されて開発されたプログラミング言語の中で、現在まで開発が続いているのはKaraffeのみです。 他にはLuryというプログラミング言語がありますが、現在開発が休止しているようです。

Karaffeの誕生

手続き型 -> 関数型言語っぽいものにするか? -> やっぱオブジェクト指向だな、という迷走試行錯誤を経て今の形になりました。 この試行錯誤の過程で、notepad-javaは早々にKaraffeという名前になりました。
Karaffeになった頃にはメモ帳の要素は薄まり、だんだん自分が作りたい言語に寄ってくるようになりました。

Karaffeロゴ
Karaffeロゴ
このKaraffeのロゴは、コーヒーがカラフェに貯まって揺らいでいる様子を表現しています。(本来カラフェにコーヒーは入れないような気もするのですが気にしないようにします)

Karaffeが目指しているもの

Karaffeは、Javaにはまだ存在しない現代的な文法や仕様を取り入れながら、よりシームレスなJavaとの相互運用性を実現することを第一に目指しています。

(主語が大きい気がしますが)既存のJVM言語は「JVM言語からJavaを使うこと」は考えていても、「JavaからそのJVM言語を使うこと」はあまり前提とされていない感じがしています。真の 相互 運用性を考えたときに「対象のライブラリがJava製なのか他のJVM言語製なのか」を考えなくても良いというのが理想像ではないかと考えています。 Karaffeが吐き出すクラスファイルやjarファイルが、(たとえKaraffeにしか無い言語仕様を使ったとしても)Karaffe製であることが言われないと分からないレベルにまで、Javaにとって極力自然なものとなるように作るというのが今の所の方針です。

そもそもKaraffeのような個人開発の言語は、普及して一般の人にまで使ってもらえることは通常考えにくいと思っています。既存の言語を置き換える意図もありません。なので、あくまで自分だけが使う(普段使っている)Javaと組み合わせることを前提とした高度な相互運用性を持つ言語にしたいと思ったのもあります。

Karaffeはだいぶ後発の言語なので、Javaのモジュールシステムにネイティブで対応したいなぁとか色々ありますが、まずは相互運用性が第一で、他は二の次、三の次です。とりあえずはシンプルなオブジェクト指向言語にできればと思っています。

Karaffeの今

今のKaraffeは多分5回目ぐらいの書き直しをしたバージョンです。 「ぐらい」と言ったのは、それだけ何回も失敗して書き直しているために覚えてないからです。 今のバージョンになったのは2018年11月です。半年弱ですね(今回は歴史ごと飛ばして書き直しましたのでfirst commitです) first commit · nokok/Karaffe@0d62de1 · GitHub

夢はでかいのですが、コンパイラを開発できるレベルの知識もなければ実装力も全然ついてきてないので、書き直した実装の中でまともに動作するものを作り出せた試しがありません。 まだまだ絵に描いた餅状態なので、どうにかしていきたい感じですね。

初期のバージョンはJavaCCとか色々使ってましたが、今はレキサ/パーサーにANTLRv4を使用しています。
この記事はこのぐらいにしておきつつ、今後はKaraffeのことをもっと書いていきたいと思います。