Haxe - Haxe

Haxe
Haxe-logo.svg
Paradigma Multiparadigma
Entwickler Haxe-Stiftung
Erstmals erschienen 2005 ; Vor 16 Jahren ( 2005 )
Stabile Version
4.2.3  Bearbeiten Sie dies auf Wikidata / 1. Juli 2021 ; vor 3 Monaten ( 1 Juli 2021 )
Schreibdisziplin Statisch , dynamisch über Anmerkungen, nominal
Implementierungssprache OCaml
Plattform ARM ; IA-32 , x86-64
Betriebssystem Android , iOS ; Linux , macOS , Windows
Lizenz GPL 2.0, Bibliothek: MIT
Dateinamenerweiterungen .hx, .hxml
Webseite haxe .org
Beeinflusst von
EcmaScript , OCaml , Java , JavaScript , C++ , PHP , C# , Python , Lua , ActionScript , NekoVM

Haxe ist eine plattformübergreifende Open-Source- Programmiersprache und ein Compiler , die Anwendungen und Quellcode für viele verschiedene Computerplattformen aus einer Codebasis erstellen können. Es handelt sich um kostenlose Open-Source-Software , die unter der MIT-Lizenz veröffentlicht wurde . Der in OCaml geschriebene Compiler wird unter der GNU General Public License (GPL) Version 2 veröffentlicht.

Haxe enthält eine Reihe von Funktionen und eine Standardbibliothek, die von allen Plattformen unterstützt wird , wie numerische Datentypen , Strings , Arrays , Maps , Binary , Reflection , Math, HTTP , Dateisystem und gängige Dateiformate . Haxe enthält auch plattformspezifische APIs für jedes Compilerziel. Kha , OpenFL und Heaps.io sind beliebte Haxe-Frameworks, die es ermöglichen, plattformübergreifende Inhalte aus einer Codebasis zu erstellen.

Haxe entstand mit der Idee, clientseitige und serverseitige Programmierung in einer Sprache zu unterstützen und die Kommunikationslogik zwischen ihnen zu vereinfachen. In der Haxe-Sprache geschriebener Code kann in JavaScript , C++ , Java , JVM , PHP , C# , Python , Lua und Node.js kompiliert werden . Haxe kann auch SWF- , HashLink- und Neko- Bytecode direkt kompilieren und läuft auch im interpretierten Modus.

Haxe unterstützt externs (Definitionsdateien), die Typinformationen vorhandener Bibliotheken enthalten können, um zielspezifische Interaktionen typsicher zu beschreiben, wie C++- Headerdateien die Struktur vorhandener Objektdateien beschreiben können . Dadurch können die in den Dateien definierten Werte so verwendet werden, als wären sie statisch typisierte Haxe-Entitäten. Neben externen Lösungen gibt es andere Lösungen, um auf die nativen Fähigkeiten jeder Plattform zuzugreifen.

Viele beliebte IDEs und Quellcode-Editoren bieten Unterstützung für die Haxe-Entwicklung . Von der Haxe Foundation wird offiziell keine bestimmte Entwicklungsumgebung oder ein bestimmtes Toolset empfohlen, obwohl VS Code , IntelliJ IDEA und HaxeDevelop die meiste Unterstützung für die Haxe-Entwicklung bieten. Die Kernfunktionalitäten Syntax Highlighting , Code Completion , Refactoring , Debugging etc. stehen in unterschiedlichem Umfang zur Verfügung.

Geschichte

Die Entwicklung von Haxe begann im Oktober 2005. Die erste Beta-Version wurde im Februar 2006 veröffentlicht. Haxe 1.0 wurde im April 2006 mit Unterstützung für Adobe Flash- , JavaScript- und Neko- Programme veröffentlicht. Unterstützung für PHP wurde 2008 hinzugefügt und C++ wurde 2009 hinzugefügt. Weitere Plattformen wie C# und Java wurden 2012 mit einer Überarbeitung des Compilers hinzugefügt.

