Warum wurde der erste Compiler vor dem ersten Interpreter geschrieben?

72

Der erste Compiler wurde 1952 von Grace Hopper geschrieben, während der Lisp-Interpreter 1958 von John McCarthys Schüler Steve Russell geschrieben wurde. Das Schreiben eines Compilers scheint ein viel schwierigeres Problem zu sein als ein Interpreter. Wenn ja, warum wurde der erste Compiler sechs Jahre vor dem ersten Interpreten geschrieben?

anguyen
quelle
67
weil zu der Zeit mehr ein Compiler als ein Interpreter benötigt wurde
Ratschenfreak
23
Den ersten Dolmetscher kompilieren? : P (nur teilweise auf den Punkt gebracht, ein Interpreter ist komplex (mehr als ein einfacher Compiler) und es wäre böse, einen effizienten Code im Maschinencode zu schreiben)
Vality
4
Wenn Sie Ihre CPU-Ausführungsanweisungen als interpretierend ansehen, wie ich es sehe (jedoch über Hardware implementiert), ist die Behauptung, dass der erste Interpreter nach dem ersten Compiler geschrieben wurde, nicht gültig. Übrigens weiß ich, dass dies bei der Frage / Antwort nicht hilft. Es soll nur ein interessanter Kommentar zu einer anderen Sichtweise sein.
Pedro Henrique A. Oliveira
11
McCarthy hat den LISP-Dolmetscher nicht geschrieben. McCarthy erfand einen mathematischen Formalismus. Steve Russell, zu dieser Zeit einer der Studenten des MIT AI Lab, erkannte, dass er einen Dolmetscher schreiben konnte, um McCarthys ausgefallene Flüge durchzuführen, und der Rest ist Geschichte.
John R. Strohm
5
Tatsächlich hörte ich, dass McCarthy LISP für nicht umsetzbar hielt. Es war Russell, der erkannte , dass McCarthys Universal-Funktion aus der LISP Handbuch a) war ein Dolmetscher und b) war implementierbar.
Jörg W Mittag

Antworten:

97

Das Schreiben eines Compilers scheint ein viel schwierigeres Problem zu sein als ein Interpreter.

Das mag heute stimmen, aber ich würde behaupten, dass dies vor etwa 60 Jahren nicht der Fall war. Ein paar Gründe warum:

  • Mit einem Interpreter müssen Sie es und das Programm im Speicher behalten. In einer Zeit, in der 1 KB Speicher ein gewaltiger Luxus war, war es entscheidend, den Speicherbedarf gering zu halten. Und das Dolmetschen benötigt etwas mehr Speicher als das Ausführen eines kompilierten Programms.
  • Moderne CPUs sind äußerst komplex und enthalten riesige Kataloge von Anweisungen. Das Schreiben eines guten Compilers ist also eine echte Herausforderung. Alte CPUs waren viel einfacher, so dass sogar die Kompilierung einfacher war.
  • Moderne Sprachen sind viel komplexer als alte Sprachen, so dass selbst Compiler viel komplexer sind. Alte Sprachen hätten also einfachere Compiler.
Euphorisch
quelle
65
und ohne compiler müsste man den dolmetscher in montage schreiben
ratschenfreak
34
Die ersten Compiler waren Menschen. (Wenn Leute Dolmetscher sind, brauchen wir keine Computer). Dann muss jemand darüber nachgedacht haben, einen Compiler in einer kompilierten Sprache zu schreiben (die einzigen, die sie hatten, aber zu der Zeit, als meine Menschen kompiliert wurden).
Strg-Alt-Delor
1
Eigentlich ... Ich habe kürzlich gelesen, dass der Apollo Guidance Computer, der in den 60er Jahren bei Mondflügen verwendet wurde, einen Interpreter hatte: Wiki-Eintrag "... der Interpreter lieferte viel mehr Anweisungen, als AGC nativ unterstützte ..." Ich nehme an, dieser "Interpreter" war eher wie der "Sweet 16" -Interpreter in alten Apple II-Computern als so etwas wie LISP.
Calphool
6
@ratchetfreak Und es war. Da waren die ersten Compiler.
RBarryYoung
3
@richard: Als Menschen Dolmetscher / Taschenrechner waren, hieß ihre Berufsbezeichnung "Computer". Wenn Menschen Dolmetscher waren, waren sie buchstäblich die Computer. Das Manhattan-Projekt beschäftigte Tausende von "Computern" (tatsächliche Berufsbezeichnung, ernsthaft), an die die Kernphysiker ihre Berechnungen per Post zur Ausführung schickten. Tatsächlich beschäftigte das Projekt auch Mathematiker, die die Berechnungen von den Ingenieuren aufschlugen, die die Berechnungen aus den Theorien der Physiker formulierten, die an die "Computer" geschickt werden sollten.
Slebetman
42

