Wikipediaのとおり:A compiled language は、その実装が通常コンパイラー(ソースコードからマシンコードを生成するトランスレーター)であるプログラミング言語です。そして 解釈言語 は、その実装のほとんどが命令を直接かつ自由に実行するプログラミング言語の一種であり、以前にプログラムを機械語命令にコンパイルする必要はありません。
したがって、以下は明らかです。
C, C++ and few other similar languages
-コンパイルされた言語Shell script, Perl, Ruby and some more
-解釈された言語ただし、3種類目の言語もあります。 C#やJavaのような言語は、実行中にコンパイラとJITの両方を使用します。そのため、私の質問は、そのような言語に別の名前があるのですか、それとも上記のタイプのいずれかに分類できるのですか?説明的な答えがより役立つでしょうか?
編集:
ウィキペディアとこれからSO post: Interpreted vs Compiled 明確に定義された言語の実装タイプが2つあることは明らかです。しかし、 2つのカテゴリで十分ですが、すべての言語がこれら2つのカテゴリに収まるか、または3つ目のカテゴリはありますか?
あなたの質問への答え:
すべての言語をコンパイルまたは解釈のいずれかに分類できますか?
「いいえ」ですが、あなたがそう思う理由ではありません。理由は、3つ目の不足しているカテゴリがあるということではありません。理由は、カテゴリ自体は無意味なであるためです。
「コンパイルされた言語」や「解釈された言語」といったものはありません。これらの用語は間違っているわけではなく、無意味です。
プログラミング言語は、抽象的な数学的なルール、定義、および制限のセットです。プログラミング言語はコンパイルまたは解釈されません。プログラミング言語だけare。 [クレジットは Shriram Krishnamurthi に誰が言ったか 9年前のチャンネルのインタビューで(51:37-52:20頃) ]
実際、プログラミング言語はanyインタープリターやコンパイラーがなくても完全に存在できます。たとえば、彼が1930年代に設計した Konrad Zuse の Plankalkül は、生涯を通じて実装されたことはありません。それでも、プログラムを作成したり、それらのプログラムを分析したり、その理由を調べたり、それらのプロパティを証明したりすることができます。実行することはできません。 (まあ、実際、それは間違っています。もちろん、頭の中で、またはペンと紙でそれらを実行できます。)
コンパイルと解釈は、プログラミング言語ではなく、コンパイラーまたはインタープリター(duh!)の特性です。コンパイルと解釈は、プログラミング言語とは異なる抽象化レベルで行われます。プログラミング言語は、抽象的な概念、仕様、一枚の紙です。コンパイラーまたはインタープリターは、その仕様を実装する具体的なソフトウェア(またはハードウェア)です。英語が型付き言語である場合、「コンパイルされた言語」および「解釈された言語」という用語は型エラーになります。 [繰り返しますが、Shriram Krishnamurthiの功績です。]
すべてのプログラミング言語はコンパイラーによって実装できます。すべてのプログラミング言語は、インタープリターによって実装できます。最近の主流のプログラミング言語の多くは、インタープリター実装とコンパイル実装の両方を備えています。最近の主流の高性能プログラミング言語実装の多くは、コンパイラーとインタープリターの両方を備えています。
C用とC++用のインタープリターがあります。一方、ECMAScript、PHP、Python、Ruby、およびLuaの現在の主要な主流の実装には、それぞれコンパイラーがあります。 GoogleのV8 ECMAScriptエンジンのオリジナルバージョンは、純粋なネイティブマシンコードコンパイラでした。 (彼らはいくつかの異なる設計を経ており、現在のバージョンdoesにはインタープリターがありますが、長年、インタープリターはありませんでした。)XRubyとRuby.NETは純粋にコンパイルされましたRuby実装。IronRubyは純粋にコンパイルされたRuby実装として開始され、パフォーマンスを向上させるために後でインタプリタが追加されました。 Opal は純粋にコンパイルされた= Ruby実装。
一部の人々は、「解釈された言語」または「コンパイルされた言語」という用語は、インタープリターまたはコンパイラーによってのみ実装できるプログラミング言語に適用するのが理にかなっていると言うかもしれません。しかし、そのようなプログラミング言語は存在しません。すべてのプログラミング言語は、インタープリターとコンパイラーによって実装できます。
たとえば、第2二村プロジェクションを使用して、インタプリタからコンパイラを自動的かつ機械的に導出できます。これは、1971年の論文で 二村良彦教授 によって最初に記述されました 計算プロセスの部分評価-コンパイラ-コンパイラへのアプローチ(日本語) 、 英語版 の28年後に再発行されました。インタプリタに関して部分的なエバリュエータ自体を部分的に評価することで 部分的な評価 を使用し、コンパイラを生成します。
しかし、このような高度な学術的変換がなくても、機能的にコンパイルと区別がつかないものを作成することができます。つまり、インタープリターをプログラムにバンドルして、単一の実行可能ファイルに解釈するだけです。
別の可能性は、「メタJIT」のアイデアです。 (これは、二村プロジェクションと精神的に関連しています。)これは、たとえばRPythonフレームワークでプログラミング言語を実装するために使用されます。 RPythonでは、言語のインタープリターを作成すると、RPythonフレームワークがプログラムを解釈している間にインタープリターをJITコンパイルして、その1つのプログラムしか解釈できない特別なコンパイル済みバージョンのインタープリターを生成します。そのプログラムのコンパイルと区別がつかない。したがって、ある意味では、RPythonは動的にインタープリターからJITコンパイラーを生成します。
逆に言えば、最初にプログラムをコンパイルしてから直接実行するラッパーにコンパイラーをラップして、ラップされたコンパイラーをインタープリターと区別できないようにすることができます。実際、これはScala REPL、C♯REPL(Monoと.NETの両方で)、Clojure REPL、インタラクティブGHC REPL 、および他の多くのREPLが実装されています。これらのREPLは、1行/ 1つのステートメント/ 1つの式を受け取り、コンパイルして、すぐに実行し、結果を出力します。このコンパイラとの対話モードはsoと区別できません一部の人々は実際に「解釈されたプログラミング言語」であるとはどういう意味かを定義する特性として、プログラミング言語のREPLの存在を使用します。
ただし、インタープリターなしではプログラムを実行できないことに注意してください。コンパイラは、プログラムをある言語から別の言語に単に変換するだけです。しかし、それだけです。これで、言語が異なるだけの同じプログラムができました。 onlyプログラムの結果を実際に取得する方法はinterpretです。時々、言語は非常に単純なバイナリマシン言語であり、インタープリターは実際にはシリコーンでハードコードされています(これを「CPU」と呼びます)が、それはまだ解釈です。
実装の大部分がインタプリタである場合、プログラミング言語を「インタプリタ型」と呼ぶことができると言う人もいます。さて、非常に人気のあるプログラミング言語ECMAScriptを見てみましょう。 ECMAScriptには、すぐに使用できる、広く使用されている高性能のメインストリーム実装がいくつかあり、[すべて1つ]には少なくとも1つのコンパイラが含まれ、場合によっては複数のコンパイラも含まれます。したがって、この定義によれば、ECMAScriptは明らかにコンパイルされた言語です。
インタプリタ、JITコンパイラ、AOTコンパイラの違いの違いとさまざまな手段を説明するこの私の答え と この答えはAOTコンパイラ間の違いを扱っています)およびJITコンパイラ 。
is言語を分類することは可能implementationsある程度まで。一般的に、
Withinコンパイラーのグループ。コンパイラーが実行されるときに時間的な違いがあります。
そして、インタープリターとコンパイラーを組み合わせる、または複数のコンパイラーを組み合わせる、または(よりまれに)複数のインタープリターを実装する実装があります。いくつかの典型的な組み合わせは
しかし、まだ他にもあります。一部の実装では、コンパイラーとインタープリターの代わりに2つのコンパイラーを使用して、混合モードエンジンと同じ利点を得ます(たとえば、最初の数年間は、V8はこのように動作しました)。
RPython はバイトコードインタープリターとJITを組み合わせますが、JITはユーザープログラムをコンパイルせず、ユーザープログラムを解釈しながらバイトコードインタープリターをコンパイルします。その理由は、RPythonは言語を実装するためのフレームワークであり、このようにして、言語の実装者はバイトコードインタープリターを作成するだけで、無料でJITを取得できるからです。 (もちろん、RPythonの最も有名なユーザーは PyPy です。)
Truffleフレームワーク は言語にとらわれないASTを解釈しますが、同時にspecializes自体を特定のASTに変換します。これはコンパイルのようなものですが、そうではありません。最終結果は、Truffleが言語固有の情報をあまり知らなくても、コードを非常に高速に実行できることです。 (Truffleは言語実装の汎用フレームワークでもあります。)ASTは言語に依存しないため、同じプログラムで複数の言語を混在させて一致させることができ、Truffleは言語間で最適化を実行できますRubyメソッドをECMAScript関数にインライン化するなど。
Macrosとeval
は、不可能コンパイルできる機能として引用されることがあります。しかし、それは間違っています。マクロのコンパイルには2つの簡単な方法とeval
があります。 (コンパイルの目的のために、マクロとeval
は互いに多少二重であり、同様の手段を使用して処理できることに注意してください。)
eval
の場合、インタープリターをコンパイル済みプログラムまたはランタイムサポートライブラリに埋め込みます。eval
の場合は、コンパイラをコンパイル済みプログラムまたはランタイムサポートライブラリに埋め込みます。私たちが知識を深めているのであれば、どの言語も原則としてコンパイラーまたはインタープリターのいずれかで実装できるため、コンパイルされた言語や解釈された言語などはありません。ただし、ほとんどの言語は比較的一貫した実装戦略に従っています。 C++はほとんどの場合、ネイティブコードにコンパイルされます。 Pythonは、ほとんど常にバイトコードインタープリタを介して実行されます。Javaは、ほとんどの場合、JITコンパイラを介して実行されます。したがって、鈍いペダニシティを主張しない場合、コンパイルまたは解釈された言語について話すことは理にかなっています。
ただし、言語の実装戦略は、コンパイル/解釈された二分法に適切に適合しません。基本的に、厳密に解釈され、ソースから直接実行される言語はありません。これは非常に遅くなります。代わりに、事実上すべての「解釈された」言語実装は、ソースをより効率的に実行できる何か(多くの場合バイトコード)にコンパイルします。さらに、一部の実装JITは、実行時にそのバイトコードをネイティブコードにコンパイルします。コンパイルされていると私たちが考える言語でさえ、しばしばある程度の解釈が含まれています。たとえば、Cのprintfは事実上、フォーマット文字列のインタープリターです。
したがって、言語をコンパイル済みまたは解釈済みに分類しようとすることは意味がないと私は主張します。ほとんどすべての言語は、2つのアプローチのある程度のハイブリッドです。 (そして、はい、私たちが知識を持っている場合、コンパイル/解釈されるのは言語ではなく言語の実装です)。
いいえ、コンパイル済みと解釈済みの分類は言語には関係ありません。
コンパイラとインタプリタは、言語を提供する手段にすぎません。そして、これらの手段の背後にあるテクノロジーが進化します。実用的な例:
最後に 興味深い記事 は、同じ言語がインタープリターからコンパイルに進化する方法を示しています。
Basicの一部のバージョンでは、ソースコードファイルのステートメントをトークン化します。
APL(プログラミング言語)には、変数文字列をパラメーターとして受け取り、解釈して実行する実行演算子があります。変数文字列マトリックスを受け取り、それから関数を作成するcreate function演算子があります。これは、言語をコンパイル済みと見なすために、ある種のランタイムコンパイルを必要とします。
OPの コンパイルされた言語 および 解釈された言語 の定義。
その他のカテゴリは次のとおりです。
新しいツールの開発や使用傾向の変化に応じて、言語によってカテゴリが変わる場合があります。