私はウェブサイトhttp://coffeescript.org/でCoffeeScriptを研究しています、そしてそれはテキストを持っています
CoffeeScriptコンパイラ自体はCoffeeScriptで記述されています
コンパイラはそれ自体をどのようにコンパイルできますか、またはこのステートメントはどういう意味ですか?
私はウェブサイトhttp://coffeescript.org/でCoffeeScriptを研究しています、そしてそれはテキストを持っています
CoffeeScriptコンパイラ自体はCoffeeScriptで記述されています
コンパイラはそれ自体をどのようにコンパイルできますか、またはこのステートメントはどういう意味ですか?
回答:
コンパイラーの最初のエディションは、それに固有のプログラミング言語から機械で生成することはできません。あなたの混乱は理解できます。より多くの言語機能を備えた新しいバージョンのコンパイラー(ソースが新しい言語の最初のバージョンで書き直されている)は、最初のコンパイラーによってビルドできます。その後、そのバージョンは次のコンパイラーなどをコンパイルします。次に例を示します。
注:CoffeeScriptのバージョンがどのように番号付けされているか正確にはわかりません。これは単なる例です。
このプロセスは通常、ブートストラップと呼ばれます。ブートストラップコンパイラのもう1つの例はrustc
、Rust言語のコンパイラです。
論文で の信頼信託の反省、ケン・トンプソン、Unixのの創始者の一つは、どのようにCコンパイラのコンパイル自体の魅力的な(そして読みやすい)の概要を書き込みます。同様の概念は、CoffeeScriptやその他の言語にも適用できます。
独自のコードをコンパイルするコンパイラのアイデアは、クイン:ソースコードを実行するときに元のソースコードを出力として生成するソースコードに漠然と似ています。 以下は、CoffeeScript quineの一例です。トンプソンは、このC羽の例を挙げました。
char s[] = {
'\t',
'0',
'\n',
'}',
';',
'\n',
'\n',
'/',
'*',
'\n',
… 213 lines omitted …
0
};
/*
* The string s is a representation of the body
* of this program from '0'
* to the end.
*/
main()
{
int i;
printf("char\ts[] = {\n");
for(i = 0; s[i]; i++)
printf("\t%d,\n", s[i]);
printf("%s", s);
}
次に、'\n'
ASCIIコード10を表すようなエスケープシーケンスがコンパイラにどのように教えられるのか不思議に思うかもしれません。答えは、Cコンパイラのどこかに、バックスラッシュシーケンスを認識する次のような条件を含む文字リテラルを解釈するルーチンがあるということです。
…
c = next();
if (c != '\\') return c; /* A normal character */
c = next();
if (c == '\\') return '\\'; /* Two backslashes in the code means one backslash */
if (c == 'r') return '\r'; /* '\r' is a carriage return */
…
したがって、上のコードに条件を1つ追加できます…
if (c == 'n') return 10; /* '\n' is a newline */
… '\n'
ASCII 10 を表すことを知っているコンパイラを生成する。興味深いことに、そのコンパイラと、それによってコンパイルされた後続のすべてのコンパイラそのマッピングを「知っている」ので、次世代のソースコードでは、最後の行を次のように変更できます。
if (c == 'n') return '\n';
…そしてそれは正しいことをします!の10
コンパイラから来ていない、もはや明示的にコンパイラのソースコードで定義する必要があります。1
これは、Cコードで実装されたC言語機能の1つの例です。ここで、すべての単一言語機能についてそのプロセスを繰り返します。これで、「セルフホスティング」コンパイラー(Cで作成されたCコンパイラー)ができました。
1論文で説明されているプロットのひねりは、コンパイラがこのような事実を「教える」ことができるため、検出が困難な方法でトロイの木馬を実行した実行ファイルを生成することを誤って教えられる可能性があり、そのような妨害行為が持続する可能性があることです。汚染されたコンパイラによって生成されたすべてのコンパイラ。
あなたはすでに非常に良い答えを得ていますが、私はあなたに啓蒙となる別の視点を提供したいと思います。まず、2人が同意できる2つの事実を確認しましょう。
#1と#2の両方が真であることに同意できると思います。次に、2つのステートメントを見てください。CoffeeScriptコンパイラーがCoffeeScriptコンパイラーをコンパイルできることは完全に正常であることがわかりましたか?
コンパイラは、何をコンパイルするかを気にしません。CoffeeScriptで書かれたプログラムであれば、コンパイルできます。そして、CoffeeScriptコンパイラ自体は、たまたまそのようなプログラムです。CoffeeScriptコンパイラーは、それがコンパイルしているCoffeeScriptコンパイラー自体であることを気にしません。表示されるのは、CoffeeScriptコードです。限目。
コンパイラはそれ自体をどのようにコンパイルできますか、またはこのステートメントはどういう意味ですか?
はい、それがまさにその発言の意味です。そして、その発言がどのように真実であるかを今ご覧いただければ幸いです。
コンパイラはそれ自体をどのようにコンパイルできますか、またはこのステートメントはどういう意味ですか?
それはまさにそれを意味します。まず第一に、考慮すべきいくつかの事柄。確認する必要がある4つのオブジェクトがあります。
これで、CoffeScriptコンパイラの生成されたアセンブリ(実行可能ファイル)を使用して任意のCoffeScriptプログラムをコンパイルし、そのプログラムのアセンブリを生成できることは明らかです。
現在、CoffeScriptコンパイラー自体は単なる任意のCoffeScriptプログラムであるため、CoffeScriptコンパイラーでコンパイルできます。
あなたの混乱は、あなたが自分自身の新しい言語を作成するとき、あなたはしていないという事実から生じると思われていコンパイラをまだあなたのコンパイラをコンパイルするために使用することができます。これは確かに鶏卵問題のようですね。
ブートストラップと呼ばれるプロセスを紹介します。
次に、新しい機能を追加する必要があります。while
-loops だけを実装したが、-loopsも必要for
だとします。これは問題ではありません。for
-loopになるように-loopを書き換えることができるからですwhile
。つまりwhile
、手元にあるアセンブリでコンパイルできるのは、コンパイラのソースコードでのみ-loopを使用できるということです。ただし、コンパイラー内で関数を作成for
して、それを使用してループを配置およびコンパイルできます。次に、既存のアセンブリを使用して、新しいコンパイラバージョンをコンパイルします。これで、for
ループの解析とコンパイルもできるコンパイラのアセンブリができました!コンパイラのソースファイルに戻り、while
不要な-loopsを-loopsに書き換えますfor
。
必要なすべての言語機能をコンパイラーでコンパイルできるようになるまで、すすぎおよび繰り返します。
while
そして、for
明らかに唯一の例でしたが、これはあなたが望む任意の新しい言語機能のために動作します。そして、あなたはCoffeScriptが今ある状況にあります:コンパイラはそれ自身をコンパイルします。
そこにはたくさんの文学があります。信頼についての考察信頼は、そのトピックに関心のあるすべての人が少なくとも一度は読むべき古典です。
ここで、コンパイラという用語は、2つのファイルが関係しているという事実を無視しています。1つは、CoffeScriptで記述された入力ファイルを取り、その出力ファイルとして別の実行可能ファイル、リンク可能なオブジェクトファイル、または共有ライブラリを生成する実行可能ファイルです。もう1つはCoffeeScriptソースファイルで、CoffeeScriptのコンパイル手順をたまたま説明しているだけです。
最初のファイルを2番目のファイルに適用し、最初のファイルと同じコンパイル動作を実行できる3番目のファイルを生成します(2番目のファイルが最初のファイルによって実装されていない機能を定義している場合はさらに多くの可能性があります)。とても欲望。
CoffeeScriptコンパイラーのRubyバージョンは既に存在しているため、CoffeeScriptコンパイラーのCoffeeScriptバージョンを作成するために使用されました。
これは、セルフホスティングコンパイラと呼ばれます。
これは非常に一般的であり、通常、自分の言語を使用してその言語の成長を維持したいという作者の欲求に起因します。
ここでのコンパイラの問題ではなく、言語の表現力の問題です。コンパイラは、ある言語で書かれたプログラムにすぎないからです。
「言語が作成/実装されている」とは、実際にはその言語のコンパイラまたはインタープリタが実装されていることを意味します。言語を実装するプログラムを作成できるプログラミング言語があります(同じ言語のコンパイラー/インタープリターです)。これらの言語は、ユニバーサル言語と呼ばれます。
これを理解できるようにするために、金属旋盤について考えてみましょう。金属を成形するための道具です。そのツールだけを使用して、パーツを作成することにより、別の同じツールを作成することができます。したがって、そのツールはユニバーサルマシンです。もちろん、最初の方法は他の手段(他のツール)を使用して作成されたため、おそらく品質が低くなっていました。しかし、最初のものは、より高い精度で新しいものを構築するために使用されました。
3Dプリンターはほとんど普遍的な機械です。3Dプリンターを使用して、3Dプリンター全体を印刷できます(プラスチックを溶かすチップを作成することはできません)。
コンパイラーは高レベルの仕様を取り、それをハードウェアで実行できるような低レベルの実装に変えます。したがって、対象となる言語のセマンティクス以外に、仕様の形式と実際の実行との間には関係はありません。
クロスコンパイラーは、あるシステムから別のシステムに移動し、クロス言語コンパイラーは、ある言語仕様を別の言語仕様にコンパイルします。
基本的にコンパイルは単なる翻訳であり、レベルは通常、言語の上位レベルから下位レベルまでですが、多くのバリエーションがあります。
もちろん、ブートストラップコンパイラは、記述された言語をコンパイルするため、最も混乱を招きます。実行可能な最低限の既存のバージョンを必要とするブートストラップの最初のステップを忘れないでください。多くのブートストラップコンパイラは、最初にプログラミング言語の最小限の機能を処理し、前の機能を使用して新しい機能を表現できる限り、今後さらに複雑な言語機能を追加します。そうでない場合は、「コンパイラ」のその部分を別の言語で事前に開発しておく必要があります。
self-hosting
コンパイラです。参照してくださいprogrammers.stackexchange.com/q/263651/6221