Der grundlegende Punkt ist, dass die Computerhardware-Umgebung der 1950er Jahre es so machte, dass damals nur ein Compiler durchführbar war, da Computer stapelweise verarbeitet wurden.

Zu dieser Zeit beschränkten sich die besseren Benutzeroberflächen hauptsächlich auf Lochkarten und Fernschreiber . Im Jahr 1961 wurde das SAGE-System das erste Kathodenstrahlröhren-Display (CRT) auf einem Computer. Daher war die Interaktivität eines Dolmetschers erst viel später vorzuziehen oder selbstverständlich.

In den 1950er Jahren verwendeten zahlreiche Computer Schalter auf der Vorderseite, um Anweisungen zu laden, und die Ausgabe bestand lediglich aus Reihen von Lampen / LEDs. In den 1970er Jahren verwendeten Bastler sogar Schalter und LEDs auf der Vorderseite. Vielleicht kennen Sie den berüchtigten Altair 8800 .

Andere Hardwareeinschränkungen machten auch Dolmetscher unmöglich. In den 1950er Jahren gab es die extrem begrenzte Verfügbarkeit von Primärspeicher (z. B. RAM) in Computern. Vor der integrierten Halbleiterschaltung (die erst 1958 eingeführt wurde) war der Speicher auf einen Magnetkernspeicher oder einen Verzögerungsleitungsspeicher beschränkt, der in Bits oder Worten ohne Präfix gemessen wurde . In Verbindung mit der Langsamkeit des sekundären Speichers (z. B. Festplatte oder Band) würde es als verschwenderisch angesehen, wenn nicht unmöglich wäre, viel Speicher für den Interpreter zu verwenden, noch bevor das zu interpretierende Programm geladen wurde.

Speicherbeschränkungen waren nach wie vor ein wichtiger Faktor, als das von John Backus bei IBM geleitete Team 1954-57 den FORTRAN-Compiler erstellte. Dieser innovative Compiler war nur deshalb erfolgreich, weil er ein optimierender Compiler war .

Die meisten Computer in den 1950er Jahren verfügten kaum über ein Betriebssystem, geschweige denn über moderne Funktionen wie dynamische Verknüpfung und virtuelle Speicherverwaltung. Die Idee eines Interpreters war zu dieser Zeit zu radikal und unpraktisch.

Nachtrag

Die Sprachen der 1950er Jahre waren primitiv. Sie umfassten nur eine kleine Handvoll Operationen, die häufig entweder von den Anweisungen der zugrunde liegenden Hardware oder von der Problemdefinition ihrer gezielten Verwendung beeinflusst wurden.

Zu dieser Zeit waren Computer selten Universalcomputer in dem Sinne, wie wir sie heute von Computern kennen. Dass sie umprogrammierbar waren, ohne dass sie neu erstellt werden mussten, galt als revolutionäres Konzept. Früher verwendeten die Menschen elektromechanische Maschinen (normalerweise Taschenrechner), um Antworten zu berechnen oder zu berechnen (die meisten Anwendungen in den 1950er-Jahren waren numerischer Natur).

Compiler und Dolmetscher sind aus Sicht der Informatik sowohl Übersetzer als auch in etwa gleich komplex in der Implementierung.

