公開技術情報

[English] [Japanese]

A. トランスコンパイラ開発のすゝめ

LuneScript 入門のアドベントカレンダー最後の記事は、 これまでとは趣向を変えてトランスコンパイラ開発そのものについて扱っていきます。

トランスコンパイラ開発をすゝめる理由

私は LuneScript というトランスコンパイラを開発しています。

この開発を通して、エンジニアとして良い経験が出来たと感じています。

なお、LuneScript を開発した理由については次の記事に書いています。

../reason

私は次の理由からトランスコンパイラ開発を 多くの方に経験して欲しいと思い、この記事を書くことにしました。

  • 現状に対する不満を建設的に解決できる
  • トレンドの技術を確認できる
  • コーディングルールを矯正できる

以降では、上記の各項目を説明していきます。

現状に対する不満を建設的に解決できる

皆さんは、今のソフトウェア開発に対して不満を持っていませんか?

  • 上司が気にいらないとか、
  • 開発 PC の性能がショボいとか、
  • 給料が安いとか、
  • 残業が多いとか、

私が言っている「不満」は、 上記のソフトウェア開発を取り巻く「現実社会への不満」では なく

ソフトウェア開発を行う上で、 頭の中にあるアイデアを実現するのに

  • 言語仕様上バグり易いとか、
  • もの凄く手間のかかる面倒な書き方しか出来ないとか、
  • 実現するために必要なユーティリティ的なものを一から作らなければならず、 本来作りたいものに辿り着く前に時間が掛り過ぎるとか、
  • そもそも言語仕様的に実現できないとか、

そういった、プログラム言語に対する不満です。

そのような不満がある人で、 その不満を解決するための具体的なアイデアがある人には、 トランスコンパイラを開発することを薦めます。

私自身、トランスコンパイラを開発しようと思った一番の理由はこのためです。

「無いなら自分で作れば良い」

アイデアをソフトウェアで実現出来る能力を持っているからこそ 「ソフトウェアエンジニア」ではないでしょうか?

「コンパイラ」ではなく「トランスコンパイラ」である理由

『なんで「コンパイラ」じゃなくて「トランスコンパイラ」なの?』 と疑問に思う方もいるかもしれません。

それは、「トランスコンパイラ」の方が「コンパイラ」を作りよりも 技術的なハードルが低いためです。 LLVM の登場で、以前と比べればコンパイラ開発のハードルは下っているとは思いますが、 それでもトランスコンパイラの方がまだまだハードルは低いです。

特に、コンパイルした後のコードにバグがあった時の「原因追求コスト」は、 トランスコンパイラの方が圧倒的に低いです。

コンパイラを作ること自体が目的であればそれでも良いとは思いますが、 コンパイラを作ること自体は手段であり、 あくまでも目的は「プログラム言語に対する不満」を解決することです。

出来るだけコストを掛けずに実現できる方が良いでしょう。

それに、「プログラム言語に対する不満」の多くは、 トランスコンパイラで解決できることがほとんどです。

もちろん「コンパイル時間をもっと短くしたい」というような不満には、 コンパイラを自前で開発しなければならないと思いますが、 それ以外のほとんど不満はトランスコンパイラで解決できるでしょう。

最終的なゴールが、コンパイラを作ることであったとしても、

  • まずはトランスコンパイラを作成し、
  • 不満を解決できていることや、言語としての使い易さを実証し、
  • そのトランスコンパイラを使うことが有益であることが確認でき、
  • その後、直接ネイティブへのコンパイルが必要になってから

最終的にコンパイラを開発するのが、効率の良い方法と言えるでしょう。

「インタプリタ」ではなく「トランスコンパイラ」である理由

「コンパイラ」ではない理由は上述しました。

ここでは、「インタプリタ」ではない理由を説明します。

と、言っても理由は「コンパイラ」の時と変らずに、 「インタプリタ」よりも「ハードルが低い」からです。

インタプリタを作るのは、コンパイラよりはハードルが低いです。 私自身、簡易的なインタプリタは何度か作った経験があります。

しかし、実用的なインタプリタとなると話は別です。 実用的なインタプリタとなると、 開発工数的な問題と、実行性能的な問題があります。 コンパイラの時にも書きましたが、 「プログラム言語に対する不満」を解決するのが目的なので、 それ以外のことは一旦考えないでおきましょう。

今は実用的なインタプリタ型の言語(スクリプト言語)が世の中にいくつもあります。 わざわざ自前で作る必要はないでしょう。

出力結果が分かり易い

コンパイラと比べてトランスコンパイラの方が良いこととして、 「トランスコンパイラの出力コードは多くの人にとって分かり易い」ことが 挙げられます。

コンパイラが出力した「ネイティブコード」と、 トランスコンパイラが出力した「とある言語のコード」、 どちらが分かり易いかと言えば、「とある言語のコード」の方が分かり易いのは 誰もが認めるところでしょう。

