Haxe

Haxe — высокоуровневый кросс-платформенный язык программирования с открытым исходным кодом, а также компилятор, с помощью которого можно создавать приложения и генерировать исходный код для разных платформ, сохраняя единую кодовую базу[3][4][5][6].

Haxe
Изображение логотипа
Класс языка Мультипарадигмальный
Появился в 2005
Разработчик Haxe Foundation
Выпуск
Система типов статическая, динамическая через аннотации
Испытал влияние Java, OCaml, ActionScript, MTASC[2], JavaScript и C++
Лицензия GPL v2, библиотека: MIT
Сайт haxe.org (англ.)
Платформа ARM, IA-32, x64
ОС Android, iOS; Linux, macOS, Windows

Haxe включает в себя функциональность, поддерживаемую на всех платформах, например: числовые типы данных, строки, массивы, а также поддержку некоторых файловых форматов (xml, zip)[4][7]. Haxe также включает в себя поддержку специфических API для каждой целевой платформы компилятора.

Код, написанный на языке Haxe, может быть скомпилирован в код JavaScript, C++, Java, JVM, PHP, C#, Python, Lua и Node.js[8]. Haxe-код также компилируется в SWF, HashLink и Neko, байт-код, а так же может быть выполнен в режиме интерпретации[8].

Основные пользователи Haxe — это TiVo, Prezi, Nickelodeon, Disney, Mattel, Hasbro, Coca Cola, Toyota и BBC[9][10]. OpenFL и Flambe — популярные фреймворки Haxe для создания мультиплатформенного контента и программ из единой кодовой базы[10]. Кроме этого, в данный момент активно развивается Snõwkit[11]. В связи с всё большим вытеснением технологии Adobe Flash в последние годы в пользу HTML5, Haxe, Unity и другие кросс-платформенные инструменты уделяют последнему всё больше времени, сохраняя обратную поддержку с Adobe Flash Player[10][12].

Архитектура

править

Единый язык

править

Самым значимым аспектом разработки архитектуры Haxe было решение о поддержке Adobe Flash, JavaScript и серверных приложений единой кодовой базой[13][14]. В типичных веб-проектах разработчики должны использовать множество разных языков, чтобы построить полноценное веб-приложение[13][14]:

  • PHP или другой серверный язык для генерации HTML;
  • JavaScript для манипуляций над HTML на стороне клиента;
  • ActionScript для графической части, при использовании Flash;
  • XML или похожий протокол для коммуникации между компонентами.

Haxe был создан с идеей объединения всех этих компонентов единой кодовой базой, а также упрощения взаимодействия между компонентами приложения[13][14][15].

В книге, за авторством Николаса Кеннеси (основателя проекта Haxe), указываются первоначальные цели создания Haxe[13]:

  • создать язык более мощный, чем ActionScript 2 или ActionScript 3;
  • сделать так, чтобы было легко портировать приложения с ActionScript на Haxe;
  • сделать язык, поддерживающий разработку для Flash 6, 7, 8 и 9;
  • сделать язык, поддерживающий разработку для JavaScript/AJAX;
  • сделать язык, поддерживающий разработку серверно-ориентированных программ, вместо PHP или Java.

Компилятор

править

Компилятор Haxe разделён на один фронтенд и множество бэкэндов. Фронтенд отвечает за парсинг и проверку типов, применение макросов, общую оптимизацию, различные трансформации кода и создания промежуточного представления кода в виде абстрактного синтаксического дерева (АСД). Каждый из бэкендов отвечает за трансляцию этого АСД в исходный код или байткод целевой платформы.

Компилятор написан на OCaml. Он может быть запущен в режиме сервера для поддержки автодополнения кода в IDE, также в этом режиме поддерживается кэш для уменьшения времени компиляции[16].

Производительность

править

Компилятор Haxe — оптимизирующий компилятор, также использующий подстановку функций, свёртку констант, удаление мёртвого кода (DCE) для оптимизации производительности скомпилированных программ.

Производительность программ, написанных на Haxe, зависит от целевой платформы.

  • ActionScript 3: программы, скомпилированные на Haxe, обычно быстрее, чем программы, скомпилированные с помощью Flex SDK ActionScript Compiler.[17] Однако, используя ActionScript Compiler 2 (ASC2) и грамотно составленный код[18], можно добиться сравнимой производительности.
  • JavaScript: программы, скомпилированные на Haxe, сравнимы по скорости с программами, написанными просто на JavaScript[19]. OpenFl — самый распространённый фреймворк, который можно запустить на HTML5/JavaScript, но приложения, построенные с помощью этого фреймворка, на текущий момент страдают от потерь производительности на мобильных устройствах[19].
  • C++: программы, скомпилированные на Haxe, работают почти также быстро, как и написанные просто на C++, но приложения, построенные с помощью OpenFL, могут страдать от потерь производительности[20].

Разработка

править

Разработка Haxe началась в октябре 2005[21], а первая бета-версия была выпущена в феврале 2006. Haxe 1.0 был выпущен в апреле 2006 и поддерживал трансляцию в Adobe Flash, Javascript и Neko.