Mctylr
quelle
Haben Computer vor dem Aufkommen von Time-Sharing Teletypen verwendet? Ich hätte erwartet, dass sie entweder Zeilendrucker oder Spool-to-Tape verwenden. Andernfalls würden die 1 bis 8 Sekunden, die der Computer nach jeder Textzeile warten müsste, 1 bis 8 Sekunden bedeuten, die der Computer hätte tun können, aber nicht getan hätte.
Supercat
2
@supercat - ja, es wurden Teletypen verwendet, aber sie waren alles andere als "interaktiv". Der erste Computer, den ich programmierte, hatte einen Speicher, der aus 18-Bit-Wörtern bestand - 1K davon. Der Speicher selbst war eine rotierende Trommel . Wenn Sie also den Computer einschalten, müssen Sie warten, bis der Speicher voll ist. Es war ein Teletyp beigefügt, und Sie konnten A) ein Zeichen lesen, das entweder über die Tastatur eingegeben oder vom Papierstreifenlesegerät gelesen wurde (aus der Sicht des Computers waren beide gleich), B) ein Zeichen in den "Drucker" schreiben "des Teletyps. Ah, tolle Tage - tolle Tage ..! IST MEIN GRUEL NOCH WARM?!?!? :-)
Bob Jarvis
@ BobJarvis: In welchem ​​Jahr wäre das gewesen?
Supercat
1
@supercat - 1973 - aber der fragliche Computer (ein EDP-18 von Educational Data Products) war schon damals relativ älter. Dennoch war es , was wir hatten (und haben alle mit dem Computer zu Chaos in der High School in den frühen Mitte der 70er Jahre war ungewöhnlich) so , wie wir dachten , es ist ziemlich erstaunlich war. :-)
Bob Jarvis
2
Dies ist eine viel bessere und vollständigere Antwort als die akzeptierte.
Jim Garrison
12

Die ersten Programmiersprachen waren recht einfach (zum Beispiel keine Rekursion) und näherten sich der Maschinenarchitektur an, die selbst einfach war. Die Übersetzung war dann ein unkomplizierter Prozess .

Ein Compiler war einfacher als ein Interpreter, der sowohl die Daten für die Programmausführung als auch die Tabellen für die Interpretation des Quellcodes zusammenhalten musste. Und der Interpreter würde mehr Platz für sich selbst, für Programmquellcode und für Symboltabellen beanspruchen.

Der Speicher könnte (aus Kosten- und Architekturgründen) so knapp sein, dass Compiler eigenständige Programme sein könnten, die das Betriebssystem überschreiben (ich habe eines dieser Programme verwendet). Das Betriebssystem musste nach dem Kompilieren neu geladen werden, um das kompilierte Programm auszuführen. ... was klar macht, dass es einfach keine Option war, einen Dolmetscher für die eigentliche Arbeit einzusetzen .

Die von Compilern geforderte Einfachheit war allerdings so, dass die Compiler nicht sehr gut waren (Codeoptimierung steckte, wenn überhaupt, noch in den Kinderschuhen). Handgeschriebener Maschinencode hatte zumindest bis in die späten sechziger Jahre den Ruf, wesentlich effizienter zu sein als vom Compiler generierter Code. Es gab sogar ein Konzept des Code-Erweiterungsverhältnisses , das die Größe des kompilierten Codes mit der Arbeit eines sehr guten Programmierers verglich. Bei den meisten (allen?) Compilern war sie normalerweise größer als 1, was langsamere Programme und, was noch wichtiger ist, größere Programme, die mehr Speicher benötigen, bedeutete. Dies war noch in den sechziger Jahren ein Thema.

Das Interesse des Compilers lag in der einfachen Programmierung, insbesondere für Benutzer, die keine Computerspezialisten waren, wie z. B. Wissenschaftler auf verschiedenen Gebieten. Dieses Interesse galt nicht der Code-Performance. Die Zeit der Programmierer galt damals jedoch als billige Ressource. Die Kosten lagen in Computerzeit, bis 1975-1980, als die Kosten von Hardware zu Software wechselten. Das bedeutet, dass selbst Compiler von einigen Profis nicht ernst genommen wurden .

Die sehr hohen Kosten für Computerzeit waren ein weiterer Grund für die Disqualifizierung von Dolmetschern , sodass die Idee für die meisten Menschen lächerlich gewesen wäre.

Der Fall von Lisp ist sehr speziell, weil es eine extrem einfache Sprache war, die es machbar machte (und der Computer war in 58 ein bisschen größer geworden). Noch wichtiger ist, dass der Lisp-Interpreter ein Proof of Concept in Bezug auf die Selbstdefinierbarkeit von Lisp ( Meta-Zirkularität ) war, unabhängig von jeglicher Frage der Benutzerfreundlichkeit.

