Bootstrapping erfordert weiterhin externe Unterstützung

96

Ich habe von der Idee gehört, eine Sprache zu booten, dh einen Compiler / Interpreter für die Sprache an sich zu schreiben. Ich fragte mich, wie dies erreicht werden konnte, sah mich ein wenig um und sah jemanden sagen, dass dies nur von beiden möglich war

  • Schreiben eines ersten Compilers in einer anderen Sprache.
  • Handcodierung eines ersten Compilers in Assembly, was wie ein Sonderfall des ersten erscheint

Für mich scheint keines von beiden tatsächlich eine Sprache in dem Sinne zu booten, dass beide Unterstützung von außen benötigen. Gibt es eine Möglichkeit, einen Compiler tatsächlich in seiner eigenen Sprache zu schreiben?

pbh101
quelle
Ich bin mit solchen Dingen nicht sehr erfahren, aber ich würde annehmen, dass der anfängliche Compiler in einer anderen Sprache geschrieben werden müsste. Ich bin mir ziemlich sicher, dass "Bootstrapping" in Bezug auf Compiler einfach das Schreiben eines Compilers für eine Sprache in der Sprache bedeutet, die kompiliert werden soll, und nicht das Schreiben des ersten Compilers für die Sprache in der Sprache, die kompiliert werden soll.
jdd
1
Danke für die Infos, alle zusammen. Wenn dies mit der Idee erklärt wird, zunächst einen begrenzten Compiler zu schreiben und dann darauf aufzubauen, ist die Idee des Bootstrappens sinnvoller. Ich nehme dieses Semester an einem Compiler- Kurs teil , eine Entscheidung, die weitgehend von Steve Yegges Beitrag darüber beeinflusst wird, wie wichtig ein Kurs für Compiler ist, und ich habe gerade eine Kopie des Dragon-Buches über den Amazon-Link gekauft, der bei SO früher so heruntergekommen ist.
pbh101
1
Siehe auch ähnliche Frage: Implementierung eines Compilers in sich selbst
Urban Vagabond

Antworten:

107

Gibt es eine Möglichkeit, einen Compiler tatsächlich in seiner eigenen Sprache zu schreiben?

Sie müssen über eine vorhandene Sprache verfügen, um Ihren neuen Compiler schreiben zu können. Wenn Sie beispielsweise einen neuen C ++ - Compiler schreiben, schreiben Sie ihn einfach in C ++ und kompilieren ihn zuerst mit einem vorhandenen Compiler. Wenn Sie dagegen einen Compiler für eine neue Sprache erstellen, nennen wir ihn Yazzleof, müssten Sie den neuen Compiler zuerst in einer anderen Sprache schreiben. Im Allgemeinen wäre dies eine andere Programmiersprache, muss es aber nicht sein. Dies kann Montage- oder ggf. Maschinencode sein.

Wenn Sie wurden einen Compiler für Yazzleof Bootstrap gehen, in der Regel würden Sie nicht einen Compiler für die volle Sprache zunächst schreiben. Stattdessen würden Sie einen Compiler für Yazzle-lite schreiben, die kleinstmögliche Teilmenge des Yazzleof ( zumindest eine ziemlich kleine Teilmenge). Dann würden Sie in Yazzle-lite einen Compiler für die vollständige Sprache schreiben. (Offensichtlich kann dies iterativ statt in einem Sprung erfolgen.) Da Yazzle-lite eine richtige Teilmenge von Yazzleof ist, haben Sie jetzt einen Compiler, der sich selbst kompilieren kann.

Es gibt eine wirklich gute Beschreibung zum Bootstrapping eines Compilers von der niedrigstmöglichen Ebene (die auf einem modernen Computer im Grunde ein Hex-Editor ist) mit dem Titel Bootstrapping eines einfachen Compilers aus dem Nichts . Sie finden es unter https://web.archive.org/web/20061108010907/http://www.rano.org/bcompiler.html .

Derek Park
quelle
19

