最初のインタプリタの前に最初のコンパイラが書かれたのはなぜですか?


72

最初のコンパイラは1952年にグレース・ホッパーによって書かれ、Lispインタプリタは1958年にジョン・マッカーシーの学生スティーブ・ラッセルによって書かれました。コンパイラを書くことは、インタプリタよりもはるかに難しい問題のようです。もしそうなら、最初のコンパイラが最初のインタプリタの6年前に書かれたのはなぜですか?


67
なぜなら、当時はインタープリターよりもコンパイラーが必要だったからです
ラチェットフリーク14

23
最初のインタープリターをコンパイルするには?:P(頬の部分的な舌のみ、インタープリターは複雑です(単純なコンパイラーよりも)、マシンコードで効率的なものを書くのは厄介です)
Vality

4
CPUを実行する命令を解釈すると解釈する場合(ハードウェア経由で実装されますが)、最初のインタープリターが最初のコンパイラの後に作成されたという主張は、保持されません。ところで、私はこれが質問/回答に役立たないことを知っています。それは、異なる視点に関する興味深いコメントであることを意味しているだけです。
ペドロエンリケA.オリベイラ14

11
McCarthyはLISPインタープリターを作成しませんでした。マッカーシーは数学的形式主義を発明しました。当時のMIT AIラボの学生の1人であったスティーブラッセルは、マッカーシーの空想の飛行を実行するための通訳を書くことができることに気付きました。残りは歴史です。
ジョンR.ストローム14

5
実際、マッカーシーはLISPを実装できないと信じていると聞きました。これは、LISPマニュアルAからマッカーシーの普遍的な機能が)ことに気づきラッセルでし通訳およびb)実装可能でした。
ヨルグWミットタグ14

回答:


97

コンパイラを書くことは、インタプリタよりもはるかに難しい問題のようです。

今日はそれは本当かもしれませんが、私は約60年前にはそうではなかったと主張します。いくつかの理由:

  • インタプリタでは、それとプログラムの両方をメモリに保持する必要があります。1kbのメモリが非常に贅沢な時代では、実行中のメモリフットプリントを低く抑えることが重要でした。また、解釈にはコンパイルされたプログラムを実行するよりも少し多くのメモリが必要です。
  • 最近のCPUは非常に複雑で、膨大な命令のカタログがあります。したがって、優れたコンパイラーを作成することは、本当に難しいことです。古いCPUははるかに単純だったため、コンパイルでさえも簡単でした。
  • 現代の言語は古い言語よりもはるかに複雑であるため、コンパイラーでさえ非常に複雑です。したがって、古い言語には、より単純なコンパイラがあります。

65
コンパイラーなしでは、アセンブリーでインタープリターを作成する必要があります
ラチェットフリーク14

34
最初のコンパイラーはどこにでもあります。(人々が通訳者である場合、コンピューターは必要ありません)。それから誰かがコンパイルされた言語でコンパイラを書くことを考えたにちがいありません(彼らが持っていた唯一の言語ですが、時間が経つにつれて私の人間をコンパイルしました)。
ctrl-alt-delor 14

1
:実は....私は最近、アポロガイダンスコンピューターは、月のフライトはインタプリタを持っていた60年代に使用されることをお読み のwikiエントリ 「...通訳は、ネイティブにサポートAGCよりも多くの指示を提供...」私は、この『インタプリタが』だったと仮定します LISPのようなものよりも、古いApple IIコンピューターに組み込まれた「Sweet 16」インタープリターに似ています。
カルフール14

6
@ratchetfreakそして、そうでした。最初のコンパイラであったように。
RBarryYoung

3
@richard:人々が通訳/計算機だったとき、彼らの役職は「コンピューター」と呼ばれていました。ですから、人々が通訳だったとき、彼らは文字通りコンピューターでした。マンハッタンプロジェクトでは、核物理学者が計算をメールで送信して実行するために、数千台の「コンピューター」(実際の職名、真剣に)を使用しました。実際、このプロジェクトでは、「コンピューター」に送られる物理学者の理論から計算を定式化したエンジニアからの計算を分解する数学者も雇いました。
スリーブマン14