Haxe был разработан Николасом Хеннесси (Nicolas Cannasse) и другими авторами, и первоначально был назван haXe, потому что это короткое, простое имя, а также «у него есть X в названии» — атрибут, необходимый для того, чтобы новая технология стала успешной, с юмором отмечал автор языка[22].

Haxe — это преемник ActionScript 2 компилятора MTASC с открытым исходным кодом, также сделанный Николасом Хеннесси[13][23] и выпущенный под лицензией GNU General Public License версии 2 или выше[24].

Haxe имеет много общего с ActionScript 3. Компилятор Haxe разрабатывается на языке OCaml, но для того, чтобы писать на Haxe, знаний OCaml не требуется.

Преимущества использования Haxe включают в себя:

  • платформо-независимая разработка;
  • разработка на высокоуровневом языке программирования;
  • возможность использовать, как целевую платформу, передовые C#.NET и Adobe AIR;
  • возможность разработки для устройств, поддерживающих только C++[25].

Исходный код

править

Рекомендуемая IDE для разработки на Haxe — это FlashDevelop[13], которая поддерживает ActionScript 2, 3 и Haxe, как основные языки с подсветкой синтаксиса, автодополнением кода и другими возможностями[13][26]. Эта IDE также поддерживает сворачивание кода, рефакторинг и интерактивную отладку.[27]

Для того, чтобы использовать уже существующий код, сообщество открытого ПО создало конверторы исходного кода для:

  • ActionScript 3 в Haxe[28],
  • C# в Haxe[29].

Поддержка платформ

править

Язык Haxe можно транслировать в байткод различных виртуальных машин, таких как Adobe Flash Player и Neko, а также в исходные коды ActionScript 3, JavaScript, включая экспериментально поддерживаемые C++ и C#. Эта стратегия «компиляции» в различные исходные коды была разработана под вдохновение парадигмы «один раз написать, запускать где угодно». Данная стратегия также позволяет выбирать программисту наилучшую платформу для работы программ.

Генератор кода Результат Платформа Использование Начиная с какой версии Haxe
AVM1[7] Байткод Adobe Flash Player 6+ Desktop, Browser 2005 (alpha)
AVM2[7] Байткод Adobe Flash Player 9+, Adobe AIR, Tamarin VM Desktop, Browser, Server 2005 (alpha)
ActionScript 3[7] Исходный код Adobe Flash Player 9+ Server, Desktop 2007 (1.12)
C++ (hxcpp)[7] Исходный код Windows, Linux, Mac OS X Server, Desktop, CLI 2009 (2.04)
C++ Исходный код Android[30], Apple iOS[31], Palm webOS[32] Mobile 2009 (2.04)
C#[7] Исходный код .NET Framework Server, Desktop, Mobile 2012 (2.10)
Java[7] Исходный код Java Server, Desktop 2012 (2.10)
JavaScript[7] Исходный код HTML 5, Node.js, PhoneGap Server, Desktop, Browser, Mobile 2006 (beta)
Neko[7] Байткод NekoVM Server, Desktop, CLI 2005 (alpha)
PHP[7] Исходный код PHP Server 2008 (2.0)
Python[7] Исходный код Python CLI, Web, Desktop 2014 (3.2)
Lua[33] Исходный код Lua Web, Desktop, Mobile 2016 (3.3)

Haxe — это объектно-ориентированный язык общего назначения, с поддержкой механизма обработки исключений и вывода типов для параметров классов. Также языком и библиотеками поддерживаются обобщённое программирование, рефлексия, итераторы и функциональное программирование[34]. Haxe также, в отличие от многих других языков, одновременно поддерживает и статическую и динамическую типизацию. Компилятор может проверять вывод типов и выдавать ошибки времени компиляции, но также разработчики могут выключить эту проверку, и положиться на динамическую проверку типов целевой платформы.

Язык Haxe похож на ECMAScript, хотя практически любой код на ECMAScript не сможет быть скомпилирован на Haxe без модификации. В отличие от ECMAScript, Haxe — компилируемый язык. Haxe был создан под влиянием ActionScript, Java, и OCaml[14].

Так как Haxe был основан на ActionScript 3, он поддерживает все функции Flash API, хотя и требует лучше оформленный код и более высокие стандарты разработки, нежели компиляторы Adobe.

Hello world

править

Эта программа напишет «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();
}

Перечисления

править

Перечисляемые типы — это ключевая особенность языка. Перечисления могут иметь собственные параметры, а также быть рекурсивными[35]. Они похожи на алгебраические типы данных, как таковые в языках вроде 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>);
}

Документация на сайте указывает[36], что 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:

Другие мультиплатформенные языки:

Примечания

