Warum werden selbsthostende Compiler als Übergangsritus für neue Sprachen angesehen?


30

Ich habe an einigen Stellen gehört, dass die Leute erwarten, dass Sprachen einen selbsthostenden Compiler verwenden oder zumindest haben, um Respekt zu verdienen.

Ich bin gespannt, warum das so ist. Ein Compiler scheint ein sehr wichtiges Stück Software zu sein, und ich stelle mir vor, dass nicht alle Sprachen gut dafür geeignet sind. Wäre es nicht sinnvoller, sich mit etwas zu befassen, das zu besseren Ergebnissen führt?


17
"Ein Compiler scheint ein sehr wichtiges Stück Software zu sein, und ich stelle mir vor, dass nicht alle Sprachen dazu geeignet sind." um zu beweisen, dass die Sprache der Aufgabe gewachsen ist.
Giorgio

13
Sofern es sich nicht um eine Spezialsprache handelt, ist eine Sprache, in der kein Compiler geschrieben werden kann, wahrscheinlich auch nicht für das geeignet, was ich tun möchte.
CodesInChaos

3
AFAIK, das gilt nicht immer für Fortran. Einige Fortran-Compiler (zB gfortranvon GCC ...) sind in Fortran nicht codiert.
Basile Starynkevitch

Antworten:


29

Wäre es nicht sinnvoller, sich mit etwas zu befassen, das zu besseren Ergebnissen führt?

Wie was?

Das Schöne an Compilern ist, dass sie nicht viele Abhängigkeiten haben. Dies macht sie zu guten Kandidaten für eine neue Sprache, die wahrscheinlich noch keine sehr große oder vielfältige Standardbibliothek hat.

Besser noch, sie erfordern eine Vielzahl von Dingen und sind gleichzeitig gut studiert. Die Vielfalt hilft sicherzustellen, dass Ihr Beispiel verschiedene Teile der Sprache testet. Gut studiert zu sein bedeutet, dass Sie andere Compiler haben, mit denen Sie sich vergleichen können - und dass Sie akademischen Sorten mehr Glaubwürdigkeit verleihen, wenn Sie wissen, was Sie tun.

Und während Compiler eine Menge Arbeit zu sein scheinen, sind sie im großen Stil der Dinge ziemlich klein. Wenn die Sprachimplementierer nicht einmal etwas tun können, was sie zuvor in der neuen Sprache getan haben, wie sollen sie dann neue Dinge tun? Wie werden sie mit den wirklich großen Dingen wie Standardbibliotheken oder einer IDE umgehen?


Nur als Randnotiz möchte ich erwähnen, dass es, obwohl nett, immer noch eine Vielzahl von Gründen gibt, warum ein Compiler in einer anderen Sprache geschrieben sein könnte. Zum Beispiel sind die meisten Javascript-Engines nicht in Javascript geschrieben. Dafür gibt es viele Gründe: Integration mit anderer Software, Verknüpfung mit vorhandenen Bibliotheken / Abhängigkeiten, überlegene Tools, Leistung, Legacy-Code ... Manchmal ist die Selbstkompilierung der Sprache nett, aber es ist trotzdem sinnvoll, den Core-Compiler in beizubehalten Ein weiterer. Die Sprache an sich macht jedoch Sinn. Normalerweise kann man es sich nicht leisten, ein gesamtes Ökosystem neu zu entwickeln.
dagnelies

2
@arnaud Und die Tatsache, dass ein Javascript-Compiler eine Javascript-Umgebung benötigen würde, die nicht in Javascript geschrieben werden kann, weil Javascript eine Javascript-Umgebung erfordert, <paradoxerweise wiederholen> , weil eine Javascript-Umgebung vom Betriebssystem nicht bereitgestellt wird (und wenn ja) war, es würde nicht in Javascript geschrieben werden).
Qix

3
@Qix en.wikipedia.org/wiki/Bootstrapping_%28compilers%29 Aber vor allem gibt es keinen Grund , es zu benutzen. Es ist weithin als schlechte Sprache bekannt. Browser können es nicht zum Kompilieren verwenden, weil sie die Situation unter Kontrolle haben :), während der Rest von uns im Web keine andere Wahl hat.
Den

3
Ich bin mir nicht so sicher, was die Behauptung angeht, dass es nicht viele Abhängigkeiten gibt. Das könnte für das Compiler- Frontend zutreffen . Sobald Sie jedoch einen AST haben, sieht es nicht nach einer vielversprechenden Route aus, wenn Sie Ihren eigenen Optimierer und Codegenerator rollen. Abgesehen von der Tatsache, dass moderne Optimierungstechniken ausgefeilte formale Logik-Engines erfordern, für die man möglicherweise eine Bibliothek eines Drittanbieters verwenden möchte, gibt es keinen Grund, das Rad für jede neue Sprache neu zu erfinden, anstatt auf einer branchenstärkeren Grundlage wie GCC aufzubauen oder LLVM.
5gon12eder