42

基本的なポイントは、1950年代のコンピューティングハードウェア環境が、当時のコンピューターのバッチ指向処理を考えると、コンパイラーだけが実行可能であるようにしたことです。

当時、より優れたユーザーインターフェイスは、主にパンチカードとテレタイププリンターに限定されていました。1961年、SAGEシステムはコンピューターの最初のブラウン管(CRT)ディスプレイになりました。そのため、インタープリターのインタラクティブな性質は、ずっと後になるまで、望ましいものでも自然なものでもありませんでした。

1950年代の多くのコンピューターはフロントパネルスイッチを使用して命令をロードし、出力は単にランプ/ LEDの列であり、愛好家は1970年代までフロントパネルスイッチとLEDを使用していました。たぶんあなたは悪名高いAltair 8800に精通しているでしょう。

他のハードウェアの制限により、インタプリタは実行不可能になりました。1950年代には、コンピューターのプライマリメモリ(RAMなど)の可用性が極端に制限されていました。半導体集積回路(1958年まで登場しなかった)の前は、メモリは磁気コアメモリまたはビットまたはワードで測定される遅延ラインメモリに限定されていました。プレフィックスはありません。セカンダリストレージメモリ(ディスクやテープなど)の速度の遅さと組み合わせて、解釈されるプログラムが読み込まれる前であっても、インタプリタに多くのメモリを使用することは実行不可能ではないとしても、無駄と見なされます。

IBMのJohn Backus率いるチームが1954〜57年にFORTRANコンパイラを作成したとき、メモリ制限は依然として主要な要因でした。この革新的なコンパイラは、最適化コンパイラであるという理由だけで成功しました。

1950年代のコンピュータのほとんどはほとんど持っていたすべてのオペレーティングシステムは、このような動的リンクと仮想メモリ管理などだけでは現代的な機能を聞かせ、その通訳のアイデアは、その時点であまりにも過激かつ非現実的でした。

補遺

1950年代の言語は原始的でした。彼らは含ま小さなしばしば基盤となるハードウェアの取扱説明書やその対象の使用の問題定義のいずれかによって影響を受けた業務の一握りを、。

当時のコンピューターは、今日のコンピューターのことを考えると、ほとんど汎用コンピューターではありませんでした。再構築することなく再プログラム可能であることは、革新的なコンセプトと考えられていました。以前は、電気機械式のマシン(通常は計算機)を使用して回答を計算または計算していました(1950年代のアプリケーションの大半は本質的に数値でした)。

コンピューターサイエンスの観点から見ると、コンパイラーとインタープリターはどちらも翻訳者であり、実装する複雑さはほぼ同じです。


タイムシェアリングが始まる前に、コンピューターはテレタイプを使用していましたか?ラインプリンターを使用するか、テープにスプールすることを期待していました。そうしないと、テキストの各行の後にコンピューターが待たなければならない1〜8秒は、コンピューターが何か有用なことをしていたはずの1〜8秒を表していました。
supercat 14

2
@supercat-はい、テレタイプが使用されましたが、「インタラクティブ」とはほど遠いものでした。私がプログラムした最初のコンピューターには、18ビットワードで構成されるメモリがありました-1Kでした。メモリー自体は回転ドラムでしたので、コンピューターの電源を入れたとき、メモリーが高速になるまで待つ必要がありました。テレタイプが接続されていて、A)キーボードから入力された文字を読み取るか、紙テープリーダーで読み取る(コンピューターの観点からは両方とも同じ)、B)文字を「プリンターに書き込むテレタイプの。ああ、素晴らしい日-素晴らしい日..!私のグルーエルはまだ暖かいですか?!?!?:-)
ボブジャービス14

@BobJarvis:それは何年でしょうか?
supercat

