web-dev-qa-db-ja.com

すべての言語をコンパイルまたは解釈のいずれかに分類できますか?

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つ目のカテゴリはありますか?

14
Sisir

あなたの質問への答え:

すべての言語をコンパイルまたは解釈のいずれかに分類できますか?

「いいえ」ですが、あなたがそう思う理由ではありません。理由は、3つ目の不足しているカテゴリがあるということではありません。理由は、カテゴリ自体は無意味なであるためです。

「コンパイルされた言語」や「解釈された言語」といったものはありません。これらの用語は間違っているわけではなく、無意味です。

プログラミング言語は、抽象的な数学的なルール、定義、および制限のセットです。プログラミング言語はコンパイルまたは解釈されません。プログラミング言語だけare。 [クレジットは Shriram Krishnamurthi に誰が言ったか 9年前のチャンネルのインタビューで(51:37-52:20頃) ]

実際、プログラミング言語はanyインタープリターやコンパイラーがなくても完全に存在できます。たとえば、彼が1930年代に設計した Konrad ZusePlankalkü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コンパイラーのグループ。コンパイラーが実行されるときに時間的な違いがあります。

  • ジャストインタイムコンパイラが実行whileプログラムが実行中
  • Ahead-Of-Timeコンパイラが実行されますbeforeプログラムが起動します

