Glasgow Haskell-Compiler - Glasgow Haskell Compiler

Der Glasgow Haskell Compiler
Originalautor(en) Kevin Hammond
Entwickler Das Glasgow Haskell-Team
Erstveröffentlichung Dezember 1992 ( 1992-12 )
Stabile Version
9.0.1  Bearbeiten Sie dies auf Wikidata / 4. Februar 2021 ; vor 7 Monaten ( 4 Februar 2021 )
Repository
Geschrieben in Haskell und C
Betriebssystem Linux , OS X 10.7 Lion und höher, iOS , Windows 2000 und höher, FreeBSD , Solaris 10 und höher
Plattform x86 , x86-64 , ARM
Verfügbar in Englisch
Typ Compiler
Lizenz Neue BSD-Lizenz
Webseite www .haskell .org / ghc /

Die Glasgow Haskell Compiler ( GHC ) ist ein Open-Source - nativen Code - Compiler für die funktionale Programmierung Sprache Haskell . Es bietet eine plattformübergreifende Umgebung zum Schreiben und Testen von Haskell-Code und unterstützt zahlreiche Erweiterungen, Bibliotheken und Optimierungen, die den Prozess der Codegenerierung und -ausführung rationalisieren. GHC ist der am häufigsten verwendete Haskell-Compiler. Die leitenden Entwickler sind Simon Peyton Jones und Simon Marlow .

Geschichte

GHC begann ursprünglich 1989 als Prototyp, geschrieben in LML (Lazy ML) von Kevin Hammond an der University of Glasgow . Später in diesem Jahr wurde der Prototyp mit Ausnahme seines Parsers von Cordelia Hall, Will Partain und Simon Peyton Jones vollständig in Haskell neu geschrieben . Seine erste Beta-Version war am 1. April 1991 und nachfolgende Versionen fügten einen Strenge-Analysator sowie Spracherweiterungen wie monadische I/O , veränderliche Arrays, unverpackte Datentypen, nebenläufige und parallele Programmiermodelle (wie Software-Transaktionsspeicher und Datenparallelität ) hinzu. und ein Profiler .

Peyton Jones sowie Marlow wechselten später zu Microsoft Research in Cambridge, England , wo sie weiterhin hauptsächlich für die Entwicklung von GHC verantwortlich waren. GHC enthält auch Code von mehr als dreihundert anderen Mitwirkenden. Seit 2009 werden Drittmittel an GHC von der Industrial Haskell Group finanziert.

Die Architektur

GHC selbst ist in Haskell geschrieben , aber das Laufzeitsystem für Haskell, das zum Ausführen von Programmen unerlässlich ist, ist in C und C-- geschrieben .

Das Frontend von GHC – das Lexer , Parser und Typechecker enthält – soll so viele Informationen über die Quellsprache wie möglich bewahren, bis die Typinferenz abgeschlossen ist, um den Benutzern klare Fehlermeldungen zu liefern. Nach der Typprüfung wird der Haskell-Code in eine typisierte Zwischensprache namens "Core" (basierend auf System F , erweitert mit und -Ausdrücken) entzuckert . Kern wurde erweitert unterstützen generali algebraische Datentypen in ihrem Typ - System und wird nun auf der Basis eine Verlängerung System F bekannt als System F C . letcase

In der Tradition der typgesteuerten Kompilierung ist der GHC-Vereinfacher oder "Middle End", an dem die meisten in GHC implementierten Optimierungen durchgeführt werden, als eine Reihe von Source-to-Source- Transformationen des Core-Codes strukturiert . Die in dieser Compiler-Phase durchgeführten Analysen und Transformationen umfassen die Bedarfsanalyse (eine Verallgemeinerung der Strengeanalyse ), die Anwendung benutzerdefinierter Rewrite-Regeln (einschließlich eines Regelsatzes, der in den GHC-Standardbibliotheken enthalten ist und die Foldr/Build- Fusion durchführt ), das Entfalten (genannt " inlining "in traditionelleren Compilern), let-Floating , eine Analyse , die bestimmt , welche Funktionsargumente unboxed sein können, Analyse Produkter konstruiert , Spezialisierung von überladenen Funktionen, sowie eine Reihe von einfacheren lokalen Transformationen wie konstante Falte und beta Reduktion .