1
@supercat-1973-しかし、問題のコンピューター(EDP-18、Educational Data Productsによる)は、それでも比較的高齢でした。それでも、それは我々が持っていたものだった(と持つすべての私たちは、それはかなり驚くべきだったと思って早70年代半ばの高校でを台無しにするコンピュータは異例でした)。:-)
ボブジャービス14

2
これは、受け入れられているものよりもはるかに優れた完全な答えです。
ジムギャリソン14

12

最初のプログラミング言語は非常に単純で(たとえば再帰はありません)、それ自体が単純なマシンアーキテクチャに近いものでした。翻訳はその後、簡単なプロセスでした

コンパイラは、プログラム実行のためのデータとソースコードを解釈するためのテーブルの両方を保持する必要があるインタープリターよりも、プログラムとして単純でした。また、インタープリターは、プログラムソースコードとシンボリックテーブルのためにより多くのスペースを必要とします。

メモリは(コストとアーキテクチャの両方の理由で)非常に少ないため、コンパイラはオペレーティングシステムを上書きするスタンドアロンプ​​ログラムになる可能性があります(これらのいずれかを使用しました)。コンパイルされたプログラムを実行するには、コンパイル後にOSを再ロードする必要がありました。...これにより、実際の作業のためにインタープリターを実行することは単にオプションではないことが明らかになります

本当であるために、コンパイラに必要な単純さは、コンパイラがあまり良くないようなものでした(コードの最適化は、まだ考慮されていてもまだ初期段階でした)。手書きのマシンコードは、少なくとも一部の地域では60年代後半まで、コンパイラが生成したコードよりもはるかに効率的であるという評判がありました。コード拡張率という概念さえあり、コンパイルされたコードのサイズを非常に優秀なプログラマーの仕事と比較しました。通常、ほとんどの(すべての?)コンパイラーで1を超えていたため、プログラムの速度が遅くなり、さらに重要なことに、より大きなプログラムではより多くのメモリーが必要になりました。これは60年代にはまだ問題でした。

コンパイラの関心は、特にさまざまな分野の科学者など、コンピューティングの専門家ではないユーザーにとって、プログラミングの容易さにありました。この関心はコードのパフォーマンスではありませんでした。それでも、プログラマーの時間は安価なリソースと見なされていました。コストはコンピューターの時間で、1975年から1980年までハードウェアからソフトウェアに切り替わりました。これは、コンパイラさえ、一部の専門家によって真剣に受け止められなかったことを意味します。

コンピューター時間の非常に高いコストは通訳を失格にするもう1つの理由であり、ほとんどの人にとってまさにその考えは笑えるものでした。

Lispの場合は非常に特殊です。なぜなら、Lispは非常に単純な言語であり、それを実現可能にしたからです(58年にはコンピューターが少し大きくなりました)。さらに重要なことは、Lispインタプリタは、ユーザビリティの問題とは無関係に、Lispの自己定義可能性(メタ循環性)に関する概念実証でした

Lispの成功の主な理由は、この自己定義性により、プログラミング構造の研究および新しい言語の設計(およびシンボリック計算の利便性)のための優れたテストベッドとなったことです。


3
私、なんて大胆だ
ファラプ14

@Pharapそれは不適切なスタイルですか?私の目的は、事実を単純に列挙するよりも自由なスタイルを可能にしながら、重要な情報を見つけやすくすることです。私は、このSEサイトではあまり効果的ではないことを認めなければなりません。
babou 14

@ anonymous-downvoter説明コメントなしのダウン投票は、誰かが愚かかもしれないことを示しています。しかし、それは誰を言っていません。
babou 14

4

私は質問の前提に同意しません。

Adm。Hopperの最初のコンパイラ(A-0)は、リンカーまたはマクロ言語に似ていました。彼女はサブルーチンにテープを保存し(それぞれに番号が割り当てられています)、プログラムはサブルーチンと引数のリストとして書き込まれます。コンパイラは、要求されたサブルーチンをテープからコピーし、完全なプログラムに並べ替えます。

彼女は詩のアンソロジーを編集するのと同じ意味で「コンパイル」という言葉を使用しました:さまざまなアイテムを1つのボリュームにまとめます。