30

Das Ziel, einen Compiler in der Sprache zu haben, die gerade kompiliert wird, ist oft Teil der Praxis, " Ihr eigenes Hundefutter zu essen ". Es zeigt der Welt, dass Sie die Sprache, den Compiler und das Ökosystem der unterstützenden Module und Tools als "gut genug für ernsthafte Arbeit" oder "produktionsbereit" betrachten.

Es hat auch den tugendhaften Effekt, dass diejenigen, die der Sprache, dem Compiler und dem Laufzeitdesign am nächsten sind, gezwungen werden, sich direkt den Auswirkungen aller von ihnen getroffenen Entscheidungen und der von ihnen gewählten Entwicklungsprioritäten zu stellen - Warzen und alle. Dies führt häufig zu einer Kerngruppe, die nicht nur das Sprachumfeld in der Theorie versteht, sondern über umfangreiche praktische Erfahrung im Umgang mit der Sprache / den Werkzeugen im Schmelztiegel mit harten, realen Bedingungen verfügt.


1
Der Vollständigkeit halber : essen Sie Ihr eigenes Hundefutter ; siehe Hund gefüttert (Adj.) oder Hundefutter (Verb)
Qix

17

Menschen erschaffen neue Allzwecksprachen aus einem Hauptgrund: Sie hassen mindestens eine Sache an jeder anderen Sprache da draußen. Aus diesem Grund kommen so viele Sprachen nicht in Gang. Sie haben eine großartige Idee für eine Sprache, die Ihr Programmierleben verbessern würde, aber Sie müssen die erste Implementierung in einer Sprache vornehmen, die Sie in mindestens einer Hinsicht nervt. Selbsthosting bedeutet, dass Sie nicht mehr in dieser alten nervigen Sprache arbeiten müssen. Das ist der Grund, warum die Schöpfer einer Sprache auf diesen Schritt hinarbeiten und ihn als wichtigen Meilenstein betrachten.

Viele Sprachfunktionen sehen auf dem Papier gut aus, aber wenn Sie sie in einem realen Projekt einsetzen, werden Sie deren Einschränkungen bemerken. Zum Beispiel haben viele Sprachen zunächst keine angemessene Unicode-Unterstützung. Das Abschließen eines großen Projekts stellt sicher, dass viele dieser Situationen angetroffen und bewältigt wurden, und ein selbsthostender Compiler ist so gut wie jedes andere Projekt. Das ist der Grund, warum andere als die Schöpfer der Sprache dies als wichtigen Meilenstein ansehen.

Das heißt nicht, dass dies der einzige Meilenstein ist, den es zu beachten gilt. Es gibt Funktionen, die von einem Compiler nicht ausgeführt werden, z. B. Datenbankintegration, grafische Oberflächen, Vernetzung usw.


Ich bin der Meinung, dass eine (Muttersprache) eine Sprache ist, in der sie sich selbst kompilieren und auf die ein Linux-Kernel portiert werden kann (da sie die meisten / alle Aufgaben umfasst, die für das Funktionieren der meisten modernen Betriebssysteme erforderlich sind).
Qix

Eine anständige Unicode-Unterstützung ist jedoch nicht unbedingt erforderlich, um einen Compiler zu schreiben.
Paŭlo Ebermann

11

Steve Yegge hat einen großartigen Blog-Beitrag geschrieben , der sich etwas indirekt damit befasst.

Das Wichtigste: Compiler decken so ziemlich jeden Aspekt der Informatik ab. Es handelt sich um einen Kurs der Oberstufe, da Sie alle anderen Dinge, die Sie im Lehrplan für Informatik lernen, kennen müssen, um beginnen zu können. Datenstrukturen, Suche und Sortierung, asymptotische Performance, Grafikfärbung? Es ist alles drin.

Es gibt einen Grund, warum Knuth seit mehreren Jahrzehnten an seiner monumentalen (und nie endenden) "Kunst der Computerprogrammierung" arbeitet, obwohl sie als (nur) ein Compiler-Lehrbuch begann. Ebenso wie Carl Sagan sagte: "Wenn Sie einen Apfelkuchen von Grund auf neu machen wollen, müssen Sie zuerst das Universum erfinden." Wenn Sie einen Compiler schreiben wollen, müssen Sie sich zuerst mit fast allen Aspekten der Informatik befassen.

Das heißt, wenn der Compiler selbst gehostet ist, kann er mit ziemlicher Sicherheit das tun, was ich brauche, egal was ich tue. Umgekehrt, wenn Sie keinen Compiler in Ihrer Sprache geschrieben haben, besteht eine gute Chance, dass etwas übersehen wird, das für jemanden wirklich wichtig ist, da die Sprachimplementierer niemals ein Programm schreiben mussten, bei dem sie über all diese Probleme nachdenken müssten.

