Haxe - Haxe

Haxe
Haxe logo.svg
Paradygmat Wieloparadygmat
Deweloper Fundacja Haxe
Po raz pierwszy pojawiły się 2005 ; 16 lat temu ( 2005 )
Wersja stabilna
4.2.3  Edytuj to na Wikidanych / 1 lipca 2021 r .; 3 miesiące temu ( 1 lipca 2021 )
Dyscyplina pisania Statyczny , dynamiczny poprzez adnotacje, nominalny
Język implementacji OCaml
Platforma ramię ; IA-32 , x86-64
OS Android , iOS ; Linux , macOS , Windows
Licencja GPL 2.0, biblioteka: MIT
Rozszerzenia nazw plików .hx, .hxml
Strona internetowa haxe .org
Wpływem
EcmaScript , OCaml , Java , JavaScript , C++ , PHP , C# , Python , Lua , ActionScript , NekoVM

Haxe to wieloplatformowy język programowania wysokiego poziomu typu open source i kompilator, który może tworzyć aplikacje i kod źródłowy dla wielu różnych platform obliczeniowych z jednej bazy kodu. Jest to darmowe oprogramowanie o otwartym kodzie źródłowym , wydane na licencji MIT . Kompilator, napisany w OCaml , został wydany na licencji GNU General Public License (GPL) w wersji 2.

Haxe zawiera zestaw funkcji i biblioteki standardowej obsługiwany na wszystkich platformach , jak liczbowych typów danych , ciągi , tablice , mapy , binarny , refleksji , matematyka, HTTP , systemu plików i wspólnych formatów plików . Haxe zawiera również specyficzne dla platformy API dla każdego celu kompilatora. Kha , OpenFL i Heaps.io to popularne frameworki Haxe, które umożliwiają tworzenie treści na wielu platformach z jednej bazy kodu.

Haxe pochodzi z ideą wspierania po stronie klienta i po stronie serwera programowania w jednym języku, a uproszczenie logiki komunikacji między nimi. Kod napisany w języku haXe może być skompilowany do JavaScript , C ++ , Java , JVM , PHP , C # , Python , Lua i node.js . Haxe może również bezpośrednio kompilować kod bajtowy SWF , HashLink i Neko, a także działa w trybie interpretowanym.

Haxe obsługuje externs (pliki definicji), które mogą zawierać informacje o typie istniejących bibliotek, aby opisać interakcję specyficzną dla celu w sposób bezpieczny dla typu, na przykład pliki nagłówkowe C++ mogą opisywać strukturę istniejących plików obiektów . Pozwala to na używanie wartości zdefiniowanych w plikach tak, jakby były statycznie typowanymi jednostkami Haxe. Oprócz zewnętrznych istnieją inne rozwiązania umożliwiające dostęp do natywnych możliwości każdej platformy.

Wiele popularnych IDE i edytorów kodu źródłowego ma wsparcie dla rozwoju Haxe . Żadne konkretne środowisko programistyczne ani zestaw narzędzi nie jest oficjalnie rekomendowany przez Haxe Foundation, chociaż VS Code , IntelliJ IDEA i HaxeDevelop mają największe wsparcie dla rozwoju Haxe. Podstawowe funkcje podświetlania składni , uzupełniania kodu , refaktoryzacji , debugowania itp. są dostępne w różnym stopniu.

Historia

Rozwój Haxe rozpoczął się w październiku 2005. Pierwsza wersja beta została wydana w lutym 2006. Haxe 1.0 został wydany w kwietniu 2006, z obsługą programów Adobe Flash , JavaScript i Neko . Wsparcie dla PHP zostało dodane w 2008 roku, a C++ zostało dodane w 2009 roku. Więcej platform, takich jak C# i Java, zostało dodanych wraz z przebudową kompilatora w 2012 roku.

Haxe został opracowany przez Nicolasa Cannasse i innych współpracowników i początkowo nosił nazwę haXe, ponieważ był krótki, prosty i „ma w środku X”, co, jak twierdzi autor, jest potrzebne, aby każda nowa technologia odniosła sukces.