Der Erfolg von Lisp beruht hauptsächlich auf der Tatsache, dass diese Selbstdefinierbarkeit es zu einem hervorragenden Prüfstand für das Studium von Programmierstrukturen und das Entwerfen neuer Sprachen machte (und auch für die Bequemlichkeit der symbolischen Berechnung).

babou
quelle
3
Oh, wie kühn .
Pharap
@Pharap Ist das ein falscher Stil? Mein Ziel ist es, die Suche nach wichtigen Informationen zu vereinfachen und gleichzeitig einen freieren Stil als die einfache Aufzählung von Fakten zu ermöglichen. Ich muss gestehen, dass es auf dieser SE-Site nicht wirklich sehr effektiv zu sein scheint.
Babou
@ anonymous-downvoter Downvoting ohne einen erklärenden Kommentar zeigt, dass jemand dumm sein kann. Es sagt jedoch nicht, wer.
Babou
4

Ich bin mit der Prämisse der Frage nicht einverstanden.

Der erste Compiler von Adm. Hopper (die A-0) war eher ein Linker oder eine Makrosprache. Sie speicherte Unterprogramme auf einem Band (jedem wurde eine Nummer zugewiesen) und ihre Programme wurden als Liste von Unterprogrammen und Argumenten geschrieben. Der Compiler kopierte die angeforderten Unterprogramme vom Band und ordnete sie in ein vollständiges Programm um.

Sie benutzte das Wort "kompilieren" in demselben Sinne, wie man eine Gedichtsammlung zusammenstellt: verschiedene Gegenstände in einem Band zusammenfassen.

Dieser erste Compiler hatte meines Erachtens keinen Lexer oder Parser, was ihn zu einem entfernten Vorfahren eines modernen Compilers macht. Später erstellte sie einen weiteren Compiler (den B-0, auch bekannt als FLOW-MATIC) mit dem Ziel einer eher englischen Syntax, die jedoch erst 1958 oder 1959 - ungefähr zur gleichen Zeit wie der Lisp-Interpreter - fertiggestellt wurde.

Daher denke ich, dass die Frage selbst ein bisschen falsch ist. Es scheint, dass sich Compiler und Interpreten fast genau zur selben Zeit zusammen entwickelten, zweifelsohne aufgrund des Gedankenaustauschs, an dem viele Wissenschaftler damals in der gleichen Richtung gedacht hätten.

Eine bessere Antwort mit Zitaten hier: https://stackoverflow.com/a/7719098/122763 .

Mark E. Haase
quelle
3

Der andere Teil der Gleichung ist, dass Compiler eine schrittweise Abstraktion über einem Assembler waren. Zuerst hatten wir fest codierten Maschinencode. "Wir" waren der Assembler. Jeder Sprung, jeder Versatz usw. wurde von Hand in hexadezimal (oder oktal) berechnet und dann in Papierstreifen oder Karten gestanzt. Als Monteure auf die Bühne kamen, war dies eine enorme Zeitersparnis. Der nächste Schritt waren Makro-Assembler. Dies gab die Möglichkeit, ein Makro zu schreiben, das zu einem Satz von Maschinenanweisungen erweitert werden würde. Fortran und Cobol waren also ein großer Schritt vorwärts. Der Mangel an Ressourcen (Speicher, Speicher und CPU-Zyklen) bedeutete, dass Universalinterpreter auf das Wachstum der Technologie warten mussten. Die meisten frühen Interpreter waren Bytecode-Engines (wie Java oder CLR von heute, aber mit viel weniger Fähigkeiten). UCSD Pascal war eine sehr beliebte (und schnelle) Sprache. MS Basic war eine Bytecode-Engine unter der Haube.

Bezüglich des Anweisungsaufwands hing es völlig davon ab, welcher Prozessor ausgeführt wurde. Die Branche erlebte eine Weile einen großen RISC-gegen-CISC-Aufruhr. Ich schrieb persönlich Assembler für IBM, Data General, Motorola, Intel (als sie auftauchten), TI und mehrere andere. Es gab einen ziemlich signifikanten Unterschied bei Befehlssätzen, Registern usw., der beeinflussen würde, was zum "Interpretieren" eines p-Codes erforderlich ist.

Als Zeitreferenz begann ich um 1972 in der Telefongesellschaft zu programmieren.