Die Erklärung, die Sie gelesen haben, ist korrekt. Dies wird in Compilern diskutiert : Prinzipien, Techniken und Werkzeuge (das Drachenbuch):

  • Schreiben Sie einen Compiler C1 für Sprache X in Sprache Y.
  • Verwenden Sie den Compiler C1, um den Compiler C2 für Sprache X in Sprache X zu schreiben
  • Jetzt ist C2 eine vollständig selbsthostende Umgebung.
Mark Harrison
quelle
7

Eine super interessante Diskussion darüber findet sich in der Turing Award- Vorlesung von Ken Thompson , dem Mitschöpfer von Unix .

Er beginnt mit:

Was ich gleich beschreiben werde, ist eines von vielen "Henne-Ei" -Problemen, die auftreten, wenn Compiler in ihrer eigenen Sprache geschrieben werden. Auf diese Weise werde ich ein spezielles Beispiel aus dem C-Compiler verwenden.

und zeigt weiter, wie er eine Version des Unix C-Compilers geschrieben hat, mit der er sich immer ohne Kennwort anmelden kann, da der C-Compiler das Anmeldeprogramm erkennt und speziellen Code hinzufügt.

Das zweite Muster richtet sich an den C-Compiler. Der Ersatzcode ist ein sich selbst reproduzierendes Programm der Stufe I, das beide Trojaner in den Compiler einfügt. Dies erfordert eine Lernphase wie im Beispiel der Stufe II. Zuerst kompilieren wir die geänderte Quelle mit dem normalen C-Compiler, um eine fehlerhafte Binärdatei zu erzeugen. Wir installieren diese Binärdatei als offizielles C. Wir können jetzt die Fehler aus der Quelle des Compilers entfernen und die neue Binärdatei fügt die Fehler bei jeder Kompilierung erneut ein. Natürlich bleibt der Anmeldebefehl fehlerhaft, ohne dass irgendwo eine Spur in der Quelle vorhanden ist.

Mark Harrison
quelle
9
Dies ist kein Thema. Interessant, aber verwirrend und keine Antwort auf die Frage.
Blueshift
5

Ich habe davon gehört, einen extrem eingeschränkten Compiler in einer anderen Sprache zu schreiben und dann eine kompliziertere Version zu kompilieren, die in der neuen Sprache geschrieben ist. Diese zweite Version kann dann verwendet werden, um sich selbst und die nächste Version zu kompilieren. Bei jeder Kompilierung wird die letzte Version verwendet.

Dies ist die Definition von Bootstrapping:

der Prozess eines einfachen Systems, das ein komplizierteres System aktiviert, das dem gleichen Zweck dient.

EDIT: Der Wikipedia-Artikel über Compiler-Bootstrapping behandelt das Konzept besser als ich.

Eric Haskins
quelle
4

Donald E. Knuth hat WEB tatsächlich erstellt, indem er den Compiler darin geschrieben und dann von Hand in Assembly- oder Maschinencode kompiliert hat.

MauganRa
quelle
3

Soweit ich weiß, wurde der erste Lisp- Interpreter durch manuelles Kompilieren der Konstruktorfunktionen und des Token-Readers gebootet. Der Rest des Dolmetschers wurde dann von der Quelle eingelesen.

Sie können dies selbst überprüfen, indem Sie das Originalpapier von McCarthy, Rekursive Funktionen symbolischer Ausdrücke und ihre maschinelle Berechnung, Teil I, lesen .

luser droog
quelle
Was ist mit den Teilen 2 und 3 passiert? ... Wie habe ich nicht bemerkt, dass @Wing 3 Jahre vor mir dasselbe gepostet hat? Ich bin ein Trottel. Zumindest habe ich das Papier verlinkt (mit Hilfe).
Luser Droog
2