Haxe wurde von Nicolas Cannasse und anderen Mitwirkenden entwickelt und hieß ursprünglich haXe, weil es kurz und einfach war und "ein X im Inneren hat", was der Autor humorvoll behauptet, um jede neue Technologie zum Erfolg zu führen.

Haxe ist der Nachfolger des Open-Source- ActionScript- 2-Compilers MTASC , der ebenfalls von Nicolas Cannasse entwickelt wurde und unter der GNU General Public License Version 2 oder höher veröffentlicht wird.

Compiler

Die Haxe-Sprache kann in Bytecode kompiliert werden, der direkt von den virtuellen Maschinen ausgeführt werden kann, auf die sie abzielt. Es kann zu Quellcode in C++ , JavaScript , PHP , C# , Java , Python und Lua kompiliert werden . Haxe hat auch einen Interpreter namens eval . Derselbe Interpreter wird auch zur Kompilierzeit verwendet, um Makros auszuführen, die eine Änderung des AST ermöglichen .

Diese Strategie des Kompilierens in mehrere Quellcodesprachen ist inspiriert vom Write-Once-, Run-Überall- Paradigma. Es ermöglicht dem Programmierer auch, die beste Plattform für den Job auszuwählen. Typische Haxe-Programme laufen auf allen Plattformen identisch, aber Entwickler können plattformspezifischen Code angeben und eine bedingte Kompilierung verwenden , um zu verhindern, dass er auf anderen Plattformen kompiliert wird.

Der Haxe-Compiler ist ein optimierender Compiler und verwendet Feld- und Funktions-Inlining , Tail-Rekursion-Elimination , Constant Folding , Loop-Unrolling und Dead-Code-Elimination (DCE), um die Laufzeitleistung kompilierter Programme zu optimieren. Der Haxe-Compiler bietet Opt-in- Null-Sicherheit , er überprüft die Kompilierzeit auf Nullwerte .

Ziele

In Haxe werden unterstützte Plattformen als "Targets" bezeichnet, die aus den folgenden Modulen bestehen:

  • Die Compiler-Backends, die für die Generierung des jeweiligen Codes verantwortlich sind.
  • Die laufzeitspezifischen APIs, die über die Kernsprachenunterstützung hinausgehen (Plattformziele).

Die folgende Tabelle dokumentiert die Plattform- und Sprachunterstützung in Haxe. Die Haxe-Sprache ermöglicht Entwicklern den Zugriff auf viele Plattformfunktionen, aber Haxe ist keine voll funktionsfähige Engine. Sie benötigen möglicherweise Frameworks, die das Erstellen von Inhalten für bestimmte Plattformen ermöglichen.

Compiler-Ziel Ausgabe Plattform Verwenden Seit der Haxe-Version
JavaScript Quelle HTML5 , NodeJS , PhoneGap Server, Desktop, Browser, Handy 2006
C++ Quelle Windows , Linux , MacOS , Android , iOS , Palm , WebOS Server, Desktop, Mobil, CLI, Spielekonsolen 2009 (2.04)
PHP Quelle PHP Server 2008 (2.0)
C# Quelle .NET-Framework Server, Desktop, Handy 2012 (2.10)
Java Quelle Java Server, Desktop 2012 (2.10)
JVM Bytecode Java virtuelle Maschine Server, Desktop 2019 (4.0)
Python Quelle Python CLI, Web, Desktop 2014 (3.2)
Lua Quelle Lua CLI, Web, Desktop, Handy 2016 (3.3)
Neko Byte-Code NekoVM Server, Desktop, CLI 2005
Flash/SWF Byte-Code Adobe Flash Player 9+, Adobe AIR , Tamarin Desktop, Browser, Server 2005
HashLink Byte-Code HashLink VM oder HL/C (in C-Datei kompilieren) Server, Desktop, Mobile, Spielekonsolen (C-Export) 2016 (3.4)