Bill Brothers
quelle
2

Wenn Sie nicht alles im Speicher haben, ist der kompilierte Code viel schneller. Vergessen Sie nicht, dass in diesen Zeiten Funktionen mit dem kompilierten Code verbunden wurden. Wenn Sie nicht kompilieren, wissen Sie nicht, welche Funktionen Sie benötigen. Sie rufen also Funktionen auf von ... Oh, noch nicht von der Festplatte, wir sind in den frühen 50ern, aber von Karten! Zur Laufzeit!

Es ist natürlich möglich, Problemumgehungen zu finden, aber sie wurden noch nicht gefunden, da die Sprachen sehr einfach und nicht so weit vom Maschinencode entfernt waren. Das Kompilieren war einfach und ausreichend.

Gangnus
quelle
1

Bevor der erste Compiler geschrieben wurde, wurde Assembler-Code geschrieben, was im Vergleich zu reinem Binärcode ein enormer Fortschritt war. Damals gab es ein starkes Argument dafür, dass Code, der von einem Compiler kompiliert wurde, weniger effizient als Assembler-Code ist - damals war das Verhältnis von (Kosten für Computer) zu (Kosten für Programmierer) sehr viel anders als heute. Aus dieser Sicht gab es also starken Widerstand gegen Compiler.

Aber Compiler sind sehr viel effizienter als Dolmetscher. Wenn Sie zu diesem Zeitpunkt vorgeschlagen hätten, einen Dolmetscher zu schreiben, hätten die Leute Sie für verrückt gehalten. Können Sie sich vorstellen, einen Millionen-Dollar-Computer zu kaufen und dann 90% seiner Leistung für die Interpretation von Code zu verschwenden?

gnasher729
quelle
Ich weiß nicht viel über Computer der 1950er Jahre, aber zumindest für die einfachen von Neumann-Maschinen der späteren Jahrzehnte würde der Interpreter-Overhead zwei bis fünf Anweisungen (möglicherweise vier bis zehn Zyklen insgesamt) pro interpretierter Anweisung betragen: Decodieren, indirekter Sprung, möglicherweise Decodieren zusätzliche Argumente. Wenn Sie den interpretierten Befehlssatz ausreichend hoch ansetzen (so dass Sie mehrere Maschinenbefehle pro Interpreterbefehl ausführen), wäre dies weniger als 90% und möglicherweise sogar akzeptabel. Siehe auch: Forth.
3
Bevor der erste Compiler geschrieben wurde, wurde der Großteil der Programme tatsächlich in tatsächlichem Maschinencode und nicht in Assemblersprache (Op-Code-Mnemonik) geschrieben.
Mctylr
2
@delnan Diese Systeme liefen mit Uhren im Kilohertz-Bereich. Eine Verschwendung von 3-5-facher Leistungsreduzierung würde wahrscheinlich den Unterschied zwischen dem erfolgreichen Abschluss des Programms und dem Ausfall des Systems aufgrund eines Hardwarefehlers (dh durchgebrannte Vakuumröhre) ausmachen. Hardware-Ausfälle waren in den 1950er Jahren ein tägliches Ereignis, wenn ich mich recht entsinne.
Mctylr
delnan: Zeig mir einen Dolmetscher, der mit fünf Instruktionen dolmetschen kann. Und Forth ist keine interpretierte Sprache, es ist ein Greuel :-). Entschuldigung, ich meine eine Thread-Sprache. So etwas wie BASIC benötigt eine Unmenge von Anweisungen, um eine Aussage zu interpretieren.
gnasher729
@gnasher: 1974 habe ich einen leistungsstarken BASIC-Interpreter für Keronix (ähm, Data General Nova-Klone) erstellt, der einen byteorientierten P-Code zum Codieren der BASIC-Anweisung verwendete. Es dauerte ungefähr 25-50 Maschinenbefehle, um einen pCode "zu interpretieren", 10 davon für den Byte-Abruf selbst. (Ich habe ein Token basierend im Jahr 1969 erstellt, das mehr Zeit in Anspruch nahm, weil die Ausdrücke tatsächlich neu analysiert werden mussten.) Aber es war und ist nicht "Gazillions".
Ira Baxter
1

