このすみノート

Webエンジニアが技術や趣味を書くブログです。

Kuin for Web - Kuin言語のJavaScript出力機能と、KuinをKuinでコンパイルするKuinInKuin

この記事は、「write-blog-every-week Advent Calendar 2019」の2日目の記事です。 「write-blog-every-week」は、毎週ブログを書くことを目標としたコミュニティです。

kojirooooocks.hatenablog.com

私がブログを書き始めたのは2017年の8月ですが、アクセスはほぼなく、無名ブログとして運営しておりました。 そんな私のブログに転機が訪れたのは、2年前に書いた 「くいなちゃんのKuinというプログラミング言語が凄い件」という記事が、はてなブックマークの人気エントリー入りしたことです。

www.konosumi.net

くいなちゃんがいなければ、ブログを書くモチベーションは枯渇して、続かなった自信があります。 というわけで、今回はくいなちゃんとKuin言語について書きます。

KuinInKuin

KuinInKuinとは、KuinのコンパイラをKuinで書き直すプロジェクトです。

github.com

KuinInKuinは、単に既存のコンパイラをKuinで書き直すに留まらず、次の根本的な思想があります。

  • 言語仕様や、コアに近いライブラリの互換性は維持する
  • KuinコンパイラをKuinで実装して、いろいろと欲しい機能が明らかになったため追加する
  • これまではWindowsで動く機械語(.exe)しか生成できなかったが、.cpp や .js も生成できるようにして、他のOSやブラウザ上で動くものも作れるようにする
  • 最終的には、Kuinリポジトリにある本家コンパイラを、このKuinInKuinで置き換える

https://github.com/kuina/KuinInKuin/issues/2 より

Kuinは主にWindows向けのゲームプログラミング言語を主戦場としていたのですが、これによってマルチに活躍できる可能性があります。 とてもおもしろい取り組みです。

なお「コンパイラをコンパイルするコンパイラ」という自己完結の仕組みは、珍しいようで実際に起こり得る話です。

コラム: コンパイラをコンパイルするコンパイラ
CコンパイラがCで書かれているといった自己参照的な状況は珍しくありません。C以外でも、数多くの言語実装がその言語自体を使って書かれています。
すでに言語Xの実装がある場合、その言語自身を使って新たなXコンパイラを作ることに論理的な矛盾はありません。セルフホストするためには、単に既存のコンパイラで開発を進めていって、自作のものが完成したらスイッチすればよいだけです。この本で我々が行おうとしているのはまさにその方法です。
https://www.sigbus.info/compilerbook より

Webブラウザ上でコンパイルできるKuinコンパイラ(β版)

現在公開されている「Webブラウザ上でコンパイルできるKuin(β版)」は、KuinInKuinでコンパイルしたKuinのコンパイラを、JavaScriptで出力したものです。

Webブラウザ上で コンパイルできるKuin(β版) - プログラミング言語「Kuin」

IssuesにKuinコンパイラ自体をJSで生成してみて動いていると書いてあるので、おそらくその成果物が稼働していると思われます。

(すでにKuinコンパイラ自体を .cpp や .js で生成してみて動いています。ブラウザ上でKuinコンパイラが動作しました!)
https://github.com/kuina/KuinInKuin/issues/2 より

チラッ…

実装が気になって覗き見しようとしたら、くいなちゃんにばれました。

f:id:konosumi:20191202022947p:plain

本題に戻りますが、「Webブラウザ上でコンパイルできるKuin(β版)」では、テキストエリアに入力したKuinのプログラミング言語がコンパイルされます。 これはWebページに実装されている、JavaScriptを見るとわかります。

# http://kuina.ch/js/kuin_web_ui_20191117.js より
let d = document, src = d.getElementById("src") /* ..続きは省略 */

/** 途中省略 **/

kuin({
    cmdLine: ["-i", "main.kn", "-s", "res/sys/", "-e", target].concat(extra),
    readFile: function(p){
        if(p === "./main.kn") return src.value;
        return null;
    },
    writeFile: function(p, s){ write(p, s, code); },
    print: function(s){ log.value += s; }
});

プログラムを記述するテキストエリアはHTML上で「id="src"」となっており、Kuin関数に渡すオブジェクトのreadFileを経由して中身が渡されます。

本来であればファイルに書かれたKuinのプログラムをコンパイルするのでしょうが、テキストエリアに直接書かれているため、テキストエリアの値(src.value)が使われていることがわかります。

cmdLineの指定は推測ですが、JS上でKuinのコマンドラインの引数指定を表現したものです。 なおコンパイラの指定オプションは、「Kuin言語仕様11」に書いてあります。

Kuin言語仕様11 コンパイラとIDE - プログラミング言語「Kuin」

この指定オプションが、JavaScriptで出力されたKuinコンパイラでも使えるようになると推測されます。

KuinInKuinのJavaScript出力機能を見てみよう

KuinInKuinのソースコードは公開されているため、誰でも見ることができます。 コンパイラのソースコード内にwebディレクトリがあり、そこにJavaScriptの出力機能があると分かります。

compiler内のmain.knを見ると、オプションファイル内の「env_」という変数を利用して、環境によってoutput関数を使い分けていることがわかります。

; 'Output'
switch(\option@env_)
case %cpp
    if(!\cpp\output@output(entry, resFiles.files))
        ret false
    end if
case %web
    if(!\web\output@output(entry, resFiles.files))
        ret false
    end if
default
    assert false
end switch

ソースコードを簡単に理解することは難しいですが、raw_funcs.knを見ると、実際にJavaScriptを生成している過程が垣間見えます。 ここでは「codes.add()」の引数に書かれているのが、実際のJavaScriptであると推測できます。

+func write(codes: list<[]char>, attr: []char, args: list<\ast@AstArg>, members: list<\ast@AstClassItem>)
    switch(attr)
    case "acos"
        do args.head()
        var x: \web\output@WebInfo :: \web\output@getInfo(args.get())
        do codes.add("return Math.acos(\{x.id});\n")
    case "acosh"
        do args.head()
        var x: \web\output@WebInfo :: \web\output@getInfo(args.get())
        do codes.add("return Math.log(\{x.id}+Math.sqrt(\{x.id}*\{x.id}-1));\n")
; 以下、省略

KuinInKuinのソースコードを見るのは楽しそう

このように、KuinInKuinのソースコードを追うのは探究心に溢れており、楽しそうです。 ただしひとつだけ難点があって、ソースコード内にコメントは少ないので、ヒントがあまりありません。

――Kuinコンパイラの迷宮へようこそ。
ここは、読解に挑んだ多くのプログラマが帰らぬこととなった場所です――。
https://github.com/kuina/KuinInKuin より

・・でも、おもしろそうな迷宮であることは確かです。

くいなちゃんは倒されたのか

そう言えば、最近Twitterのくいなちゃんアイコンが変わりました。

twitter.com

くいなちゃんには倒されると次世代に引き継がれる仕組みがあるのですが、倒されたのでしょうか? すでに20期を超えているのですが、地味に気になります。

歴代くいなちゃん
何かしらのきっかけでくいなちゃんが倒されると、次の世代のくいなちゃんに引き継がれる仕組みです。
http://kuina.ch/others/about_kuina より

まとめ

KuinはcppやJavaScriptの生成機能を実装することで、将来的にはMacやブラウザを対象とした、ハイブリッドのプログラミング言語になれる可能性があります。

こんな言語を6歳のくいなちゃんが開発しているわけですから、くいなちゃんはすごい。

write-blog-every-week Advent Calendar 2019

次の「write-blog-every-week Advent Calendar 2019」は、@AquiTCDさんです。

blog.solunita.net