Seit Haxe Version 1.12 (2007) gab es ein ActionScript 3 Quellziel (für Adobe FlashPlayer), dieses wurde in Version 4.0 aus Haxe entfernt.

Vorteile für Haxe

  • Möglichkeit zur Ausrichtung auf mehrere Plattformen und Geräte mit derselben Sprache
  • Möglichkeit, streng typisierten Code zu verwenden
  • Möglichkeit zur Verwendung von Makros (Syntaxtransformation), die mit der Sprache Haxe durchgeführt werden kann
  • Sprachfeatures wie Erweiterungsmethoden und funktionale Programmierung hinzugefügt
  • Die Laufzeitleistung von Haxe-Programmen ist mit der von handgeschriebenen Quellen vergleichbar.

Sprache

Haxe ist eine Allzwecksprache, die objektorientierte Programmierung , generische Programmierung und verschiedene funktionale Programmierkonstrukte unterstützt . Features wie Iterationen , Ausnahmen und Codereflexion sind ebenfalls integrierte Funktionen der Sprache und Bibliotheken. Ungewöhnlich unter Programmiersprachen enthält Haxe ein Typensystem, das sowohl stark als auch dynamisch ist . Der Compiler überprüft Typen implizit mithilfe von Typinferenz und gibt Fehler bei der Kompilierung aus, ermöglicht es dem Programmierer jedoch auch, die Typprüfung zu umgehen und sich auf die dynamische Typbehandlung der Zielplattform zu verlassen. Alle nativen Ziel-APIs können verwendet werden.

Typensystem

Haxe verfügt über ein ausgeklügeltes und flexibles Typensystem. Die angebotenen Typarten sind Klassen, Interfaces, Funktionsmethodentypen, anonyme Typen, algebraische Datentypen (ADTs, in Haxe Enum genannt ) und abstrakte Typen. Parametrischer Polymorphismus ist mit Klassen, ADTs und Funktionstypen möglich, wodurch die Sprache eine generische Programmierung basierend auf Typlöschung unterstützt. Dies schließt die Unterstützung für Varianz in polymorphen Funktionen ein , jedoch nicht in Typkonstruktoren .

Das Typsystem ist statisch, es sei denn, es sind Anmerkungen für die dynamische Typisierung vorhanden, um sie mit Zielen zu verwenden, die sie unterstützen. Die Typprüfung folgt der nominalen Typisierung, mit Ausnahme anonymer Typen, bei denen stattdessen die strukturelle Typisierung verwendet wird. Schließlich wird Typrückschluss unterstützt, der Variablendeklarationen ohne Typanmerkungen ermöglicht .

Module und Namensräume

Der gesamte Haxe-Code ist in Modulen organisiert, die über Pfade angesprochen werden. Im Wesentlichen stellt jede .hx- Datei ein Modul dar, das mehrere Typen enthalten kann. Um beispielsweise den Typ Aim Paket my.pack wie gezeigt zu erstellen , sollte die Ordnerstruktur my\pack sein und die Datei könnte A.hx im Ordner pack sein .

 // file my/pack/A.hx
package my.pack;

class A {}

In anderen Modulen können andere Typen importiert werden, indem importAnweisungen unter die Paketdefinition gestellt werden, zB import my.pack.A; Ein Modul kann mehrere Typen enthalten, wie zum Beispiel die folgenden. Es ist möglich, einen Typ nach dem anderen aus diesem Modul zu importieren, indem Sie import my.pack2.A;. Ein Typ kann sein private, in diesem Fall kann nur sein enthaltendes Modul darauf zugreifen.

package my.pack2;

typedef A = {a:String}
private typedef B = {b:String}

Klassen

