In der Programmierung ist eine selbsttragende Programmiersprache (engl. self-hosted language) eine Computersprache, die in der Lage ist, ihren Compiler mittels ihrer selbst zu erzeugen. Der Compiler ist selbst in dieser Sprache geschrieben. Im weiteren Sinne werden auch andere Softwaresysteme als Programmiersprachen (und ihre Compiler) als selbsttragend bezeichnet, wenn diese Systeme bei ihrer eigenen Weiterentwicklung eingesetzt werden. Beispielsweise wird eine Versionsverwaltung selbsttragend, wenn sie zur Verwaltung ihres eigenen Quellcodes eingesetzt wird, oder ein Kernel wird selbsttragend, wenn er den Kern des Betriebssystems bildet, welches zur Entwicklung und Erzeugung des Kernels eingesetzt wird und mit seiner neuen Version ausgetauscht werden kann.
Eigenschaften und Erzeugung
Bevor ein Softwaresystem selbsttragend werden kann, muss es zuerst erzeugt werden. Da die Software zu ihrer eigenen Erzeugung jedoch noch nicht existiert, entsteht ein Henne-Ei-Problem, welches mit Bootstrapping gelöst wird. Dabei wird mindestens die erste Version des Computerprogramms (des Compilers) mittels eines anderen Compilers erzeugt. Erst, wenn der Compiler in der Lage ist, sich selbst aus seinem eigenen Quellcode zu erzeugen, gilt er als selbsttragend. So lange der Compiler in einer anderen Programmiersprache geschrieben ist, als die er selbst versteht, oder sogar auf einem (gänzlich) anderen System betrieben wird, als die Programme, die er erzeugt, spricht man von einem Cross-Compiler.
Typische Programmiersprachen für das Bootstrapping eines Compilers sind C/C++, Assembler, Python, Lua, Haskell und andere.
Ein Nachweis, ob eine Programmiersprache selbsttragend ist, kann über Idempotenz geführt werden: die Kompilierung des Compiler-Quellcodes, der in der Programmiersprache geschrieben ist, die der Compiler kompiliert, sollte einen Compiler erzeugen, mit dem der Compiler-Quellcode abermals kompiliert werden kann und einen identischen Compiler erzeugt.
Vorteile und Abgrenzung
Durch die Eigenschaft eines Compilers, seinen eigenen Quellcode kompilieren zu können und dabei ein Programm zu erzeugen, das mit diesem Compiler identisch ist, muss in der Entwicklung des Compilers kein separates System mehr eingesetzt werden, da das System für das Kompilieren identisch mit dem System für die Anwendung ist. Daraus ergibt sich, dass auch jede andere Software, die mit diesem Compiler geschrieben werden kann, auf dem gleichen System lauffähig ist und folgerichtig auch dort debuggt werden kann. Die Eigenschaft einer Programmiersprache, selbsttragend zu sein, ist demnach eine sehr wichtige Eigenschaft für die Entwicklung, den Betrieb und die Kompatibilität von Softwaresystemen, die in dieser Sprache geschrieben wurden.
Software, die Dateien erzeugt, welche mit einem Abspielprogramm ausgeführt werden, zählt nicht zu selbsttragenden Programmen. Hierzu zählen proprietäre Medienformate wie Microsoft PowerPoint oder Shockwave Flash, und streng genommen auch Programmiersprachen, die mit einer Laufzeitumgebung wie der Java-Laufzeitumgebung oder Common Intermediate Language als Zwischenschicht ausgeführt werden müssen, wenn diese Laufzeitumgebungen nicht auch selbst in dieser Programmiersprache geschrieben wurden. Die Familie der .NET-Programmiersprachen wurde erst mit der Entwicklung der .NET Compiler Platform (unter Nutzung der vorher in C++ geschriebenen Compiler im Bootstrapping) selbsttragend und (theoretisch) von dem Modell der mit ihnen verknüpften Laufzeitumgebung unabhängig.
Da JavaScript seine Ausführungsumgebung, eine virtuelle Maschine, nicht selbst erzeugt, ist JavaScript keine selbsttragende Programmiersprache. Anders verhält es sich mit TypeScript, einer echten Obermenge von JavaScript. Die TypeScript-Umgebung ist selbst in TypeScript geschrieben und erzeugt nativen JavaScript-Code. JavaScript kommt hier die Rolle des Betriebssystems für den TypeScript-Compiler und die mit ihm generierte Software zu.
Sprachen, die interpretiert werden müssen – zu denen die meisten Skriptsprachen gehören – sind nicht selbsttragend, wenn sie nicht in der Lage sind, auch einen Interpreter für sich selbst zu erzeugen, der in dieser Sprache geschrieben wurde. Je nach ihrem Funktionsumfang und ihren Möglichkeiten kann eine Skriptsprache eine solche Fähigkeit aber erwerben.
Geschichte
Die erste selbsttragende Programmiersprache (außer Assembler) wurde für Lisp von Hart und Levin am Massachusetts Institute of Technology im Jahr 1962 geschrieben.
„Der Compiler, wie er auf dem Compiler-Standardband existiert, ist ein Programm in Maschinensprache, das gewonnen werden konnte, indem die S-Ausdrucksdefinition des Compilers auf sich selbst durch den Interpreter angewendet wurde.“
Seitdem werden neue Programmiersprachen in der Regel mit dem Ziel geschrieben, dass sie im Laufe ihrer Entwicklung selbsttragend werden, wenn andere technische Gründe, die in ihrem Anwendungsbereich zu finden sind, dem nicht entgegenstehen. Selbsttragende Programmiersprachen sind turingmächtig.
Ken Thompson begann mit der Entwicklung von Unix im Jahr 1968 durch das Schreiben und Kompilieren von Programmen auf dem Großrechner GE-365 von General Electric und übertrug sie zum Testen zum schrankwandgroßen Minirechner PDP-7. Nachdem der erste Unix-Kernel mit einem Kommandozeileninterpreter, einem Texteditor, einem Assembler und einigen Dienstprogrammen vervollständigt wurde, war das Unix-Betriebssystem selbsttragend: Programme konnten auf dem PDP-7 selbst geschrieben und getestet werden, ohne den Großrechner und seine damals sehr teure Rechenzeit zu bemühen.
Douglas McIlroy schrieb auf einem Blatt Papier TMG, einen Compiler-Compiler: ein Programm, welches Compiler erzeugt. Er „entschied, seinem Blatt Papier sein Blatt Papier zu geben“, führte die Berechnung selbst durch und „compilierte“ einen TMG-Compiler in Assembler, welches er auf Ken Thompsons PDP-7 eingab.
Die Entwicklung des GNU-Systems verlässt sich hauptsächlich auf den GNU C-Compiler und den Texteditor Emacs. Das GNU-System ermöglicht so die selbst erhaltende und selbst pflegende Entwicklung von freier Software für das GNU-Projekt.
Liste von Sprachen mit selbsttragenden Compilern (Auswahl)
Die folgenden Programmiersprachen verwenden selbsttragende Compiler:
- C
- C++ (Visual C++, clang, gcc 4.8)
- C# (Microsoft Roslyn, Mono)
- ClojureScript
- CoffeeScript
- D
- Dart
- Eiffel
- Elixir
- F#
- FASM
- Go
- Haskell
- Kotlin
- Lisp (Common Lisp)
- Oberon
- OCaml
- Python (PyPy)
- QB64
- Rust
- Scala
- Smalltalk
- Standard ML
- Tcl
- TMG
- TypeScript
- Vala
- Virgil
- Visual Basic .NET (Microsoft Roslyn, Mono)
- Zig
Einzelnachweise
- ↑ Robert Heaton: What is a self-hosting compiler? In: robertheaton.com. 24. Oktober 2017, abgerufen am 5. November 2022 (englisch).
- ↑ Tim Hart, Mike Levin: AI Memo 39 – The new compiler. (PDF) In: publications.ai.mit.edu. 30. November 1995, archiviert vom am 13. Dezember 2020; abgerufen am 23. Mai 2008 (englisch, Benutzername: anonymous, Passwort: anonymous).
- ↑ Dennis M. Ritchie: The Development of the C Language. In: bell-labs.com. 1993, abgerufen am 5. November 2022 (englisch).
- ↑ Ken Thompson: Ken Thompson interviewed by Brian Kernighan at VCF East 2019 (ab 0:38:50) auf YouTube, 6. Mai 2019, abgerufen am 28. Oktober 2019 (englisch).
- ↑ David Nolen: ClojureScript Next. In: swannodette.github.io. 29. Juli 2015, abgerufen am 5. November 2022 (englisch).
- ↑ Tomasz Grysztar: flat assembler. In: flatassembler.net. Abgerufen am 7. Januar 2022 (englisch): „The flat assembler is self-hosting and the complete source code is included.“
- ↑ Ingo Wechsung et al.: Haskell Communities and Activities Report. In: haskell.org. Mai 2016, abgerufen am 5. November 2022 (englisch).
- ↑ Keith Nash: Implement TCL in TCL. In: wiki.tcl-lang.org. 29. Juni 2007, abgerufen am 19. September 2017 (englisch).
- ↑ Ben L. Titzer: virgil – A lightweight multi-paradigm programming language. In: code.google.com. Archiviert vom am 28. Dezember 2014; abgerufen am 27. Mai 2015 (englisch).