править
  1. Release 4.3.6 — 2024.
  2. https://haxe.org/manual/introduction-haxe-history.html
  3. Nicolas' announcement of spelling change on Haxe official mail list.
  4. 1 2 Ponticelli, Franco. Professional haXe and Neko (неопр.). — Wiley, 2008. — ISBN 0470122137. Архивировано 28 ноября 2015 года.
  5. Ivanov, Michael. Away3D 3.6 Cookbook (неопр.). — Packt Publishing Ltd[англ.], 2011. — ISBN 1849512817. Архивировано 2 ноября 2015 года.
  6. Doucet, Lars Haxe/OpenFL for home game consoles. Gamasutra (3 июня 2015). Дата обращения: 9 октября 2015. Архивировано 8 сентября 2015 года.
  7. 1 2 3 4 5 6 7 8 9 10 11 Introduction to the Haxe Standard Library Архивная копия от 14 августа 2015 на Wayback Machine, Haxe Docs
  8. 1 2 Compiler Targets. Haxe - The Cross-platform Toolkit. Дата обращения: 23 февраля 2021. Архивировано 2 марта 2021 года.
  9. Companies using Haxe Архивная копия от 7 сентября 2015 на Wayback Machine, Haxe Docs
  10. 1 2 3 Doucet, Lars Dear Adobe: Support Haxe, save your Tools. Gamasutra (24 июня 2014). Дата обращения: 9 октября 2015. Архивировано 24 сентября 2015 года.
  11. about snõwkit. snõwkit (20 сентября 2014). Дата обращения: 9 августа 2016. Архивировано 9 августа 2016 года.
  12. Doucet, Lars Flash is dead, long live OpenFL! Gamasutra (18 марта 2014). Дата обращения: 9 октября 2015. Архивировано 30 августа 2015 года.
  13. 1 2 3 4 5 6 7 Grden, John; Mineault, Patrick; Balkan, Aral; Hughes, Marc; Arnold, Wade. The Essential Guide to Open Source Flash Development (англ.). — Apress, 2008. — P. Chapter 9 (Using Haxe). — ISBN 1430209941. Архивировано 8 февраля 2016 года.
  14. 1 2 3 4 Haxe Interview (неопр.). — Io Programmo, 2009. — 1 April. — С. 1—6. Архивировано 8 декабря 2015 года.
  15. Fisher, Matt. HTML5 for Flash Developers (неопр.). — Packt Publishing Ltd[англ.], 2013. — ISBN 1849693331. Архивировано 24 ноября 2015 года.
  16. Server mode command-line : haxe --wait [host:]port
  17. AS3 vs haXe performance Архивная копия от 5 января 2013 на Wayback Machine, SplashDust website
  18. AS3 Performance Optimization Архивная копия от 6 октября 2015 на Wayback Machine, Starling Wiki
  19. 1 2 Vadim Dyachenko. On “You can’t make good HTML5 games in Haxe”. Yellow After Life (5 декабря 2013). Дата обращения: 9 октября 2015. Архивировано из оригинала 30 сентября 2015 года.
  20. Kaya, Talha OpenFL & Haxe, A Bumpy Start. Gamasutra (4 июля 2014). Дата обращения: 9 октября 2015. Архивировано 24 сентября 2015 года.
  21. Haxe 3.2 Release. Github. Дата обращения: 9 октября 2015. Архивировано 21 февраля 2016 года.
  22. Haxe mailing list post on naming. Архивировано 28 марта 2007 года.
  23. MTASC Compiler Архивная копия от 20 октября 2020 на Wayback Machine, MTASC website
  24. Haxe license page. Архивировано 12 мая 2012 года.
  25. Haxe introduction page. Архивировано 4 мая 2012 года.
  26. Main Page, FlashDevelop Wiki Архивная копия от 10 октября 2015 на Wayback Machine, «first class support for Flash ActionScript (AS2 and AS3) and Haxe development»
  27. Haxe Support Архивная копия от 6 июля 2015 на Wayback Machine, FlashDevelop Wiki
  28. as3hx Архивная копия от 14 мая 2015 на Wayback Machine, AS3 to Haxe converter, Haxe source code repository
  29. CS2HX — C# to haXe converter Архивная копия от 4 марта 2010 на Wayback Machine, CodePlex project hosting
  30. Blog post mentioning Android port progress. Дата обращения: 9 октября 2015. Архивировано 28 декабря 2015 года.
  31. Haxe, iPhone & C++ At Last Архивная копия от 15 апреля 2012 на Wayback Machine, GameHaxe website
  32. How to get started with Haxe 2.06 and the webOS PDK [archived on WayBackMachine]. Архивировано 22 октября 2014 года.
  33. Hello Lua! - Haxe - The Cross-platform Toolkit. Дата обращения: 9 августа 2016. Архивировано 6 августа 2016 года.
  34. Haxe language reference. Архивировано 2 мая 2012 года.
  35. Haxe reference detailing the use of enum. Архивировано 11 мая 2012 года.
  36. Language Features. Haxe - The Cross-platform Toolkit. Haxe Foundation. Дата обращения: 30 апреля 2015. Архивировано 16 мая 2015 года.
  37. A Scala to JavaScript compiler. Дата обращения: 9 октября 2015. Архивировано 10 августа 2015 года.

Ссылки

править