Haxe jest następcą otwartego kompilatora ActionScript 2 MTASC , również zbudowanego przez Nicolasa Cannasse i wydanego na licencji GNU General Public License w wersji 2 lub nowszej.

Kompilator

Język Haxe może zostać skompilowany do kodu bajtowego, który może być wykonywany bezpośrednio przez maszyny wirtualne, na które jest przeznaczony. Może kompilować do kodu źródłowego w językach C++ , JavaScript , PHP , C# , Java , Python i Lua . Haxe ma również tłumacza zwanego eval . Ten sam interpreter jest również używany w czasie kompilacji do uruchamiania makr, które umożliwiają modyfikację AST .

Ta strategia kompilacji do wielu języków kodu źródłowego jest inspirowana paradygmatem „ napisz raz, uruchom w dowolnym miejscu” . Pozwala również programiście wybrać najlepszą platformę do pracy. Typowe programy Haxe działają identycznie na wszystkich platformach, ale programiści mogą określić kod specyficzny dla platformy i użyć kompilacji warunkowej, aby zapobiec kompilacji na innych platformach.

Kompilator Haxe jest kompilatorem optymalizującym i używa inliniowania pól i funkcji , eliminacji rekurencji ogona , stałego składania , rozwijania pętli i eliminacji martwego kodu (DCE) w celu optymalizacji wydajności skompilowanych programów. Kompilator Haxe oferuje opcję null-safety , która sprawdza czas kompilacji pod kątem wartości dopuszczających wartość null.

Cele

W Haxe obsługiwane platformy nazywane są „targetami”, które składają się z następujących modułów:

  • Backendy kompilatora, które są odpowiedzialne za generowanie odpowiedniego kodu.
  • Interfejsy API specyficzne dla środowiska uruchomieniowego, które wykraczają poza podstawową obsługę języka (platform-targets).

Poniższa tabela przedstawia obsługę platformy i języka w Haxe. Język Haxe pozwala programistom uzyskać dostęp do wielu funkcji platformy, ale Haxe nie jest w pełni funkcjonalnym silnikiem, mogą potrzebować frameworków, które umożliwiają tworzenie treści dla niektórych platform.

Cel kompilatora Wyjście Platforma Posługiwać się Od wersji Haxe
JavaScript źródło HTML5 , NodeJS , PhoneGap Serwer, komputer stacjonarny, przeglądarka, telefon komórkowy 2006
C++ źródło Windows , Linux , MacOS , Android , iOS , Palm , WebOS Serwer, komputer stacjonarny, urządzenia mobilne, CLI, konsole do gier 2009 (2.04)
PHP źródło PHP serwer 2008 (2.0)
C# źródło .NET Framework Serwer, komputer stacjonarny, telefon komórkowy 2012 (2.10)
Jawa źródło Jawa Serwer, komputer stacjonarny 2012 (2.10)
JVM kod bajtowy Maszyna wirtualna Java Serwer, komputer stacjonarny 2019 (4.0)
Pyton źródło Pyton CLI, sieć, komputery stacjonarne 2014 (3.2)
Lua źródło Lua CLI, web, desktop, mobile 2016 (3.3)
Neko kod bajtowy NekoVM Serwer, komputer stacjonarny, CLI 2005
Flash/SWF kod bajtowy Adobe Flash Player 9+, Adobe AIR , Tamarin Pulpit, przeglądarka, serwer 2005
HashLink kod bajtowy HashLink VM lub HL/C (kompilacja do pliku C) Serwer, komputer stacjonarny, telefon komórkowy, konsole do gier (eksport C) 2016 (3.4)

Od wersji Haxe 1.12 (2007) istniał cel źródłowy ActionScript 3 (dla Adobe FlashPlayer), został on usunięty z Haxe w wersji 4.0.

Korzyści dla Haxe

  • Możliwość kierowania na wiele platform i urządzeń używających tego samego języka
  • Umiejętność posługiwania się ściśle wpisanym kodem
  • Umiejętność korzystania z makr (przekształcenia składni), które można wykonać za pomocą języka Haxe
  • Dodano funkcje językowe, takie jak metody rozszerzeń i programowanie funkcjonalne
  • Wydajność w czasie wykonywania programów Haxe jest porównywalna z szybkością źródeł pisanych ręcznie.