私の知る限り、その最初のコンパイラにはレクサーやパーサーがありませんでした。これは、最新のコンパイラの遠い先祖になります。彼女は後に、より英語に似た構文を目指して別のコンパイラー(B-0、別名FLOW-MATIC)を作成しましたが、Lispインタープリターとほぼ同じ1958年または1959年まで完成しませんでした。

したがって、質問自体は少し間違っていると思います。当時の多くの科学者が同じ方向に沿って考えていたはずのアイデアを共有したために、コンパイラとインタープリターはほぼ同時に同時進化したようです。

ここに引用してより良い答え:https://stackoverflow.com/a/7719098/122763


3

方程式のもう1つの部分は、コンパイラーがアセンブラーの上のステップ抽象化であったことです。最初に、ハードコードされたマシンコードがありました。「私たち」はアセンブラーでした。すべてのジャンプやオフセットなどは、手作業で16進数(または8進数)に計算され、紙テープまたはカードにパンチされました。そのため、アセンブラーが登場したときは、時間を大幅に節約できました。次のステップはマクロアセンブラでした。これにより、一連のマシン命令に展開されるマクロを作成することができました。したがって、FortranとCobolは大きな前進でした。リソース(ストレージ、メモリ、CPUサイクル)の不足は、汎用インタープリターがテクノロジーの成長を待たなければならないことを意味していました。初期のインタプリタのほとんどはバイトコードエンジンでした(今日のJavaやCLRのようですが、機能ははるかに劣っています)。UCSD Pascalは非常に人気のある(かつ高速な)言語でした。MS Basicは、内部のバイトコードエンジンでした。

命令のオーバーヘッドという点では、実行されているプロセッサに完全に依存していました。業界はしばらくの間、RISC対CISCの大きな混乱を経験しました。私は個人的に、IBM、Data General、Motorola、Intel(登場したとき)、TI、その他いくつかのアセンブラーを書きました。命令セット、レジスタなどにはかなりの違いがあり、pコードを「解釈」するために必要なものに影響を与えます。

時間の参考として、1972年頃に電話会社でプログラミングを開始しました。


2

すべてをメモリに保持していない場合、コンパイルされたコードははるかに高速です。忘れないでください、これらの時間では関数がコンパイルされたコードに加わりました。コンパイルしていない場合、どの関数が必要かわかりません。だから、あなたは...から関数を呼び出しています...ああ、まだディスクからではなく、50代前半ですが、カードからです!ランタイムで!

もちろん、回避策を見つけることは可能ですが、言語は非常に単純で、マシンコードからそれほど遠くないため、まだ回避策は見つかりませんでした。コンパイルは簡単で十分でした。


1

最初のコンパイラーが書かれる前に、人々はアセンブラー・コードを書きました。これは普通のバイナリー・コードと比較して大きな進歩でした。当時、コンパイラーによってコンパイルされたコードはアセンブラーコードよりも効率が悪いという強い議論がありました。当時、(コンピューターのコスト)と(プログラマーのコスト)の関係は、今日とは大きく異なりました。そのため、その観点からコンパイラーに対して強い抵抗がありました。

しかし、コンパイラはインタプリタよりもはるかに効率的です。その時点で通訳を書くことを提案していたなら、人々はあなたがおかしいと思ったでしょう。100万ドルのコンピューターを購入し、そのコードの解釈能力の90%を無駄にすることを想像できますか?


私は1950年代のコンピューターについてあまり知りませんが、少なくとも後の数十年の単純なフォンノイマンマシンでは、インタープリターのオーバーヘッドは、解釈された命令ごとに2から5命令(合計で4から10サイクル)になります:デコード、間接ジャンプ、デコード追加の引数。インタプリタ命令セットを十分に高レベルにすると(インタプリタ命令ごとに複数のマシン命令を実行する場合)、これは90%未満になり、おそらく許容範囲内になります。Forthも参照してください。