Das Backend des Compilers wandelt den Core-Code über eine Zwischensprache STG (kurz für "Spineless Tagless G-machine") in eine interne Darstellung von C-- um. Der C--Code kann dann einen von drei Wegen nehmen: Er wird entweder als C-Code für die Kompilierung mit GCC gedruckt , direkt in nativen Maschinencode umgewandelt (die traditionelle „ Codegenerierung “-Phase) oder in LLVM IR für die Kompilierung mit LLVM . umgewandelt . In allen drei Fällen wird der resultierende native Code schließlich mit dem GHC-Laufzeitsystem verknüpft, um eine ausführbare Datei zu erzeugen.

Sprache

GHC erfüllt die Sprachstandards Haskell 98 und Haskell 2010 . Es unterstützt auch viele optionale Erweiterungen des Haskell-Standards: zum Beispiel die Software Transactional Memory (STM)-Bibliothek, die Composable Memory Transactions ermöglicht .

Erweiterungen zu Haskell

Es wurden eine Reihe von Erweiterungen von Haskell vorgeschlagen. Diese Erweiterungen bieten Funktionen, die in der Sprachspezifikation nicht beschrieben sind, oder sie definieren bestehende Konstrukte neu. Daher wird möglicherweise nicht jede Erweiterung von allen Haskell-Implementierungen unterstützt. Es wird ständig versucht, Erweiterungen zu beschreiben und diejenigen auszuwählen, die in zukünftigen Versionen der Sprachspezifikation enthalten sein werden.

Die vom Glasgow Haskell Compiler unterstützten Erweiterungen umfassen:

  • Unboxed-Typen und -Operationen. Diese repräsentieren die primitiven Datentypen der zugrunde liegenden Hardware, ohne die Umleitung eines Zeigers auf den Heap oder die Möglichkeit einer verzögerten Auswertung. Numerisch intensiver Code kann erheblich schneller sein, wenn er mit diesen Typen codiert wird.
  • Die Möglichkeit, eine strikte Auswertung für ein Wert-, Musterbindungs- oder Datentypfeld anzugeben .
  • Bequemere Syntax für die Arbeit mit Modulen, Mustern, Listenverständnissen , Operatoren, Datensätzen und Tupeln.
  • Syntaktischer Zucker zum Rechnen mit Pfeilen und rekursiv definierten monadischen Werten. Beide Konzepte erweitern die monadische Do- Notation, die im Standard-Haskell bereitgestellt wird.
  • Ein wesentlich leistungsfähigeres System von Typen und Typklassen, das im Folgenden beschrieben wird.
  • Template Haskell , ein System für die Metaprogrammierung zur Kompilierzeit . Ein Programmierer kann Ausdrücke schreiben, die Haskell-Code in Form eines abstrakten Syntaxbaums erzeugen . Diese Ausdrücke werden zur Kompilierzeit typgeprüft und ausgewertet; der generierte Code wird dann eingebunden, als ob er direkt vom Programmierer geschrieben worden wäre. Zusammen mit der Fähigkeit, Definitionen zu reflektieren , bietet dies ein mächtiges Werkzeug für weitere Erweiterungen der Sprache.
  • Quasi-Zitat, das es dem Benutzer ermöglicht, eine neue konkrete Syntax für Ausdrücke und Muster zu definieren. Quasi-Zitate sind nützlich, wenn ein in Haskell geschriebenes Metaprogramm Code manipuliert, der in einer anderen Sprache als Haskell geschrieben ist.
  • Generische Typklassen, die Funktionen ausschließlich in Bezug auf die algebraische Struktur der Typen angeben, auf denen sie arbeiten.
  • Parallele Auswertung von Ausdrücken mit mehreren CPU-Kernen. Dies erfordert kein explizites Spawnen von Threads. Die Verteilung der Arbeit erfolgt implizit, basierend auf Annotationen des Programmierers.
  • Compiler- Pragmas zur Steuerung von Optimierungen wie Inline-Expansion und Spezialfunktionen für bestimmte Typen.
  • Anpassbare Rewrite-Regeln. Der Programmierer kann Regeln bereitstellen, die beschreiben, wie ein Ausdruck durch einen äquivalenten, aber effizienter ausgewerteten Ausdruck ersetzt wird. Diese werden in Kern-Datenstrukturbibliotheken verwendet, um eine verbesserte Leistung im gesamten Code auf Anwendungsebene bereitzustellen.
  • Punktsyntax aufzeichnen. Bietet syntaktischen Zucker für den Zugriff auf die Felder eines (möglicherweise verschachtelten) Datensatzes, der der Syntax vieler anderer Programmiersprachen ähnelt.