Bevor ein Schleifenprogramm interpretiert werden kann, muss es auf einem Medium gespeichert werden, das wiederholt gelesen werden kann. In den meisten Fällen ist RAM das einzig geeignete Medium. Da Code in der Regel auf Lochkarten eingegeben wird, die - für vom Menschen lesbare Sprachen - wahrscheinlich weitgehend leer sind, muss eine Verarbeitung des Codes durchgeführt werden, bevor er im RAM gespeichert wird. In vielen Fällen ist die Verarbeitung des Lochkartentextes zu einem Formular, das für die direkte Ausführung durch den Verarbeiter geeignet ist, nicht wirklich schwieriger als die Verarbeitung zu einem Formular, das über einen Interpreter effizient gehandhabt werden kann.

Beachten Sie, dass das Ziel der frühen Compiler nicht darin bestand, eine Assembler- oder Objektcodedatei auf der Festplatte zu erstellen, sondern Code im Arbeitsspeicher zu speichern, der zur Ausführung bereit war. Dies ist überraschend einfach, wenn kein Betriebssystem im Weg ist. Ein Compiler kann Code generieren, der an einem Ende des Speichers beginnt, und Variablen und Verzweigungsziele zuweisen, die am anderen Ende beginnen. Wenn eine Anweisung mit dem Label "1234" gekennzeichnet ist, speichert der Compiler in der Variablen "1234" eine Anweisung, um zur aktuellen Codegenerierungsadresse zu springen, und erstellt diese Variable, falls sie nicht vorhanden ist. Eine Anweisung "goto 1234" erzeugt eine Variable "1234", wenn sie nicht existiert, und springt dann zu dieser Variablen [die hoffentlich einen Sprung zu der richtigen Position hat, die darin gespeichert ist, bevor diese Anweisung ausgeführt wird].gotoEin Label, das noch nicht definiert wurde, da es weiß, wann die gotoCompiles zu einer Variablen springen werden. Dies ist möglicherweise nicht die effizienteste Methode zum Generieren von Code, entspricht jedoch der Größe der Programme, die von Computern erwartet wurden.

Superkatze
quelle
1
Platte? Ummmm ... nein. Band. Große, langsame Bänder von Rolle zu Rolle. Und viele von ihnen. Ich erinnere mich an einen Vortrag von Grace Murray Hopper (doppelt interessant für mich, weil ich ein Major für Systemanalyse und ein Midshipman in der Navy ROTC-Abteilung auf dem Campus war und CAPT Hopper ein dienender Marineoffizier). Sie erzählte eine Geschichte, in der sie auf die Idee kam, ungenutzte Teile eines Programms auf Band zu schreiben - sie nannte es "Verwendung von Zusatzspeicher". "Aber", sagte sie, "die Idee hat sich erst durchgesetzt, als IBM dasselbe tat und es Virtual Memory nannte." CAPT Hopper mochte IBM wirklich nicht ... :-)
Bob Jarvis
@ BobJarvis: Ich hatte diesen Aspekt nicht berücksichtigt, aber das gleiche allgemeine One-Pass-Design, das zum Kompilieren von einsatzbereitem Code für den Arbeitsspeicher verwendet wird, könnte mit einem Bandlaufwerk gut funktionieren. Die Ausgabe vom Compiler würde auf Band gehen, dann würde das Band zurückgespult und in sequentielle Speicheradressen eingelesen und direkt ausgeführt, ohne dass ein Teil des Compilers gleichzeitig im Speicher sein muss.
Supercat
0

Weil Dolmetscher Compiler brauchen, um arbeiten zu können.

Die obige Aussage ist nicht wirklich wahr. Streng genommen Sie können einen Dolmetscher machen , ohne jemals mit oder auf andere Weise mit einem Compiler interagieren. Aber die Ergebnisse würden nicht so aussehen, wie ich es mit diesen Begriffen meine.

Compiler und Interpreten machen im engeren Sinne ganz andere Dinge. Ein Compiler liest Text aus einer Quelle und wandelt ihn in ein anderes Format um: Assemblersprache, Maschinencode, eine andere Hochsprache, eine Datenstruktur oder was auch immer. Währenddessen nimmt ein Interpreter eine Datenstruktur auf und führt darauf basierende Anweisungen aus.

