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?
history
compiler
interpreters
anguyen
quelle
quelle
Antworten:
Das mag heute stimmen, aber ich würde behaupten, dass dies vor etwa 60 Jahren nicht der Fall war. Ein paar Gründe warum:
quelle
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.
quelle
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).
quelle
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 .
quelle
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.
quelle
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.
quelle
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?
quelle
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].
goto
Ein Label, das noch nicht definiert wurde, da es weiß, wann diegoto
Compiles 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.quelle
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.
quelle
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.
quelle