Język

Haxe jest językiem ogólnego przeznaczenia wspiera programowanie obiektowe , programowanie ogólne i różne funkcjonalne programowania konstruktów. Funkcje takie jak iteracje , wyjątki i odbicie kodu są również wbudowanymi funkcjami języka i bibliotek. Nietypowy wśród języków programowania Haxe zawiera system typów, który jest zarówno silny, jak i dynamiczny . Kompilator sprawdzi typy niejawnie przy użyciu wnioskowania o typie i poda błędy w czasie kompilacji, ale umożliwia także programiście pominięcie sprawdzania typu i poleganie na dynamicznej obsłudze typów platformy docelowej. Można używać wszystkich natywnych docelowych interfejsów API.

Wpisz system

Haxe ma wyrafinowany i elastyczny system czcionek. Oferowane typy typów to klasy, interfejsy, typy funkcji-metod, typy anonimowe, algebraiczne typy danych (ADT, zwane enum w Haxe) i typy abstrakcyjne. Polimorfizm parametryczny jest możliwy w przypadku klas, ADT i typów funkcji, zapewniając obsługę języka dla programowania generycznego opartego na wymazywaniu typu. Obejmuje to obsługę wariancji w funkcjach polimorficznych , ale nie w konstruktorach typu .

System typów jest statyczny, chyba że istnieją adnotacje do dynamicznego wpisywania , do użytku z obiektami docelowymi, które je obsługują. Sprawdzanie typu następuje po typowaniu nominalnym, z wyjątkiem typów anonimowych, w których zamiast tego jest używane typowanie strukturalne . Wreszcie obsługiwane jest wnioskowanie o typie , co pozwala na deklaracje zmiennych bez adnotacji typu .

Moduły i przestrzenie nazw

Cały kod Haxe jest zorganizowany w moduły, które są adresowane za pomocą ścieżek. Zasadniczo każdy plik .hx reprezentuje moduł, który może zawierać kilka typów. Na przykład, aby utworzyć typ Aw pakiecie my.pack, jak pokazano, struktura folderów powinna mieć postać my\pack , a plik może mieć postać A.hx w pakiecie folderów .

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

class A {}

W innych modułach można zaimportować inne typy, umieszczając importinstrukcje poniżej definicji pakietu, np import my.pack.A; . Moduł może zawierać wiele typów, takich jak poniższe. Możliwe jest jednoczesne importowanie jednego typu z tego modułu za pomocą import my.pack2.A;. Typem może być private, w którym to przypadku tylko jego moduł zawierający może mieć do niego dostęp.

package my.pack2;

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

Klasy

Klasy (keyword class) w Haxe są podobne do tych w Javie czy TypeScript. Ich pola mogą być metodami, zmiennymi lub właściwościami, odpowiednio statycznymi lub przypadającymi na instancję. Haxe obsługuje akcesory publici private, oraz bardziej zaawansowane metody kontroli dostępu, które są oznaczone za pomocą adnotacji. Metody i statyczne zmienne mogą być wstawiane za pomocą słowa kluczowego inline. Pola można oznaczyć jako finaldeklarujące stałą, która musi być zainicjowana natychmiast lub w konstruktorze i nie można do niej zapisać, w przypadku funkcji finaloznaczy jako niemożliwa do nadpisania w podklasach.

Interfejsy w Haxe są bardzo podobne do na przykład w Javie.

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();
}

Generyki

Haxe obsługuje programowanie generyczne . Poniżej znajduje się przykład funkcji tożsamości .

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

Wyliczone typy

Typy wyliczane są ważną cechą języka; mogą mieć parametry typu i być rekurencyjne. Zapewniają one podstawowe wsparcie dla algebraicznych typów danych , umożliwiając uwzględnienie typów produktów w sposób podobny do Haskella i ML . switchWyrażenie można zastosować dopasowanie wzoru na wartość enum, pozwalając na eleganckich rozwiązań złożonych problemów programistycznych:

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));
	}
}

