私は現在、楽しみのために新しいプログラミング言語の実装に取り組んでいます。ほとんどの言語が普及することは決してないことを私は理解していますが、それでも言語に高品質の実装を持たせたいと思っています。言語は大まかにLISPに似ています。クロージャ、ファーストクラスの継続、同像性構文、ファーストクラスの関数などをサポートします。さらに、言語がすでに確立されているライブラリコード(具体的にはJava)にアクセスできるようにしたいです。 =標準ライブラリなど)。
JVMバイトコードへの動的コンパイルは、それをサポートするように設計されていない仮想マシンを使用して、指定された機能セット(ファーストクラス関数を除く)を実装するのが難しいため、本質的に問題外です。一方、C/C++またはその他の低レベル言語にコンパイルすると、プラットフォームへの依存度が望ましくない場合や、Java standard)を使用する機能が低下/削除されます。私の言語で書かれたプログラムを介したライブラリ。
実装に対する私の(ほぼ完成した)アプローチは、Javaでカスタムpコードインタープリターを実装することです。高水準言語は、コードをオンザフライでコンパイルして、基本的にこのカスタム仮想マシンの命令の配列にします。各命令は、共通のインターフェースを実装するオブジェクトです。実行されると、命令はスタックマシンを操作します。残念ながら、各命令を実行するには仮想メソッド呼び出しが必要です。一方、このようなインタープリターの通常の実装では、オブジェクトベースの命令は使用されません。ただし、現在のマイクロベンチマークと推測ベースの推定値は、同等のプログラムが与えられた場合、完成した実装がPythonの速度と一致する必要があることを示しています。
言語の設計目標を考えると、この実装方法はクレイジーまたはアマチュア的だと思いますか?
どうしますか?
あなたが提案することは、一般的に健全なアプローチのようです。命令ごとのオブジェクトは少し重いかもしれませんが、特にそれが扱いやすい設計である場合は、それから始められない理由はありません。
現時点ではバイトコードへのコンパイルは問題外であると提案していますが、それは後でいつでも追加することを決定できます。一部のコードを解釈して残りのコードをコンパイルするランタイム環境を作成できます(LISP環境はそれを永遠に実行しており、JITコンパイラーは今日もそれを実行し続けています)。
常に複数の言語の実装が存在する可能性があることに注意してください。 C++は、Cの上にプリプロセッサであるCfrontとして最初に実装されました。初期のJVMは常にバイトコードを解釈していましたが、現在ではほとんどすべてがJITです。 Pythonには複数の実装があり、そのうちのいくつかは可能な場合はネイティブマシンコードにコンパイルされます。
JVMバイトコードへの動的コンパイルは、それをサポートするように設計されていない仮想マシンを使用して、指定された機能セット(ファーストクラス関数を除く)を実装するのが難しいため、本質的に問題外です。
JVMバイトコードにコンパイルされる、すでに説明した機能のほとんどをサポートする言語はたくさんあります(JRuby、Scala、Clojure)。これらの言語の実装はオープンソースであるため、JVMにこれらの機能を実装する際のアプローチを検討することをお勧めします。
しかし、あなたが述べた目標は楽しいので、他の言語のコンパイラー実装を調べることは、あなたが始めたいことではないと想像できます。
JVMにプログラミング言語を実装した私の経験では、プログラミング言語は簡単に機能しますが、特にテスト用のおもちゃのプログラムよりも少し多くのデータを突然使用した場合のパフォーマンスとメモリ消費に関して、いくつかの荒削りな部分があります。