Großer Punkt # 2: Ab 30.000 Fuß sehen eine überraschende Anzahl von Problemen genau wie Compiler aus.

Compiler nehmen einen Strom von Symbolen, ermitteln ihre Struktur nach bestimmten domänenspezifischen vordefinierten Regeln und wandeln sie in einen anderen Symbolstrom um. Klingt ziemlich allgemein, nicht wahr? Gut ja.

Unabhängig davon, ob Sie Mitglied des Visual C ++ - Teams sind oder nicht, müssen Sie häufig etwas tun, das wie ein Teil eines Compilers aussieht. Ich mache es buchstäblich jeden Tag.

Im Gegensatz zu den meisten anderen Berufen verwenden Programmierer nicht nur Werkzeuge, sondern bauen ihre eigenen Werkzeuge. Ein Programmierer, der (aufgrund mangelnder Kenntnisse oder fehlender verwendbarer Werkzeuge zum Erstellen anderer Werkzeuge) keine Werkzeuge schreiben kann, ist für immer behindert und auf die Werkzeuge beschränkt, die jemand anderes bereitstellt.

Wenn eine Sprache zum Erstellen von Programmen "nicht gut geeignet" ist, die einen Strom von Symbolen aufnehmen, Regeln auf sie anwenden und ihn in einen anderen Strom von Symbolen umwandeln können, klingt dies nach einer ziemlich eingeschränkten Sprache und nicht nach einer, die nützlich wäre mir.

(Zum Glück gibt es nicht viele Programmiersprachen, die für die Transformation von Symbolen ungeeignet sind. C ist wahrscheinlich eine der schlechtesten Sprachen, die derzeit verwendet werden. C-Compiler sind jedoch in der Regel selbst gehostet, sodass sie niemanden aufhalten.)

Ein dritter Grund, mit dem ich aus persönlicher Erfahrung enden werde, der von Yegge nicht erwähnt wurde (weil er nicht über das "Warum Selbst-Host" schrieb): Es schüttelt Wanzen aus. Wenn Sie einen Compiler schreiben, bedeutet dies, dass Sie jedes Mal , wenn Sie ihn erstellen (nicht nur, wenn Sie ihn ausführen ), darauf angewiesen sind, dass er funktioniert und ordnungsgemäß mit einer Codebasis von angemessener Größe (dem Compiler selbst) verglichen wird.

In diesem Monat habe ich einen relativ neuen und berühmten Compiler verwendet, der nicht von mir selbst gehostet wird (Sie können sich wahrscheinlich vorstellen, welchen), und ich kann keine 2 Tage ohne Fehler in der Sache verbringen. Ich frage mich, wie viel die Designer tatsächlich verwenden mussten.


8

Wenn Sie möchten, dass ein Compiler für die Sprache X sich selbst hostet, müssen Sie ihn zuerst in einer anderen Sprache implementieren, z. B. Y, sodass er Eingaben für die Sprache X übernimmt und Assembler-Code oder Zwischencode oder sogar Code ausgibt Objektcode für den Computer, auf dem der Compiler ausgeführt wird. Sie möchten Sprache Y so ähnlich wie möglich zu Sprache X wählen, da Sie irgendwann in Y geschriebenen Code in X übersetzen.

Sie möchten jedoch nicht mehr vom Compiler in der Sprache Y schreiben als erforderlich. Zunächst implementieren Sie nur eine Teilmenge der Sprache, wodurch redundante Konstrukte eliminiert werden. Im Fall einer Sprache ‚C‘ Typs, während aber nicht für oder tun , während . wenn aber kein Fall oder tertiäre op. Keine Strukturen, Gewerkschaften oder Aufzählungen. Was Sie übrig haben, ist gerade genug von der Sprache, um einen Parser und einen rudimentären Codegenerator für die Sprache X zu schreiben. Überprüfen Sie dann die Ausgabe. Nochmal.

Sobald dies funktioniert, können Sie die Compilerquelle, die in Sprache Y geschrieben wurde, in Sprache X umschreiben und die Quelle der Sprache X mit dem Compiler kompilieren, der in Sprache Y geschrieben wurde. Die Ausgabe ist ein neuer Compiler, der in der neuen Sprache X geschrieben wurde Kompiliert die Sprache X, dh sie ist jetzt selbsthostend. Es ist jedoch nicht vollständig, da Sie nur eine Teilmenge der Sprache in der Sprache Y implementiert haben.