Typsystemerweiterungen

Ein ausdrucksstarkes statisches Typsystem ist eines der wichtigsten Merkmale von Haskell. Dementsprechend wurde ein Großteil der Arbeit bei der Erweiterung der Sprache auf Typen und Typklassen gerichtet .

Der Glasgow Haskell Compiler unterstützt ein erweitertes Typsystem basierend auf dem theoretischen System F C . Zu den wichtigsten Erweiterungen des Typensystems gehören:

  • Willkürlicher und imprädikativer Polymorphismus . Im Wesentlichen kann ein polymorpher Funktions- oder Datentypkonstruktor erfordern, dass eines seiner Argumente selbst polymorph ist.
  • Verallgemeinerte algebraische Datentypen . Jeder Konstruktor eines polymorphen Datentyps kann Informationen in den resultierenden Typ kodieren. Eine Funktion, die bei diesem Typ Musterübereinstimmungen aufweist, kann die Typinformationen pro Konstruktor verwenden, um spezifischere Operationen an Daten durchzuführen.
  • Existenzielle Typen . Diese können verwendet werden, um einige Daten zusammen mit Operationen an diesen Daten zu "bündeln", so dass die Operationen verwendet werden können, ohne den spezifischen Typ der zugrunde liegenden Daten offenzulegen. Ein solcher Wert ist einem Objekt sehr ähnlich, wie es in objektorientierten Programmiersprachen zu finden ist.
  • Datentypen, die eigentlich keine Werte enthalten. Diese können nützlich sein, um Daten in der Metaprogrammierung auf Typebene darzustellen .
  • Typfamilien : benutzerdefinierte Funktionen von Typen zu Typen. Während parametrischer Polymorphismus für jede Typinstanziierung dieselbe Struktur bereitstellt, bieten Typfamilien einen Ad-hoc- Polymorphismus mit Implementierungen, die sich zwischen den einzelnen Instanzen unterscheiden können. Anwendungsfälle umfassen inhaltsbewusste Optimierungscontainer und Metaprogrammierung auf Typebene.
  • Implizite Funktionsparameter mit dynamischem Gültigkeitsbereich . Diese werden in Typen ähnlich wie Typklasseneinschränkungen dargestellt.
  • Lineare Typen (GHC 9.0)

Erweiterungen in Bezug auf Typklassen umfassen:

  • Eine Typklasse kann auf mehr als einen Typ parametrisiert werden. Somit kann eine Typklasse nicht nur eine Menge von Typen beschreiben, sondern eine n- äre Relation auf Typen.
  • Funktionale Abhängigkeiten , die Teile dieser Beziehung darauf beschränken, eine mathematische Funktion von Typen zu sein. Das heißt, die Einschränkung gibt an, dass einige Typklassenparameter vollständig bestimmt sind, sobald ein anderer Satz von Parametern festgelegt ist. Dies führt den Prozess der Typinferenz in Situationen, in denen es sonst zu Mehrdeutigkeiten kommen würde.
  • Deutlich gelockerte Regeln bezüglich der zulässigen Form von Typklasseninstanzen. Wenn diese vollständig aktiviert sind, wird das Typklassensystem zur Kompilierzeit zu einer Turing-vollständigen Sprache für die Logikprogrammierung .
  • Typfamilien können, wie oben beschrieben, auch einer Typklasse zugeordnet werden.
  • Die automatische Generierung bestimmter Typklasseninstanzen wird in mehrfacher Hinsicht erweitert. Neue Typklassen für generische Programmierung und allgemeine Rekursionsmuster werden unterstützt. Wenn ein neuer Typ als isomorph zu einem vorhandenen Typ deklariert wird, kann außerdem jede für den zugrunde liegenden Typ deklarierte Typklasseninstanz "kostenlos" auf den neuen Typ angehoben werden.

Portabilität

Versionen von GHC sind für verschiedene Plattformen verfügbar , einschließlich Windows und die meisten Unix- Varianten (wie Linux , FreeBSD , OpenBSD und macOS ). GHC wurde auch auf verschiedene Prozessorarchitekturen portiert .

Siehe auch

Verweise

Externe Links