Windows専用の言語処理系のひとつに、HSPというものがある。
HSPの機能のいくつかは、月の裏側から集めてきたらしい。不要とわかって捨てられたものを、わざわざ復活させている。たとえばC言語風のマクロだ。私見では、#defineと#ifdefは手動メモリ管理に次ぐ害悪だ。Stroustrup『C++の設計と進化』540ページより引用する:
マクロの定義は、環境の中や、コンパイラのディレクティブ、ヘッダファイルなど、いろんなところに潜んでいる。マクロによる置換はスコープという境界ルールを無視し、それどころか、勝手にブレースや引用符を挿入してプログラムのスコープ構造を変えてしまうこともある。(中略)その機能はあまりにも構造性を欠き侵略的なので、プログラマやメンテナ、コードを移植する人、ツールの作者などにとってつねに頭痛の種だった。
しかしHSPは当たった。同種のWindows専用の言語処理系のなかで、一番の大当たりになった。
なぜ当たったのか? 私はこういう世界とはまったく縁がないので、説得力のある意見をとりあえず信じることにする。私の知るかぎり、もっとも説得力のある説明は、以下のとおりだ。
「インストーラ抜きの配布物がEXEファイル1個になる。それが本物っぽくて、いい」
VBの配布物はEXEファイル1個にはできない。ランタイムが必要だ。Perlは、PARを使えばEXEファイル1個にすることはできるが、PARを使うにはかなりの知識が要る。その点、最初の最初から「本物っぽい」配布物が得られるHSPは、人をひきつけたのだ――配布物がEXEファイル1個になるのが「本物っぽい」と感じるような初心者を。
初心者がなにを「本物っぽい」と感じるかは、なかなかわからない。彼らはカーゴ・カルトの世界にいる。
初心者でなくなるのは簡単だ。慣れればいい。だが慣れるだけではカーゴ・カルトからは抜け出せない。信仰しているカーゴ・カルトが、「ベスト・プラクティス」という名前になるだけだ。
『本物のプログラマはPascalを使わない』というあのエッセイは、そこの機微をよく捉えている。このエッセイによれば、本物のプログラマはFORTRANを使うのだという――FORTRANは当時のカーゴ・カルトだったのだろう。EXEファイル1個の配布物が「本物」であることと、FORTRANが「本物」であることのあいだには、大した違いはない。
さて、今日の本題に入ろう。ネイティブ・コンパイラ(ネイティブに実行可能なバイナリ・ファイルを生成するコンパイラ)を信仰するカーゴ・カルトについて。
基本を確認しよう。
C言語のコンパイラはC言語で書ける。C言語で書かれたCコンパイラは、自分自身をコンパイルできる。
問題は、最初の実行だ。世界で初めてC言語の処理系を書いたのなら、ご愁傷様だ――手作業でなんとかするしかない。だが、ほかにC言語の処理系がすでに存在していて使えるなら、手作業は必要ない。
さて応用である。
JITコンパイル型のJava VMは、自分自身を実行できる。
事の本質はCコンパイラとなにも変わらない。「最初の実行」という問題が、VMを起動するたびに起こるだけだ。なんらかの方法で起動しさえすれば、あとはVMが自分自身を実行する。起動方法としては、インタプリタ型のJava
VM(速度は非常に遅くていい)などが考えられる。そしてその起動用VMも、FORTHインタプリタのような極小のVM上で動かすことができる。最小限のFORTHインタプリタは非常に簡単に書けるので、アセンブラさえいらないくらいだ。
高度な動的最適化は、理論上も現実にも、コンパイル時最適化をしのぐ。ある程度以上のメモリのある環境なら、ネイティブに実行可能なバイナリは、BIOSとブートローダとカーネルのごく一部にしか必要でない。ネイティブ・コンパイラはほとんど不要だ。
(ただし、ネイティブでないコンパイラは相変わらず必要だ。コンパイル時の型チェックはプログラマを助け、冗長性の低いバイトコードは実行効率を高める)
EXEファイル1個の配布物。FORTRAN。ネイティブ・コンパイラ。
どれも、ある条件のもとでは、ベストな選択だ。だが、その条件を判断する知識が抜け落ちたとき、その選択はカーゴ・カルトになる。
このようなカーゴ・カルトを見分けるキーワードが、「本物」だ。
なにかを選ぶとき、それが「本物」だからという理由で選んではいないか。なにかが確かだと思うとき、その根拠がどこかで「本物」につながってはいないか。
選ばれて「本物」になる。確かだと思われて「本物」になる。だが、その逆は、カーゴ・カルトだ。
>JITコンパイル型のJava VMは、自分自身を実行できる。
これ、何かおかしいと思うのですが。
「Java で書かれ(てバイトコードになっ)た Java VM は~」
の間違いではないでしょうか?
Java VMが解釈するのはJavaの
バイトコードなので、自分自身を実行する
Java VMは当然Javaのバイトコードで
書かれています。
「JIT コンパイル型の Java VM は、全て、自分自身を実行できる」
と読んでしまったので、間違いだと思ってしまったようです。