Nun fügen Sie die fehlenden Features hinzu und testen jedes (oder jede Gruppe von Features), die den richtigen Code generieren. dh sobald die Funktion im Compiler implementiert ist, können Sie Testprogramme mit den neuen Funktionen schreiben, kompilieren und testen, aber Sie sollten sie noch nicht in der Compiler-Quelle verwenden. Nachdem die neuen Funktionen überprüft wurden, können Sie diese neuen Funktionen in der Compiler-Quelle selbst verwenden. Ersetzen Sie möglicherweise einen Teil des in der Sprachuntermenge geschriebenen Originalcodes, und kompilieren Sie die Compiler-Quelle mithilfe der Version mit den neuen Funktionen neu.

Sie haben jetzt einen Mechanismus zum Hinzufügen neuer Features zur Sprache - und sobald die Codegenerierung für die Features korrekt überprüft wurde, können sie in der nächsten Generation des Compilers selbst verwendet werden.

Vor ungefähr 60 Jahren, als Computer zum ersten Mal vor Ort waren (und später, als Mikroprozessoren zum ersten Mal eintrafen), gab es keine anderen Sprachen, die für die Implementierung des anfänglichen Compilers geeignet wären. Die ersten Compiler mussten also in Assembler-Code geschrieben werden, und wenn genügend Compiler ausgeführt wurde, wurde der Assembler-Code durch die in einer neuen Sprache geschriebene Version ersetzt. Kein Assembler? Der gesamte Prozessor fiel eine weitere Ebene zurück, wobei der Assembler zunächst in Maschinencode geschrieben wurde .


2

Ist es möglich, eine Programmiersprache zu erstellen, die nicht für das Schreiben eines Compilers geeignet ist, aber für einen anderen Zweck geeignet ist?

Wenn ich mir eine Sprache wie SQL anschaue, ist die Antwort vermutlich ja. Sprachen dieser Art sind jedoch keine Allzwecksprachen.


1
Herausgefordert angenommen: Schreiben Sie einen C-Compiler in SQL.
Qix

2

Wer sagt das? ... jedenfalls ist es nur eine Meinung. Einige mögen zustimmen, andere nicht, hier gibt es kein Richtig oder Falsch. Einige Sprachen haben Compiler in sich geschrieben, andere nicht. Wie auch immer.

Trotzdem denke ich, dass es eine gute Übung / ein Proof-of-Concept ist, wenn eine Sprache sich selbst kompilieren kann ... es ist einfach ... schön ... und es beweist, dass die Sprache für einige komplexe Aufgaben geeignet ist.

Ich möchte auch erwähnen, dass es, obwohl nett, immer noch eine Vielzahl von Gründen gibt, warum ein Compiler in einer anderen Sprache geschrieben sein könnte. Zum Beispiel sind die meisten Javascript-Engines nicht in Javascript geschrieben. Dafür gibt es viele Gründe: Integration mit anderer Software, Verknüpfung mit vorhandenen Bibliotheken / Abhängigkeiten, überlegene Tools, Leistung, Legacy-Code ... Manchmal ist die Selbstkompilierung der Sprache nett, aber es ist trotzdem sinnvoll, den Core-Compiler in beizubehalten Ein weiterer. Die Sprache an sich macht jedoch Sinn. Normalerweise kann man es sich nicht leisten, ein gesamtes Ökosystem neu zu entwickeln.


2

Clang ist in C ++ geschrieben. Es wäre nicht allzu schwer, den Clang Objective-C-Compiler in Objective-C umzuschreiben, aber dann wäre es ziemlich nutzlos. Jede Änderung im C ++ - Compiler muss in Objective-C und umgekehrt wiederholt werden. Warum also?

Es gibt jetzt einen Clang Swift-Compiler. Sicherlich könnte dieser Compiler in Swift umgeschrieben werden. Aber welchen Zweck hätte es? Um zu demonstrieren, dass die Sprache mächtig genug ist, um einen Compiler darin zu schreiben? Es interessiert niemanden, ob Sie in Swift Compiler schreiben können. Die Leute kümmern sich darum, ob Sie Benutzeroberflächen in Swift schreiben können und dies nachweislich auch.

Wenn Sie einen gut getesteten Compiler haben, der leicht an das Kompilieren verschiedener Sprachen angepasst werden kann, ist es völlig sinnlos, ihn in verschiedene Sprachen umzuschreiben, es sei denn, das Umschreiben in einer anderen Sprache würde die Arbeit mit dem Compiler erleichtern. Und wenn es sinnvoll wäre, Clang beispielsweise in Swift zu schreiben, würden die Compiler für Clang C, C ++ und Objective-C alle in Swift geschrieben.

Es gibt wichtigere Dinge zu tun, als zu beweisen, dass Sie einen Compiler in einer Programmiersprache schreiben können.


1

Es zeigt, dass die Sprache in der Lage ist, komplexe Zeichenfolgen zu verarbeiten und in eine andere Sprache zu übersetzen / sich selbst zu interpretieren.

Bei der Erstellung eines Compilers (dem ersten großen Projekt) tritt ein Problem in den Vordergrund.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.