最初のC ++コンパイラはどのようにC ++で作成できますか?


48

Stroustrupは、最初のC ++コンパイラであるCfrontがC ++で作成されたと主張しています(Stroustrup FAQ)。

しかし、最初のC ++コンパイラをC ++で作成することはどのように可能ですか?

コンパイラーを構成するコードもコンパイルする必要があります。したがって、最初のC ++コンパイラーをC ++で作成することはできませんでしたか?


6
en.wikipedia.org/wiki/Cfrontはこの問題をわずかにカバーしています。
クリストファー

回答:


57

ここに鍵があります:

最初のC ++コンパイラ(Cfront)はC ++で作成されました。それを構築するために、最初にCを使用して「C with Classes」-to-Cプリプロセッサを記述しました。「C with Classes」は、C ++の直接の祖先となったC方言でした。このプリプロセッサは、「C with Classes」コンストラクト(クラスやコンストラクタなど)をCに変換しました。これは、すべての言語を理解せず、Cコンパイラが行う型チェックのほとんどを残し、個々の完全な知識なしで構築します。その後、「C with Classes」でCfrontの最初のバージョンを作成しました。

そのため、Cfrontの最初のバージョンはC ++ではなく、中間言語で作成されました。CコンパイラーとプリプロセッサーをCで直接作成する機能は、Cの多くの革新(および大規模なセキュリティホール)につながりました。したがって、「C with Classes」コードをストレートCに変換する新しいプリプロセッサーを作成します(ストレートCは何でも)そして、「C with Classes」を使用してC ++コンパイラを記述し(Cで実行できなかったため、しばらく時間がかかります)、そのC ++コンパイラを使用してより効率的で完全なコンパイラを記述しますC ++。とった?


5
+1することができます(するべきではない)私のお気に入りの物語の1つへのリンクを含めるため。
-jwernerny

3
コンパイラは有効なC ++コードで記述されましたが、「C with Classes」プリプロセッサでサポートされていた完全なC ++機能の一部のみを使用しました。完全な言語のサブセットを使用したため、結果(Cfrontの最初の作業バージョン)もコンパイルしました。この「ブートストラップ」ステップを実行した後、彼はおそらくプリプロセッサを再び使用する必要はないでしょう。
joeytwiddle

2
@jwernerny-私はいつもその記事が不満だと思った。彼は最も困難で自明ではない部分について次のように説明しています。「バグはUNIXの「ログイン」コマンドのコードと一致します。 」しかし、これはどのように行われますか?実際に実証されたことがありますか?
確実に

3
「Cの多くの革新(および大規模なセキュリティホール)に導かれる」:私の知る限り、これらのトリックはCだけでなく、どの言語でも使用できます。したがって、他の言語でも同じセキュリティホールを使用できます。
ジョルジオ

2
@detly:今では些細なことのように聞こえますが、1983年には、これは実装の多様性の欠如によって実行可能な新しい攻撃でした。ソースからすべてをコンパイルすることは現在よりもはるかに大きな試練だったため、当時はバイナリをより信頼していました。
Blrfl

17

ブートストラップされました。CfrontにC ++機能が追加されるとすぐに、cfrontはその時点からその機能を使用できます(ただし、その機能を実装することはできません)。これは、cfrontがC ++コードをCコードに変換する機能を持っていたために機能しました。新しいプラットフォームが登場した場合、別のプラットフォームでcfrontを使用してcfrontをC ++からCに変換し、新しいプラットフォームのCコンパイラを使用してCからオブジェクトコードへのコンパイルを終了できます。


9

BSはその質問に答えていると思います。

最初のC ++コンパイラ(Cfront)はC ++で作成されました。それを構築するために、最初にCを使用して「C with Classes」-to-Cプリプロセッサを記述しました。「C with Classes」は、C ++の直接の祖先となったC方言でした。このプリプロセッサは、「C with Classes」コンストラクト(クラスやコンストラクタなど)をCに変換しました。これは、すべての言語を理解せず、Cコンパイラが行う型チェックのほとんどを残し、個々の完全な知識なしで構築します。

その後、「C with Classes」でCfrontの最初のバージョンを作成しました。Cfrontは、C ++ソースの完全な構文およびセマンティックチェックを行う従来のコンパイラでした。そのため、完全なパーサー、シンボルテーブルの構築、各クラス、関数などの完全な内部ツリー表現の構築を行いました。また、Cを出力する前に、C ++構造の内部ツリー表現でソースレベルの最適化を行いました。生成されたCで、型チェックにCに依存しませんでした。アセンブラとしてCを使用しました。結果のコードは妥協のないほど高速でした。

最初に、彼は「C with Classes」と呼ばれる単純なプリプロセッサによってCに実装されたものを作成しました。これは基本的にC ++でしたが、プリプロセッサはほとんどまたはまったくチェックしませんでした。次に、それを使用して、C ++のより強力な翻訳者であるCfrontをCfrontに書き込み、型チェック、シンボルテーブルなどを完備しました。


1
基本的に、C ++プログラムをコンパイルすると、Cに変換され、Cに変換された後、再びマシンコードにコンパイルされますか?
11

@Pacerier:元々、はい、しかし今はそうではありません。
マイクダンラベイ

あなたのコメントがよくわかりません。2番目のステップをスキップしてC ++ソースを取得し、マシンコードにコンパイルするコンパイラーがあるということですか?
Pacerier

7
@Pacerier:まあ、彼らはアセンブリ言語やマシンコードに直接行かない。通常、彼らは最初に機械に依存しない中間表現(トリプルまたはクワッド)に行き、最適化のためにそれを分析します。それから、アセンブリまたはマシンコードを生成します。コンパイラー設計に関する本(Aho&Ullman)を選んだら、きっと面白いと思うでしょう。
マイクダンラベイ

1
彼が構築していたC ++も、現在存在する言語の一部であったことに注意することが重要です。テンプレートや新しいライブラリはなく、Cキャストのみを使用しており、正しく思い出せば例外はありませんでした。
ロボット

2

この点については回答がなかったため、この回答を追加します。

技術的には、コードをコンパイルするためのソフトウェアは必要ありません。必要なコンパイラ仕様がある限り、実際のコンパイルを手動で行うことができます。これは、最初のC ++コンパイラのコンパイル方法ではありません。可能だと言っているだけです。

アセンブリ言語と比較してください。それらが初期に使用されたとき、アセンブリコードをマシンコードに変換するアセンブラソフトウェアはありませんでした。これは手作業で行われましたが、アセンブリ言語を使用するとプログラマーの概要がわかりやすくなりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.