Was wir heutzutage tendenziell als "Compiler" betrachten, ist ein Compiler, der mit einem Codegenerator gekoppelt wurde : Ein Programm, das Daten aus einer Quelle aufnimmt und Code in einem bestimmten Format ausgibt, basierend auf dem, was es sieht. Das ist eine ziemlich intuitive Verwendung für Compiler, und es war eines der ersten Dinge, für die Compiler erstellt wurden. Aber wenn Sie es anders sehen, scheint dies dem, was ein Dolmetscher tut, sehr ähnlich zu sein. Es wird immer Code ausgegeben, anstatt allgemeinere Operationen auszuführen, aber das Prinzip ist dasselbe.

Wenn wir es von der anderen Seite betrachten, muss ein Dolmetscher seine Daten von irgendwoher abrufen . Dies sind nur Daten, so dass Sie sie auf die gleiche Weise aufbauen können, wie Sie andere Arten von Daten aufbauen würden. Da es sich um eine Interpretation handelt, ist es selbstverständlich, dass Sie Ihre Daten auf der Grundlage von Anweisungen in einer Textdatei erstellen können. Aber um das zu tun, müssten Sie etwas in den Text lesen und Ihre Datenstruktur erstellen, und das ist ein Compiler . Es ist an den Interpreter angeschlossen, nicht an einen Codegenerator, aber es ist trotzdem ein Compiler.

Deshalb wurden zuerst Compiler geschrieben. Die Idee, Datenstrukturen zu interpretieren, war nicht neu, selbst wenn Compiler konzipiert wurden, aber Compiler waren das "fehlende Bindeglied", mit dem Programmierer diese Strukturen aus Text erstellen konnten.

Der Löffeligste
quelle
Der ursprüngliche Basic-Interpreter für Apple wurde meines Wissens von Hand in Maschinencode übersetzt und existierte nie im maschinenlesbaren Quellcode-Format. Ich bin mir nicht sicher, mit welchem ​​"Compiler" Sie es erstellt haben.
Supercat
@supercat: Ich weiß nicht, wie der von Ihnen erwähnte Basic-Interpreter erstellt wurde, aber ich spreche nicht über Compiler, die zur Erstellung von Interpreten verwendet wurden. Ich spreche von den Compilern, die Teil von Dolmetschern sind. Als Teil seines Codes benötigt der Apple BASIC-Interpreter eine Möglichkeit, die Textdateien mit BASIC-Code einzulesen und aus diesem Text einen Syntaxbaum zu erstellen, den er dann ausführt. Der Code, der dies ausführt, ist ein Compiler. Es wird kein Maschinencode generiert, es werden jedoch weiterhin die Aufgaben ausgeführt, den Code einzulesen und in ein anderes Formular zu übersetzen.
The Spooniest
Typische Mikrocomputer-BASIC-Interpreter erzeugen nichts, das auch nur annähernd einem Syntaxbaum ähnelt. Ich bin nicht mit dem ursprünglichen Apple BASIC-Interpreter (genannt "Integer BASIC") vertraut, aber der von Microsoft für Apple ("Applesoft BASIC"), Commodore und verschiedenen anderen Firmen implementierte BASIC-Interpreter speichert Programmtext wie er ist, abgesehen von zwei Dingen : (1) jeder Zeile wurde eine 16-Bit-Zeilennummer und die 16-Bit-Adresse der nächsten Zeile vorangestellt, gefolgt von einem Null-Byte; (2) Jedes Schlüsselwort wurde durch ein einzelnes Byte ersetzt, bei dem das hohe Bit gesetzt war.
Davon abgesehen
... Zeichen für Zeichen von links nach rechts; Eine Anweisung wie A = 1234 "würde die Ziffern 1, 2, 3 und 4 zur Laufzeit in eine Gleitkommazahl
umwandeln
@supercat: Das klingt dann näher an einem Bytecode als an einem Syntaxbaum, also irre ich mich in diesem Punkt. Der wichtigste Punkt bleibt jedoch bestehen: Der Pseudo-Byte-Code muss immer noch aus Text bestehen, und der Code, der dies tut, ist ein Compiler.
The Spooniest
-1

Ein weiterer Faktor: Als die ersten Compiler geschrieben wurden, waren die Kosten für die Maschinenzeit viel höher als jetzt. Dolmetscher benötigen viel mehr Maschinenzeit.

Loren Pechtel
quelle