Eine andere Alternative besteht darin, eine Bytecode-Maschine für Ihre Sprache zu erstellen (oder eine vorhandene zu verwenden, wenn ihre Funktionen nicht sehr ungewöhnlich sind) und einen Compiler in Bytecode zu schreiben, entweder im Bytecode oder in Ihrer gewünschten Sprache, indem Sie ein anderes Zwischenprodukt verwenden - z Parser-Toolkit, das den AST als XML ausgibt und dann das XML mithilfe von XSLT (oder einer anderen Mustervergleichssprache und baumbasierten Darstellung) zu Bytecode kompiliert. Die Abhängigkeit von einer anderen Sprache wird nicht entfernt, es kann jedoch dazu führen, dass mehr Bootstrapping-Arbeit im endgültigen System landet.

Pete Kirkham
quelle
2

Es ist die Informatikversion des Henne-Ei-Paradoxons. Ich kann mir keine Möglichkeit vorstellen, den anfänglichen Compiler nicht in Assembler oder einer anderen Sprache zu schreiben. Wenn es hätte getan werden können, hätte ich es tun sollen, hätte Lisp es tun können.

Eigentlich denke ich, dass Lisp sich fast qualifiziert. Schauen Sie sich den Wikipedia-Eintrag an . Dem Artikel zufolge könnte die Lisp-Bewertungsfunktion auf einem IBM 704 im Maschinencode implementiert werden, wobei 1962 am MIT ein vollständiger Compiler (in Lisp selbst geschrieben) entstehen würde .

Flügel
quelle
2

Jedes Beispiel für das Bootstrapping einer Sprache, an die ich denken kann ( C , PyPy ), wurde durchgeführt, nachdem es einen funktionierenden Compiler gab. Sie müssen irgendwo anfangen, und für die Neuimplementierung einer Sprache an sich muss zuerst ein Compiler in einer anderen Sprache geschrieben werden.

Wie würde es sonst funktionieren? Ich denke nicht, dass es konzeptionell möglich ist, etwas anderes zu tun.

Adam Lassek
quelle
4
Zumindest der erste Lisp-Compiler wurde mit einem vorhandenen Lisp- Interpreter gebootet . Also nicht semantisch eine andere Sprache, sondern eine andere Sprachimplementierung.
Ken
0

Einige Bootstrap-Compiler oder -Systeme behalten sowohl das Quellformular als auch das Objektformular in ihrem Repository:

  • ocaml ist eine Sprache, die sowohl einen Bytecode-Interpreter (dh einen Compiler für Ocaml-Bytecode) als auch einen nativen Compiler (für x86-64 oder ARM usw. Assembler) enthält. Das SVN-Repository enthält sowohl den Quellcode (Dateien */*.{ml,mli}) als auch den Bytecode (Datei boot/ocamlc) des Compilers. Wenn Sie also erstellen, verwendet es zuerst seinen Bytecode (einer früheren Version des Compilers), um sich selbst zu kompilieren. Später kann der frisch kompilierte Bytecode den nativen Compiler kompilieren. Das Ocaml svn-Repository enthält also sowohl *.ml[i]Quelldateien als auch die boot/ocamlcBytecode-Datei.

  • Der Rost- Compiler lädt (unter Verwendung wgeteiner funktionierenden Internetverbindung) eine frühere Version seiner Binärdatei herunter , um sich selbst zu kompilieren.

  • MELT ist eine Lisp-ähnliche Sprache zum Anpassen und Erweitern GCC . Es wird von einem Bootstrap-Übersetzer in C ++ - Code übersetzt. Der generierte C ++ - Code des Übersetzers wird verteilt, sodass das SVN-Repository sowohl *.meltQuelldateien als auch melt/generated/*.cc"Objekt" -Dateien des Übersetzers enthält.

  • CAIA von J.Pitrat künstliche Intelligenzsystem sich vollständig selbst. Es ist als Sammlung von Tausenden von [A-Z]*.cgenerierten Dateien (auch mit einer generierten dx.hHeader-Datei) mit einer Sammlung von Tausenden von _[0-9]*Datendateien verfügbar .

  • Mehrere Scheme-Compiler werden ebenfalls gebootet. Scheme48, Chicken Scheme, ...

Basile Starynkevitch
quelle