そして、インタープリターとコンパイラーを組み合わせる、または複数のコンパイラーを組み合わせる、または(よりまれに)複数のインタープリターを実装する実装があります。いくつかの典型的な組み合わせは

  • mixed-mode両方が同じプログラムを同時に処理するインタープリターとJITコンパイラーを組み合わせた実行エンジン(例:Oracle HotSpot JVM、IBM J9 JVM)
  • マルチフェーズ [その用語を発明しました。広く使われている実行エンジンについては知りません。最初のフェーズは、プログラムを次のフェーズにより適した言語にコンパイルするコンパイラで、次に、その言語を処理する2番目のフェーズです。 (より多くのフェーズが存在する可能性がありますが、2つが一般的です。)おそらく推測できるように、第2フェーズは再び異なる実装戦略を使用できます。
    • インタプリタ:これは典型的な実装戦略です。多くの場合、解釈される言語は、「解釈可能性」のために最適化されたバイトコードの形式です。例:CPython、 YARV(2.6より前) 、Zend Engine
    • これを2つのコンパイラの組み合わせにするコンパイラ。通常、最初のコンパイラーは言語を「コンパイル可能性」用に最適化されたバイトコードの形式に変換し、2番目のコンパイラーはターゲット・プラットフォームに固有の最適化コンパイラーです
    • 混合モードVM。例:YARV 2.6以降、Rubinius、SpiderMonkey、SquirrelFish Extreme、Chakra

しかし、まだ他にもあります。一部の実装では、コンパイラーとインタープリターの代わりに2つのコンパイラーを使用して、混合モードエンジンと同じ利点を得ます(たとえば、最初の数年間は、V8はこのように動作しました)。

RPython はバイトコードインタープリターとJITを組み合わせますが、JITはユーザープログラムをコンパイルせず、ユーザープログラムを解釈しながらバイトコードインタープリターをコンパイルします。その理由は、RPythonは言語を実装するためのフレームワークであり、このようにして、言語の実装者はバイトコードインタープリターを作成するだけで、無料でJITを取得できるからです。 (もちろん、RPythonの最も有名なユーザーは PyPy です。)

Truffleフレームワーク は言語にとらわれないASTを解釈しますが、同時にspecializes自体を特定のASTに変換します。これはコンパイルのようなものですが、そうではありません。最終結果は、Truffleが言語固有の情報をあまり知らなくても、コードを非常に高速に実行できることです。 (Truffleは言語実装の汎用フレームワークでもあります。)ASTは言語に依存しないため、同じプログラムで複数の言語を混在させて一致させることができ、Truffleは言語間で最適化を実行できますRubyメソッドをECMAScript関数にインライン化するなど。

Macrosevalは、不可能コンパイルできる機能として引用されることがあります。しかし、それは間違っています。マクロのコンパイルには2つの簡単な方法とevalがあります。 (コンパイルの目的のために、マクロとevalは互いに多少二重であり、同様の手段を使用して処理できることに注意してください。)

  1. インタープリターの使用:マクロの場合、インタープリターをコンパイラーに組み込みます。 evalの場合、インタープリターをコンパイル済みプログラムまたはランタイムサポートライブラリに埋め込みます。
  2. コンパイラーの使用:マクロの場合、まずマクロをコンパイルしてから、コンパイルしたマクロをコンパイラーに埋め込み、この「拡張」コンパイラーを使用してプログラムをコンパイルします。 evalの場合は、コンパイラをコンパイル済みプログラムまたはランタイムサポートライブラリに埋め込みます。
48
Jörg W Mittag

私たちが知識を深めているのであれば、どの言語も原則としてコンパイラーまたはインタープリターのいずれかで実装できるため、コンパイルされた言語や解釈された言語などはありません。ただし、ほとんどの言語は比較的一貫した実装戦略に従っています。 C++はほとんどの場合、ネイティブコードにコンパイルされます。 Pythonは、ほとんど常にバイトコードインタープリタを介して実行されます。Javaは、ほとんどの場合、JITコンパイラを介して実行されます。したがって、鈍いペダニシティを主張しない場合、コンパイルまたは解釈された言語について話すことは理にかなっています。

ただし、言語の実装戦略は、コンパイル/解釈された二分法に適切に適合しません。基本的に、厳密に解釈され、ソースから直接実行される言語はありません。これは非常に遅くなります。代わりに、事実上すべての「解釈された」言語実装は、ソースをより効率的に実行できる何か(多くの場合バイトコード)にコンパイルします。さらに、一部の実装JITは、実行時にそのバイトコードをネイティブコードにコンパイルします。コンパイルされていると私たちが考える言語でさえ、しばしばある程度の解釈が含まれています。たとえば、Cのprintfは事実上、フォーマット文字列のインタープリターです。

したがって、言語をコンパイル済みまたは解釈済みに分類しようとすることは意味がないと私は主張します。ほとんどすべての言語は、2つのアプローチのある程度のハイブリッドです。 (そして、はい、私たちが知識を持っている場合、コンパイル/解釈されるのは言語ではなく言語の実装です)。

13
Winston Ewert

いいえ、コンパイル済みと解釈済みの分類は言語には関係ありません。

コンパイラとインタプリタは、言語を提供する手段にすぎません。そして、これらの手段の背後にあるテクノロジーが進化します。実用的な例:

  • 80年代後半 Instant Cfrom Rational Systems はCインタプリタでした(はい!)。パフォーマンスに敏感な開発には遅すぎますが、それはかなり印象的でした。
  • 長い間、BASICは一般的に解釈される言語でした。しかし、突然、BASICコンパイラー(Visual Basicなど)の市場が出現しました。
  • CSD Pascal 、ソースコードがバイトコード(pコード)にコンパイルされたため、仮想マシンで提供される最初の言語は多くのコンパイラーと見なされていました。しかし、pコードは実際にはマシンコードにコンパイルされず、それ自体が解釈され、パフォーマンスが低下したため、インタープリターのカテゴリーでそれを見た人もいます。
  • Transpilers は、以前と今でも使用されており、1つの言語を別の言語に、場合によってはコンパイル済み言語に変換し、いくつかの追加ライブラリを使用してより動的な言語構造に対処します。
  • 仮想マシンを JIT-compiler technology (例:JVM、CLI/CLR)と組み合わせることで、現在、最初に解釈される多くの言語をコンパイルできます(例: IronPython for Ptyhton、または- Clojure LISP方言として)。

最後に 興味深い記事 は、同じ言語がインタープリターからコンパイルに進化する方法を示しています。

1
Christophe

Basicの一部のバージョンでは、ソースコードファイルのステートメントをトークン化します。

APL(プログラミング言語)には、変数文字列をパラメーターとして受け取り、解釈して実行する実行演算子があります。変数文字列マトリックスを受け取り、それから関数を作成するcreate function演算子があります。これは、言語をコンパイル済みと見なすために、ある種のランタイムコンパイルを必要とします。

0
rcgldr

OPの コンパイルされた言語 および 解釈された言語 の定義。

その他のカテゴリは次のとおりです。

  • 無し。インタプリタもコンパイラも存在しない言語。これは、学術コンピュータサイエンスの多くの言語の場合です。
  • 混合。ほとんどの実装で部分的にコンパイルされ、部分的に実行される言語。 OPが言及するように、これはJavaの場合です。いいえ、このカテゴリの一般的な名前はわかりません。 JITコンパイル済み言語は、私がよく言及する言語です。

新しいツールの開発や使用傾向の変化に応じて、言語によってカテゴリが変わる場合があります。

0