Klassen (Schlüsselwort class) in Haxe ähneln denen in Java oder TypeScript. Ihre Felder können entweder Methoden, Variablen oder Eigenschaften sein, jeweils statisch oder pro Instanz. Haxe unterstützt die Accessoren publicund private, und fortgeschrittenere Methoden für die Zugriffskontrolle, die durch Annotationen gekennzeichnet sind. Methoden und statische Konstantenvariablen können mit dem Schlüsselwort inline eingebunden werden inline. Felder können als finaleine Konstante deklariert werden, die sofort oder im Konstruktor initialisiert werden muss und in die nicht geschrieben werden kann, falls die Funktion finalin Unterklassen als nicht überschreibbar markiert wird.

Schnittstellen in Haxe sind denen in beispielsweise Java sehr ähnlich.

interface ICreature {
    public var birth:Date;
    public var name:String;

    public function age():Int;
}

class Fly implements ICreature {
    public var birth:Date;
    public var name:String;
	
    public function age():Int return Date.now().getFullYear() - birth.getFullYear();
}

Generika

Haxe unterstützt generische Programmierung . Das Folgende ist ein Beispiel für die Identitätsfunktion .

function identity<T>(arg:T):T {
	return arg;
}

Aufgezählte Typen

Aufzählungstypen sind ein wichtiges Merkmal der Sprache; sie können Typparameter haben und rekursiv sein. Sie bieten grundlegende Unterstützung für algebraische Datentypen und ermöglichen die Einbeziehung von Produkttypen , ähnlich wie bei Haskell und ML . Ein switchAusdruck kann einen Mustervergleich auf einen Enum-Wert anwenden , was elegante Lösungen für komplexe Programmierprobleme ermöglicht:

enum Color {
	red;
	green;
	blue;
	rgb(r:Int, g:Int, b:Int);
}

class Colors {
	static function toInt(c:Color):Int {
		return switch c {
			case red: 0xFF0000;
			case green: 0x00FF00;
			case blue: 0x0000FF;
			case rgb(r, g, b): (r << 16) | (g << 8) | b;
		}
	}

	static function validCalls() {
		var redint = toInt(Color.red);
		var rgbint = toInt(Color.rgb(100, 100, 100));
	}
}

Beispiele für parametrische Aufzählungstypen sind die Haxe-Standardbibliothekstypen Option und Entweder:

enum Option<T> {
    Some(v:T);
    None;
}

enum Either<L, R> {
    Left(v:L);
    Right(v:R);
}

Haxe unterstützt auch generalisierte algebraische Datentypen (GADTs).

Anonyme Typen

Anonyme Typen werden definiert, indem ihre Struktur explizit angegeben wird, wobei eine Syntax verwendet wird, die der mathematischen datensatzbasierten Darstellung eines Typs folgt. Sie können verwendet werden, um eine strukturelle Typisierung für Funktionsargumente zu implementieren (siehe unten), und können mit dem Schlüsselwort einen Alias ​​erhalten typedef:

typedef AliasForAnon = { a:Int, b:String, c:Float->Void };

Funktionstypen

Funktionen sind erstklassige Werte in Haxe. Ihr Typ wird durch die Verwendung von Pfeilen zwischen Argumenttypen und zwischen den Argumenttypen und dem Rückgabetyp angegeben, wie es in vielen funktionalen Sprachen üblich ist. Im Gegensatz zu prominenten Beispielen wie Haskell oder der ML- Sprachfamilie sind jedoch nicht alle Funktionen unäre Funktionen (Funktionen mit nur einem Argument), und in Haxe können Funktionen nicht standardmäßig teilweise angewendet werden. Somit haben die folgenden Typsignaturen eine andere Semantik als in den oben genannten Sprachen. Der Typ F1ist eine Funktion, die a Stringals Argument annimmt und einen Wert vom Typ zurückgibt Float.

Typen F1und F2 bezeichnen denselben Typ, außer dass F2beschriftete Parameter verwendet werden, was für Vervollständigungs- und Dokumentationszwecke nützlich ist.