Przykładami parametrycznych typów wyliczeń są standardowe typy bibliotek Haxe Option i Albo:

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

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

Haxe obsługuje również uogólnione algebraiczne typy danych (GADT).

Typy anonimowe

Typy anonimowe są definiowane przez jawne oznaczenie ich struktury przy użyciu składni zgodnej z matematyczną reprezentacją typu opartą na rekordach. Mogą być używane do implementacji typowania strukturalnego dla argumentów funkcji (patrz poniżej) i można im nadać alias za pomocą słowa kluczowego typedef:

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

Rodzaje funkcji

Funkcje są wartościami pierwszej klasy w Haxe. Ich typ jest oznaczany za pomocą strzałek między typami argumentów oraz między typami argumentów a typem zwracanym, co jest powszechne w wielu językach funkcjonalnych. Jednak w przeciwieństwie do znanych przykładów, takich jak Haskell lub rodzina języków ML , nie wszystkie funkcje są funkcjami jednoargumentowymi (funkcje z tylko jednym argumentem), a w Haxe funkcje nie mogą być domyślnie stosowane częściowo . Tak więc następujące sygnatury typów mają inną semantykę niż we wspomnianych językach. Type F1to funkcja, która przyjmuje Stringjako argumenty i zwraca wartość typu Float.

Typy F1i F2 oznaczają ten sam typ, z wyjątkiem tego, że F2używa parametru oznaczonego etykietą, który jest przydatny do celów uzupełniania i dokumentacji.

Rodzaje F4i F5oznaczają ten sam typ. Obie są funkcjami binarnymi, które zwracają funkcję binarną typu F3. Dla F5składni do deklarowania typu funkcji w typie funkcji jest używana.

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);

Typy abstrakcyjne

Najnowszym dodatkiem do systemu typów Haxe jest koncepcja zwana typami abstrakcyjnymi . Używany w Haxe, odnosi się do czegoś innego niż konwencjonalny abstrakcyjny typ . Służą do niejawnych konwersji między typami, umożliwiając ponowne użycie istniejących typów do określonych celów, takich jak implementacja typów dla jednostek miary. To znacznie zmniejsza ryzyko pomylenia wartości tego samego typu, ale o różnych znaczeniach (np. mile i km).

W poniższym przykładzie założono, że system metryczny jest domyślny, podczas gdy w przypadku starszych danych wymagana jest konwersja na mile. Haxe może automatycznie przeliczać mile na kilometry, ale nie odwrotnie.

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
  }
}

Jak pokazuje przykład, przypisanie „km = one100Miles;” nie wymaga jawnej konwersji. zrobić właściwą rzecz.

Typowanie strukturalne

W wielu funkcjonalnych językach programowania główną rolę odgrywa typowanie strukturalne . Haxe zatrudnia go w obecności anonimowych typów, używając mianownik pisanie o programowaniu obiektowym , gdy zaangażowane są tylko wymienione typy. Typy anonimowe w Haxe są analogiczne do niejawnych interfejsów języka Go, jeśli chodzi o pisanie. W przeciwieństwie do interfejsów Go, możliwe jest skonstruowanie wartości przy użyciu typu anonimowego.

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"});
	}
}

Architektura wewnętrzna

Kompilator

Kompilator Haxe jest podzielony na jeden frontend i wiele backendów. Frontend tworzy abstrakcyjne drzewo składni (AST) na podstawie kodu źródłowego i wykonuje sprawdzanie typu, rozwijanie makr i optymalizację na AST . Różne backendy tłumaczą przetworzone AST na kod źródłowy lub generują kod bajtowy , w zależności od celu.

Kompilator jest napisany w OCaml . Można go uruchomić w trybie serwera, aby zapewnić uzupełnianie kodu dla zintegrowanych środowisk programistycznych (IDE) i utrzymywać pamięć podręczną, aby jeszcze bardziej przyspieszyć kompilację.

Zobacz też

Bibliografia

Zewnętrzne linki