3
最初のコンパイラが作成される前は、プログラムの大部分は実際にはアセンブリ言語ではなく実際のマシンコードで作成されていました(op-codesニーモニック)。
mctylr 14

2
@delnanこれらのシステムはキロヘルツのクロックで実行されていたため、パフォーマンスが3〜5時間低下するのは、ハードウェア障害(真空管の吹き飛ばし)によってシステムが失敗する前にプログラムが正常に完了するかどうかの違いです。正しく思い出せば、ハードウェア障害は1950年代に毎日発生していました。
mctylr 14

delnan:5つの命令オーバーヘッドで解釈できるインタープリターを見せてください。そして、Forthはインタープリター言語ではなく、憎悪です:-)。申し訳ありませんが、私はスレッド化された言語を意味します。BASICのようなものは、1つのステートメントを解釈するのに膨大な数の命令を必要とします。
gnasher729 14

@gnasher:1974年、私はKeronix(ahem、Data General Novaクローン)用の高性能BASICインタープリターを作成しました。これは、バイト指向のPコードを使用してBASICステートメントをエンコードしました。pCodeを「解釈」するのに約25〜50個のマシン命令が必要で、そのうち10個がバイトフェッチ自体に使用されていました。(1969年にトークンベースのトークンを作成しましたが、実際には式を再解析する必要があったため、より多くのトークンを取得しました)。しかし、それは「無数」ではありませんでした。
アイラバクスター14

1

ループプログラムを解釈する前に、繰り返し読み取ることができるメディアに保存する必要があります。ほとんどの場合、唯一の適切なメディアはRAMです。通常、コードは、人間が読める言語ではほとんど空であるパンチカードに入力されるため、コードをRAMに保存する前に何らかの処理を実行する必要があります。多くの場合、プロセッサによる直接実行に適した形式にパンチカードテキストを処理することは、インタプリタを介して効率的に処理できる形式に処理するよりも実際には難しくありません。

初期のコンパイラの目標は、ディスク上にアセンブリ言語またはオブジェクトコードファイルを作成することではなく、実行可能なRAM内のコードを作成することでした。邪魔するオペレーティングシステムがない場合、これは実際には驚くほど簡単です。コンパイラは、メモリの一方の端からコードを生成し、もう一方の端から変数と分岐ターゲットを割り当てることができます。ステートメントがラベル「1234」でマークされている場合、コンパイラーは「1234」という変数に現在のコード生成アドレスにジャンプする命令を保存し、存在しない場合はその変数を作成します。「goto 1234」というステートメントは、変数「1234」が存在しない場合は作成し、その変数にジャンプします(そのステートメントが実行される前に、適切な場所へのジャンプが格納されることを期待しています)。gotoまだ定義されていないラベルです。これはgoto、変数がジャンプする場所をコンパイルするタイミングを知っているためです。それはコードを生成する最も効率的な方法ではないかもしれませんが、コンピューターが処理することが期待されているプログラムのサイズには十分です。


1
ディスク?うーん...いや テープ。大きくて遅いリールツーリールテープ。そしてそれらの多く。グレース・マレー・ホッパーによる講義に行ったことを覚えています(私はシステム分析専攻であり、キャンパスで海軍のROTCの分遣隊のミッドシップマンであり、CAPTホッパーは海軍士官だったので、私にとって非常に興味深いです)。彼女は、プログラムの未使用部分をテープに書き込むというアイデアを思いついたという話を話した。「しかし」と彼女は言いました、「IBMが同じことをして仮想メモリと呼ぶまで、このアイデアは受け入れられませんでした」。CAPTホッパーはIBMを本当に嫌っていました... :
ボブジャービス14

@BobJarvis:私はその側面を考慮していませんでしたが、すぐに実行可能なコードをRAMにコンパイルするために使用される同じ一般的なワンパス設計は、テープドライブでうまく機能します。コンパイラからの出力はテープに送られ、テープは巻き戻されて順次メモリアドレスに読み取られ、コンパイラの一部を同時にメモリに保持する必要なく直接実行されます。
supercat 14