Typen F4und F5bezeichnen denselben Typ. Beides sind Binärfunktionen, die eine Binärfunktion vom Typ zurückgeben F3. Für F5die Syntax wird die Deklaration eines Funktionstyps innerhalb eines Funktionstyps verwendet.

typedef F1 = String -> Float;
typedef F2 = (text:String) -> Float;

typedef F3 = (score:Int, text:String) -> Float;
typedef F4 = (score:Int, text:String) -> F3;
typedef F5 = (score:Int, text:String) -> ((score:Int, text:String) -> Float);

Abstrakte Typen

Die neueste Ergänzung des Haxe-Typensystems ist ein Konzept, das als abstrakte Typen bezeichnet wird . Wie in Haxe verwendet, bezieht sich dies auf etwas, das sich von einem herkömmlichen abstrakten Typ unterscheidet . Sie werden verwendet, um implizite Konvertierungen zwischen Typen vorzunehmen, wodurch die Wiederverwendung vorhandener Typen für bestimmte Zwecke ermöglicht wird, z. B. die Implementierung von Typen für Maßeinheiten. Dadurch wird das Risiko einer Verwechslung von Werten des gleichen zugrunde liegenden Typs, jedoch mit unterschiedlichen Bedeutungen (zB Meilen vs. km) stark reduziert.

Im folgenden Beispiel wird davon ausgegangen, dass das metrische System der Standard ist, während für Altdaten eine Umrechnung in Meilen erforderlich ist. Haxe kann Meilen automatisch in Kilometer umrechnen, aber nicht umgekehrt.

abstract Kilometer(Float) {
    public function new(v:Float) this = v;
}
 
abstract Mile(Float) {
    public function new(v:Float) this = v;
    @:to public inline function toKilometer():Kilometer return (new Kilometer (this / 0.62137));
}
 
class Test {
  static var km:Kilometer;
  static function main(){
    var one100Miles = new Mile(100);
    km = one100Miles;
 
    trace(km); // 160.935
  }
}

Wie das Beispiel zeigt, ist für die Zuweisung "km = one100Miles;" keine explizite Konvertierung erforderlich. das Richtige zu tun.

Strukturtypisierung

In vielen funktionalen Programmiersprachen spielt die strukturelle Typisierung eine große Rolle. Haxe verwendet es in Gegenwart anonymer Typen, indem es die nominative Typisierung der objektorientierten Programmierung verwendet , wenn nur benannte Typen beteiligt sind. Anonyme Typen in Haxe sind analog zu den impliziten Interfaces der Sprache Go hinsichtlich der Typisierung. Im Gegensatz zu Go-Schnittstellen ist es möglich, einen Wert mit einem anonymen Typ zu konstruieren.

class FooBar {
	public var foo:Int;
	public var bar:String;

	public function new() {
		foo = 1;
		bar = "2";
	}

	function anyFooBar(v:{foo:Int, bar:String})
		trace(v.foo);

	static function test() {
		var fb = new FooBar();
		fb.anyFooBar(fb);
		fb.anyFooBar({foo: 123, bar: "456"});
	}
}

Interne Architektur

Compiler

Der Haxe-Compiler ist in ein Frontend und mehrere Backends unterteilt. Das Frontend erstellt einen abstrakten Syntaxbaum (AST) aus dem Quellcode und führt Typprüfung, Makroerweiterung und Optimierung auf dem AST durch . Die verschiedenen Backends übersetzen die verarbeiteten AST in Quellcode oder generieren Bytecode , je nach Ziel.

Der Compiler ist in OCaml geschrieben . Es kann im Servermodus ausgeführt werden, um die Codevervollständigung für integrierte Entwicklungsumgebungen (IDEs) bereitzustellen und einen Cache zu verwalten, um die Kompilierung weiter zu beschleunigen.

Siehe auch

Verweise

Externe Links