言語実装用言語

Cが使われるのはたまたまでしょうねえ。Lispのcarとcdrの語源を考えれば、Lispももともとハードウェアに非常に近いところを記述できる言語でもあったわけです。Smalltalkのat:やat:put:だって、ArrayやByteArrayはCの"[]"と大差ないですし。

小さなブートストラップ用の処理系は書いた上で、後は全部自分自身で書くというのは、まともな記述力を持った言語なら昔から当然行われてきたことではあります。まともな記述力というのは、コンパイラとか構文木とか実行系とかの要素がその言語自身のデータとして扱えるということなので、CとかRubyとかは外れてしまいますが、LispSmalltalkとかということになるでしょうか。ML系の関数型言語もその線に載っているものが多いと思うのですが、実行している自分自身を変えるときの自由度が小さい(たぶん)という問題はありますね。自分自身の言語で書かれているというだけならCだってCコンパイラは普通Cで書きますが、とてもじゃないけどコンパイル実行中のプログラムが使っているデータ構造が見えるわけはないですからね。

最初のSmalltalkはBasicで書かれたわけですが、その後の変更は基本的には歴代のSmalltalk内で行われてきたわけですし、Lisp-70はS式の書き換え規則だけでバイナリにまで落としてしまうというものでした。Cが使われるのは、OSのAPIがCのものが多いということと、みんなが力を入れて最適化をがんばった歴史があるということですね。Squeak VMSqueakで書かれていますが、CへのトランスレータSqueakで書かれていて、それをコンパイルして実行します。いろいろなOSに移植することを考えると、Cが一番ポータビリティがあるのは間違いないと思いますが、「Cで書く」必要は特にないですね。

Cokeも、小さなブートストラップ用のIdStコンパイラ(idc)はC++で書かれていますが、"stage 2"のidcはIdStで書かれていますし、Jolt以降は命令列を生成してメモリに書き込んで実行するところまでCokeで書かれています。ABIは、Cの関数が呼べるようにCokeの関数呼び出し規約はCのものを使うようになっていますが、そこも本質的ではないです。