0

インタープリターが機能するにはコンパイラーが必要だからです。

上記のステートメントは実際には正しくありません。厳密に言えば、コンパイラを使用したり、コンパイラと対話したりすることなく、インタプリタを作成できます。しかし、これを行った結果は、これらの用語が意味するものとはあまり似ていないでしょう。

厳密な意味では、コンパイラーとインタープリターはまったく異なることを行います。コンパイラは、あるソースからテキストを読み取り、それを他の形式に変換します。アセンブリ言語、マシンコード、別の高レベル言語、データ構造、その他何でもです。一方、インタプリタは何らかのデータ構造を取り込んで、それに基づいて命令を実行します。

私たちが最近「コンパイラ」と考える傾向にあるのは、実際にはコードジェネレータと組み合わせられたコンパイラです。つまり、何らかのソースからデータを取り込み、その内容に基づいて何らかの形式でコードを出力するプログラムです。これはコンパイラのかなり直感的な使用方法であり、コンパイラが最初に作成されたものの1つでした。しかし、別の見方をすれば、これはインタープリターが行うことと非常によく似ています。より一般的な操作を実行する代わりに、常にコードを出力しますが、原理は同じです。

反対側から見ると、インタープリターはどこかからデータを取得する必要があります。これは単なるデータなので、他の種類のデータを作成するのと同じ方法で作成できます。解釈について話しているので、テキストファイルの指示に基づいてデータを作成できるのは自然なことです。しかし、それを行うには、テキストを読み、データ構造を作成するものが必要です。それがコンパイラです。コードジェネレーターではなくインタープリターに接続されていますが、すべて同じコンパイラーです。

それがコンパイラが最初に書かれた理由です。データ構造を解釈するという考え方は、コンパイラが考案されたときでも新しいものではありませんでしたが、コンパイラは、プログラマがそれらの構造をテキストから構築できる「ミッシングリンク」でした。


Appleの元の基本的なインタプリタ] [は、私が理解していることから、機械コードに手で翻訳されたものであり、機械読み取り可能なソースコード形式では存在しませんでした。あなたが言う「コンパイラ」がそれを生成するためにどのように使用されたかはわかりません。
supercat 14

@supercat:あなたが言及したBasicインタプリタがどのように生成されたかはわかりませんが、インタプリタを生成するために使用されるコンパイラについては話していません。インタプリタの一部であるコンパイラについて話している。そのコードの一部として、Apple] [BASICインタープリターは、BASICコードを含むテキストファイルを読み込み、そのテキストから構文ツリーを作成して実行する何らかの方法を必要とします。これを行うコードはコンパイラです。マシンコードは生成されませんが、コードを読み込んで別のフォームに変換するタスクを実行します。
スプーニエスト14

典型的なマイクロコンピューターのBASICインタープリターは、構文木に似たリモートでも何も生成しません。オリジナルのApple BASICインタープリター(「整数BASIC」と呼ばれます)に精通していませんが、MicrosoftによってAppleに実装されたBASICインタープリター(「Applesoft BASIC」)、Commodore、および2つのことを除いてプログラムテキストをそのまま保存したさまざまな企業:(1)各行の前に16ビットの行番号と次の行の16ビットのアドレスが続き、その後にゼロバイトが続きます。(2)各キーワードは、上位ビットが設定された単一バイトに置き換えられました。それ以外は、式が解析された...
supercat

...文字ごとに、左から右へ。以下のようなステートメントA = 1234"実行時の浮動小数点数に数字1、2、3、及び4に変換するであろう。
supercat

@supercat:それは構文木よりもバイトコードに近いように聞こえるので、その特定については間違っています。しかし、要点は今でも変わりません。擬似バイトコードはテキストから構築する必要があり、これを行うコードはコンパイラーです。
スプーニエスト14

-1

別の要因:最初のコンパイラーが作成されたとき、マシン時間のコストは現在よりもはるかに高くなりました。通訳者はより多くの機械時間を使用します。

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