Шинода, Майк
- 1 year ago
- 0
- 0
Haxe — высокоуровневый кросс-платформенный язык программирования с открытым исходным кодом , а также компилятор , с помощью которого можно создавать приложения и генерировать исходный код для разных платформ, сохраняя единую кодовую базу .
Haxe включает в себя функциональность, поддерживаемую на всех платформах , например: числовые типы данных, строки , массивы , а также поддержку некоторых файловых форматов ( xml , zip ) . Haxe также включает в себя поддержку специфических API для каждой целевой платформы компилятора.
Код, написанный на языке Haxe, может быть скомпилирован в код JavaScript , C++ , Java , JVM , PHP , C# , Python , Lua и Node.js . Haxe-код также компилируется в SWF, HashLink и , байт-код , а так же может быть выполнен в режиме интерпретации .
Основные пользователи Haxe — это , , Nickelodeon , Disney , Mattel , Hasbro , Coca Cola , Toyota и BBC . и — популярные фреймворки Haxe для создания мультиплатформенного контента и программ из единой кодовой базы . Кроме этого, в данный момент активно развивается . В связи с всё большим вытеснением технологии Adobe Flash в последние годы в пользу HTML5 , Haxe, Unity и другие кросс-платформенные инструменты уделяют последнему всё больше времени, сохраняя обратную поддержку с Adobe Flash Player .
Самым значимым аспектом разработки архитектуры Haxe было решение о поддержке Adobe Flash, JavaScript и серверных приложений единой кодовой базой . В типичных веб-проектах разработчики должны использовать множество разных языков, чтобы построить полноценное веб-приложение :
Haxe был создан с идеей объединения всех этих компонентов единой кодовой базой, а также упрощения взаимодействия между компонентами приложения .
В книге, за авторством Николаса Кеннеси (основателя проекта Haxe), указываются первоначальные цели создания Haxe :
Компилятор Haxe разделён на один фронтенд и множество бэкэндов. Фронтенд отвечает за парсинг и проверку типов, применение макросов, общую оптимизацию, различные трансформации кода и создания кода в виде абстрактного синтаксического дерева (АСД). Каждый из бэкендов отвечает за трансляцию этого АСД в исходный код или байткод целевой платформы.
Компилятор написан на OCaml . Он может быть запущен в режиме сервера для поддержки автодополнения кода в IDE, также в этом режиме поддерживается кэш для уменьшения времени компиляции .
Компилятор Haxe — оптимизирующий компилятор , также использующий , свёртку констант , удаление мёртвого кода (DCE) для оптимизации производительности скомпилированных программ.
Производительность программ, написанных на Haxe, зависит от целевой платформы.
Разработка Haxe началась в октябре 2005 , а первая бета-версия была выпущена в феврале 2006. Haxe 1.0 был выпущен в апреле 2006 и поддерживал трансляцию в Adobe Flash , Javascript и .
Haxe был разработан Николасом Хеннесси (Nicolas Cannasse) и другими авторами, и первоначально был назван haXe , потому что это короткое, простое имя, а также «у него есть X в названии» — атрибут, необходимый для того, чтобы новая технология стала успешной, с юмором отмечал автор языка .
Haxe — это преемник ActionScript 2 компилятора MTASC с открытым исходным кодом, также сделанный Николасом Хеннесси и выпущенный под лицензией GNU General Public License версии 2 или выше .
Haxe имеет много общего с ActionScript 3 . Компилятор Haxe разрабатывается на языке OCaml , но для того, чтобы писать на Haxe, знаний OCaml не требуется.
Преимущества использования Haxe включают в себя:
Рекомендуемая IDE для разработки на Haxe — это FlashDevelop , которая поддерживает ActionScript 2, 3 и Haxe, как основные языки с подсветкой синтаксиса , и другими возможностями . Эта IDE также поддерживает , рефакторинг и интерактивную отладку .
Для того, чтобы использовать уже существующий код, сообщество открытого ПО создало конверторы исходного кода для:
Язык Haxe можно транслировать в байткод различных виртуальных машин, таких как Adobe Flash Player и , а также в исходные коды ActionScript 3 , JavaScript , включая экспериментально поддерживаемые C++ и C# . Эта стратегия «компиляции» в различные исходные коды была разработана под вдохновение парадигмы «один раз написать, запускать где угодно». Данная стратегия также позволяет выбирать программисту наилучшую платформу для работы программ.
Генератор кода | Результат | Платформа | Использование | Начиная с какой версии Haxe |
---|---|---|---|---|
AVM1 | Байткод | Adobe Flash Player 6+ | Desktop, Browser | 2005 (alpha) |
Байткод | Adobe Flash Player 9+, Adobe AIR , | Desktop, Browser, Server | 2005 (alpha) | |
ActionScript 3 | Исходный код | Adobe Flash Player 9+ | Server, Desktop | 2007 (1.12) |
C++ (hxcpp) | Исходный код | Windows, Linux, Mac OS X | Server, Desktop, CLI | 2009 (2.04) |
C++ | Исходный код | Android , Apple iOS , Palm webOS | Mobile | 2009 (2.04) |
C# | Исходный код | .NET Framework | Server, Desktop, Mobile | 2012 (2.10) |
Java | Исходный код | Java | Server, Desktop | 2012 (2.10) |
JavaScript | Исходный код | HTML 5 , Node.js , PhoneGap | Server, Desktop, Browser, Mobile | 2006 (beta) |
Байткод | NekoVM | Server, Desktop, CLI | 2005 (alpha) | |
PHP | Исходный код | PHP | Server | 2008 (2.0) |
Python | Исходный код | Python | CLI, Web, Desktop | 2014 (3.2) |
Lua | Исходный код | Lua | Web, Desktop, Mobile | 2016 (3.3) |
Haxe — это объектно-ориентированный язык общего назначения, с поддержкой механизма обработки исключений и вывода типов для параметров классов. Также языком и библиотеками поддерживаются обобщённое программирование , рефлексия , итераторы и функциональное программирование . Haxe также, в отличие от многих других языков, одновременно поддерживает и статическую и динамическую типизацию. Компилятор может проверять вывод типов и выдавать ошибки времени компиляции, но также разработчики могут выключить эту проверку, и положиться на динамическую проверку типов целевой платформы.
Язык Haxe похож на ECMAScript , хотя практически любой код на ECMAScript не сможет быть скомпилирован на Haxe без модификации. В отличие от ECMAScript, Haxe — компилируемый язык . Haxe был создан под влиянием ActionScript , Java , и OCaml .
Так как Haxe был основан на ActionScript 3 , он поддерживает все функции Flash API, хотя и требует лучше оформленный код и более высокие стандарты разработки, нежели компиляторы Adobe.
Эта программа напишет «Hello World» после компиляции и запуска:
class Main {
static function main() {
trace("Hello World");
}
}
Проверить этот код можно, сохранив его в файл с именем
Main.hx
и запустив компилятор Haxe со следующими параметрами:
haxe -main Main --interp
. Эта команда запустит Haxe Compiler в режиме интерпретации кода и выведет на экран терминала
Main.hx:3: Hello world
.
Haxe — статически типизированный язык. Он имеет богатую систему типов, включая классы, интерфейсы, функциональные типы, анонимные типы, алгебраические типы данных ( ADT , называемые «перечислениями» в Haxe), а также абстрактные типы данных. Классы, алгебраические типы данных и функциональные типы поддерживают параметрический полиморфизм , основанный на стирании типов, в других объективно-ориентированных языках часто называемый «Дженериками».
Haxe включает с себя поддержку и полиморфизма подтипов .
К тому же, Haxe поддерживает и . Для облегчения работы программистов и без ущерба безопасности типов, Haxe поддерживает вывод типов, который во многих случаях позволяет не писать типы вручную.
Классы (ключевое слово «class») в Haxe похожи на таковые в Java или AS3 . Их полями могут быть методы, статические переменные класса или свойства экземпляра класса. Haxe поддерживает атрибуты доступа «public» и «private», а также более продвинутые методы контроля доступа (ACL, ссылки), которые описываются аннотациями. Методы и статические переменные с постоянным значением могут быть встроены с помощью ключевого слова «inline».
Интерфейсы в Haxe похожи на интерфейсы Java .
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();
}
Перечисляемые типы — это ключевая особенность языка. Перечисления могут иметь собственные параметры, а также быть рекурсивными . Они похожи на алгебраические типы данных , как таковые в языках вроде ML или Haskell . Строго говоря, это правильные типы-суммы , при условии, что типы‑произведения , включенные в них, обязаны быть определены внутри этих типов-сумм. Это значит, что перечисления не просто именованные «магические числа», как в большинстве языков, ими можно элегантно решать сложные архитектурные проблемы:
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));
}
}
Haxe также поддерживает параметрические перечисляемые типы. Примером могут послужить реализация типов Option, Either и ConsList, причем ConsList ещё и рекурсивный:
enum Option<T> {
Some(v:T);
None;
}
enum Either<T,U> {
Left(v:T);
Right(v:U);
}
enum ConsList<T> {
Nil;
Cons(head:T,tail:ConsList<T>);
}
Документация на сайте указывает , что Haxe также поддерживает обобщённые алгебраические типы (GADT), но не приводит пример создания такового.
Анонимные типы определяются с помощью явного описания их структуры, им также можно назначить псевдоним, используя определение типа (ключевое слово «typedef»):
typedef Anon = { a:Int, b:String, c:Float->Void };
Функциональные типы являются объектами первого класса в Haxe. Они описываются, используя стрелки между типами аргументов, и между типами и возвращаемым значением, как и в многих других функциональных языках. Однако, в отличие от Haskell или семейства ML , не все функции в Haxe унарные (функции с одним аргументом), по умолчанию они не могут быть частично применены . Таким образом сигнатуры типов в следующих примерах имеют отличное от вышеупомянутых языков значение.
Тип F — это функция, которая принимает Int и String как аргументы и возвращает Float как результат.
В языках, где существуют только унарные функции, этот тип означал бы функцию, которая принимает Int как аргумент и возвращает функцию типа String->Float.
Типы F2 и F3 описывают один и тот же тип. Они оба описывают бинарные функции, которые возвращают бинарную функцию типа F. Для F2 описывается случай использования функционального типа внутри другого определения.
typedef F = Int->String->Float;
typedef F2 = Int->String->F;
typedef F3 = Int->String->(Int->String->Float);
Концепция, названная абстрактные типы , — это последнее дополнение в систему типов Haxe. Они позволяют повторно использовать существующие типы для специфических целей, например, реализации типов для единиц измерения, при этом сильно уменьшая возможность смешивания разных систем (например мили и километры). Термин «абстрактный тип» в контексте языка Haxe имеет другое значение, в отличие от обычных абстрактных типов .
Следующий пример предполагает, что метрическая система используется по умолчанию, а конвертация в мили необходима, чтобы поддерживать устаревшие данные. Haxe способен автоматически преобразовывать мили в километры, но не в обратную сторону.
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
}
}
Пример показывает, что не обязательно делать явное преобразование
km = one100Miles;
для использования корректных единиц.
Структурная типизация играет важную роль во многих функциональных языках программирования и, в то же время, довольно малую в распространенных ООП языках. В отличие от номинальной системы типов, равенство двух типов определяется не равенством каких-либо имён типа, а скорее устройством типа. Структурные типы можно рассматривать как неявные интерфейсы:
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"});
}
}
Также, на платформе Haxe:
Другие языки, компилирующиеся в JavaScript:
Другие мультиплатформенные языки:
haxe --wait [host:]port