「じゃぁなんで分かり易い方が良いんだ?」というと、 導入リスクがそれだけ低いということです。

新しい技術をプロジェクトに導入する際、 それが「安全」かどうかを判断する必要があります。

単に「安全」と言っても、色々な観点があります。

  • ウイルス的なものが入り込んでいないことを保証する「情報セキュリティ」
  • 海外に輸出可能か、「外為法」の対象かどうか
  • ライセンス的に問題ないか。 そのコンパイラの作者が作成した部分のライセンスは問題なくても、 作者が意図せずに使用しているコードにライセンス上の問題がないか

他にも新しいものを導入するには、幾つかの安全性をクリアする必要があります。

これらの安全性をクリアする際、その対象技術の分かり易さは非常に重要です。

コンパイラの場合、 生成されたネイティブコードを調べるのは現実的ではないため、 コンパイラのコードを調査して安全性を確認することになります。

一方トランスコンパイラは、 ライセンスと変換後のコードを調べれば良いだけです。

トレンドの技術を確認できる

せっかく新しいトランスコンパイラを開発するのであれば、 できるだけ使い勝手の良いものを作ろうと思うのがエンジニアの性分でしょう。

であれば、さまざまな言語の特徴を調査して、 良いものを取り込むのが常套手段です。

私も LuneScript を開発するにあたり、なるべく多くの言語を調査し、 さまざまな機能を取り込んだつもりです。

さまざまな言語の特徴を知ることに何の意味があるのか? 例えば普段 C 言語のプロジェクトしか関わりのないエンジニアが Go や swift の特徴を知ることに意味があるのか? そのようなことを疑問に思う人もいると思います。

普段から Qiita 等のサイトで自ら新しい情報を収集しているような人ならば、 そのようなことを疑問に持つことはないと思いますが、 そうでない場合は疑問に思う人は少なくないでしょう。

私は、例え普段 C 言語のプロジェクトしか関わりのないエンジニアであっても、 イマドキの言語の特徴は把握しておくべきだと思います。

それは、イマドキの言語の特徴そのものは C 言語では使えないとしても、 考え方や、エッセンスなどは C 言語でも導入可能だからです。

例えば、関数型言語の考え方自体は、 Haskell を使わなくても C 言語でも実現できます。

もちろん、C 言語の syntax だと書き難いモノや、 C 言語の仕様上実現できないモノなども存在します。

しかし、関数型言語の考え方自体を知った上で、敢えて C 言語らしく書くことと、 C 言語しか知らないからいつも通りに C 言語で書くことは、違います。

また、イマドキの言語の特徴をトランスコンパイラの機能として取り込むには、 単にイマドキの言語を使うよりも、より深い理解が可能になります。 というか深い理解がなければ取り込むことは出来ません。

このように、イマドキの言語の特徴の理解を深めるためにも トランスコンパイラの開発は経験として良いものだと言えます。

コーディングルールを矯正できる

これは、いままで挙げた内容と少し方向性が違いますが、 自分としては結構重要だと思った点です。

皆さん、コーディングする際、 「こう書きたい」「こう書くべき」というような理想の書き方を持っていると思います。

トランスコンパイラを開発するということは、 コーディングルールを言語レベルで矯正(強制)できる、ということでもあります。

この説明だと「どういうこと?」と疑問に持つ方も多いと思いますが、 python の「インデントによるブロック」と言えば通じると思います。

python は、 ブロックをキーワードや区切り記号ではなく、インデントによって表現します。

つまり、「ブロックはインデントすべき」ということを コーディングルールで縛るのではなく、 Python では「インデントが揃っていないとブロックとして扱わねぇよ」と 言語レベルで矯正(強制)している訳です。

コーディングルールで論争が起ることは少なくありません。 独自にトランスコンパイラを開発すれば、 言語レベルでそのような無駄な論争を防げます。

自分でトランスコンパイラを開発するまではあまり意識していませんでしたが、 普段意識しているコーディングルールの中でも、 別の言語では言語レベルで実施できないから不要になっているルールというものが いくつかあることが分かりました。

新しい言語を開発する際は、新しい機能を取り入れるだけでなく、 普段のコーディングルールを見直し、言語レベルで対応できないか検討するべきだと思います。

最後に

これまでに、 簡易的なインタプリタや、ソースコードタグシステム 等を趣味で作ってきました。

今回 LuneScript 開発を通して、 また一つソフトウェア開発の面白さを実感できました。

「いまさら新しい言語なんて作っても意味はない」、 そう思っている方も多いと思います。少なくとも私はそう思っていました。

しかし、今回 LuneScript を開発することで、 また一つソフトウェアエンジニアとして成長出来たと思います。

人がどう思おうが自分で成長を感じることが出来れば、それが一番です。

ソフトウェア開発に対して不満を持っている方は、 是非新しいプログラミング言語の開発にチャレンジしてみてください。