Haxe
![]() | |
Paradigm | Multi-paradigm |
---|---|
Developer | Haxe Foundation |
First appeared | 2005 |
Stable release | 4.1.3[1]
/ July 22, 2020 |
Preview release | 4.0.0-rc.5
/ September 12, 2019[2] |
Typing discipline | Static, dynamic via annotations, nominal |
Implementation language | OCaml |
Platform | ARM; IA-32, x86-64 |
OS | Android, iOS; Linux, macOS, Windows |
License | GPL 2.0, library: MIT |
Filename extensions | .hx, .hxml |
Website | haxe |
Influenced by | |
ActionScript, OCaml, Java |
Haxe is an open source high-level cross-platform multi-paradigm programming language and compiler that can produce applications and source code, for many different computing platforms, from one code-base.[3][4][5][6] It is free and open-source software, distributed under the GNU General Public License (GPL) version 2, and the standard library under the MIT License.
Haxe includes a set of common functions that are supported across all platforms, such as numeric data types, text, arrays, binary and some common file formats.[4][7] Haxe also includes platform-specific application programming interface (API) for Adobe Flash, C++, PHP and other languages.[4][8] OpenFL and Flambe are popular Haxe frameworks that enable creating multi-platform content from one codebase.[9]
Haxe originated with the idea of supporting client-side and server-side programming in one language, and simplifying the communication logic between them.[10][11][12] Code written in the Haxe language can be source-to-source compiled into ActionScript 3, JavaScript, Java, C++, C#, PHP, Python, Lua[13] and Node.js.[4][7][14][15] Haxe can also directly compile SWF, HashLink and Neko bytecode.
Many popular IDEs and source code editors have support available for Haxe development.[16] No particular development environment or tool set is officially recommended by the Haxe Foundation, although VS Code and IntelliJ IDEA have extensions to support Haxe development. The core functionalities of syntax highlighting, code completion, refactoring, debugging, etc., are available in various degree.
To help leverage existing code, the Haxe community has created source code converters for ActionScript 3 to Haxe[17] and C# to Haxe.[18] The Haxe compiler can also output Haxe into standalone ActionScript 3, C++, C#, Java, PHP, Python and Lua source code,[19] which can then be pulled out of the Haxe ecosystem and developed with traditional workflows.
Major users of Haxe include BBC, Coca-Cola, Disney, Hasbro, Mattel, Nickelodeon, Prezi, TiVo, Toyota, and Zynga.[20][9]
History
Development of Haxe began in October 2005.[21] The first beta version was released in February 2006. Haxe 1.0 was released in April 2006, with support for Adobe Flash, JavaScript, and Neko programs. Support for PHP was added in 2008, and C++ was added in 2009. More platforms such as C# and Java were added with a compiler overhaul in 2012.
Haxe was developed by Nicolas Cannasse and other contributors, and was originally named haXe because it was short, simple, and "has an X inside", which the author asserts humorously is needed to make any new technology a success.[22]
Haxe is the successor to the open-source ActionScript 2 compiler MTASC, also built by Nicolas Cannasse,[11][23] and is released under the GNU General Public License version 2 or later.[24]
Compiler
The Haxe language can compile into bytecode for different virtual machines such as the Adobe Flash Player, HashLink and Neko, and can generate source code in C#, C++, ActionScript 3, JavaScript and Lua
The Haxe compiler is an optimizing compiler, and uses function inlining, constant folding, and dead code elimination (DCE) to optimize the run-time performance of compiled programs.
This strategy of compiling to multiple source code languages is inspired by the write once, run anywhere paradigm. It also allows the programmer to choose the best platform for the job. Typical Haxe programs run identically on all platforms, but developers can specify platform-specific code and use conditional compilation to prevent it from compiling on other platforms.
The following table documents platform and language support in Haxe.
Code generator | Output | Platform | Use | Since Haxe version |
---|---|---|---|---|
ActionScript 3[7] | source | Adobe Flash Player 9+, Adobe AIR | Server, desktop | 2007 (1.12) |
C++ (hxcpp)[7] | source | Windows, Linux, macOS | Server, desktop, CLI | 2009 (2.04) |
C++ | source | Android,[25] Apple iOS,[15] Palm webOS[26] | Mobile | 2009 (2.04) |
C#[7] | source | .NET Framework | Server, desktop, mobile | 2012 (2.10) |
Java[7] | source | Java | Server, desktop | 2012 (2.10) |
JavaScript[7] | source | HTML5, NodeJS, PhoneGap | Server, desktop, browser, mobile | 2006 |
Neko[7] | byte code | NekoVM | Server, desktop, CLI | 2005 |
PHP[7] | source | PHP | Server | 2008 (2.0) |
Python[7] | source | Python | CLI, web, desktop | 2014 (3.2) |
Lua[7] | source | Lua | CLI, web, desktop, mobile | 2016 (3.3) |
SWF with ActionScript 3[7] | byte code | Adobe Flash Player 9+, Adobe AIR, Tamarin | Desktop, browser, server | 2005 |
HashLink[7] | byte code | HashLink VM or HL/C (compile to C file) | Server, desktop, mobile (for C export) | 2016 (3.4) |
Language comparison
Haxe has much in common with ActionScript 3. The Haxe compiler is developed in the OCaml language. No knowledge of OCaml is needed to develop applications using Haxe. Advantages to using Haxe over ActionScript 3 include:
- More advanced language features such as extension methods and functional programming
- Ability to target alternative platforms such as C#.NET
- Ability to target devices that support only C++[27]
Performance comparison
The run-time performance of Haxe programs varies depending on the target platform:
- ActionScript 3: Programs produced using the Haxe compiler usually run faster than programs produced using the Apache Flex SDK ActionScript Compiler.[28] However, using ActionScript Compiler 2 (ASC2) with manual optimizing,[29] many have reported comparable performance.
- JavaScript: Programs produced using the Haxe compiler run at a comparable speed to handwritten JavaScript programs.[30] OpenFL is a common Haxe-powered framework that can run in HTML5-JavaScript, but content built with OpenFL currently suffers performance issues on mobile devices.[30]
- C++: Programs produced using the Haxe compiler rival handwritten C++ programs, but C++ applications built with OpenFL suffer major performance issues.[31]
Language
Haxe is a general-purpose language supporting object-oriented programming, generic programming, and various functional programming constructs. Features such as iterations, exceptions, and code reflection are also built-in functions of the language and libraries.[32] Unusual among programming languages, Haxe contains a type system which is both strong and dynamic. The compiler will check types implicitly and give compile-time errors, but it also enables the programmer to bypass type-checking and rely on the target platform's dynamic type-handling.
Since Haxe had its origins in ActionScript 3, all of the existing Flash API can be used, although Haxe requires better-formed code and programming standards than Adobe compilers (for example, regarding scoping and data typing).
Type system
Haxe has a sophisticated and flexible type system. The type kinds it offers are classes, interfaces, function-method types, anonymous types, algebraic data types (ADTs, called enum in Haxe), and abstract types. Parametric polymorphism is possible with classes, ADTs and function types, giving the language support for generic programming based on type erasure. This includes support for variance in polymorphic functions, although not in type constructors.
The type system is static unless annotations for dynamic typing are present, for use with targets that support them. Type checking follows nominal typing with the exception of anonymous types where structural typing is used instead. Finally, type inference is supported, allowing for variable declarations without type annotations.
Classes
Classes (keyword class
) in Haxe are similar to those in Java or ActionScript 3. Their fields can be either methods, variables, or properties, each static or per instance respectively.
Haxe supports the accessors public
and private
, and more advanced methods for access control (ACL, link) that are denoted using annotations. Methods and static constant variables can be inlined using the keyword inline
.
Interfaces in Haxe are very similar to those in, for example, 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();
}
Enumerated types
Enumerated types are an important feature of the language; they can have type parameters and be recursive.[33] They provide basic support for algebraic data types, allowing the inclusion of product types, in a fashion similar to Haskell and ML. A switch
expression can apply pattern matching to an enum value, allowing for elegant solutions to complex programming problems:
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));
}
}
Examples of parametric enum types are the Haxe standard library types Option[34] and Either:[35]
enum Option<T> {
Some(v:T);
None;
}
enum Either<L, R> {
Left(v:L);
Right(v:R);
}
Haxe also supports generalized algebraic data types (GADTs).[36][37]
Anonymous types
Anonymous types are defined by denoting their structure explicitly, using a syntax that follows the mathematical record-based representation of a type. They can be used to implement structural typing for function arguments (see below), and can be given an alias with the keyword typedef
:
typedef AliasForAnon = { a:Int, b:String, c:Float->Void };
Function types
Functions are first-class values in Haxe. Their type is denoted by using arrows between argument types, and between the argument type(s) and return type, as common in many functional languages. However, unlike in prominent examples like Haskell or the ML language family, not all functions are unary functions (functions with one argument only), and in Haxe, functions can't be partially applied per default. Thus, the following type signatures have different semantics than in the aforementioned languages. The type F is a function that takes an Int and a String as arguments, and returns a value of type Float.
The same notation in a language with unary functions only, would refer to a function that takes an Int as argument, and returns a function of type String->Float.
Types F2 and F3 denote the same type. Both are binary functions that return a binary function of type F. For F3 the syntax to declare a function type within a function type is used.
typedef F = Int->String->Float;
typedef F2 = Int->String->F;
typedef F3 = Int->String->(Int->String->Float);
Since Haxe 4 you can also name the arguments:
typedef F = (value:Int, label:String)->Float;
typedef F2 = (value:Int, label:String)->F;
typedef F3 = (value:Int, label:String)->((value:Int,String)->Float);
Abstract types
The latest addition to the Haxe type system is a concept termed abstract types. As used in Haxe, this refers to something different from a conventional abstract type. They are used to make conversions between types implicit, allowing reuse of existing types for specific purposes, like implementing types for units of measurement. This greatly reduces the risk of mixing up values of the same underlying type, but with different meanings (e.g., miles vs. km).
The following example assumes that the metric system is the default, while a conversion to miles is needed for legacy data. Haxe can automatically convert miles to kilometers, but not the reverse.
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
}
}
As the example shows, no explicit conversion is needed for the assignment "km = one100Miles;" to do the right thing.
Structural typing
In many functional programming languages, structural typing plays a major role. Haxe employs it in the presence of anonymous types, using the nominative typing of object-oriented programming, when only named types are involved. Anonymous types in Haxe are analogous to the implicit interfaces of the language Go as to typing. In contrast with Go interfaces, it is possible to construct a value using an anonymous type.
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"});
}
}
Internal architecture
Compiler
The Haxe compiler is divided into one frontend and multiple backends. The frontend creates an abstract syntax tree (AST) from the source code, and performs type checking, macro expansion, and optimization on the AST. The various backends translate the processed AST into source code or generate bytecode, depending on their target.
The compiler is written in OCaml. It can be run in server-mode to provide code completion for integrated development environments (IDEs) and maintain a cache, to further speed compiling.[38]
Targets
In Haxe, supported platforms are known as "targets", which are Haxe modules that provide access to core-APIs (language and bytecode targets), for the compiler-backends that are responsible for generating the respective code, and for runtimes with specific APIs that go beyond the core language support (platform-targets).
- Bytecode Targets produce executable byte code (Neko, SWF, SWF8), that can be executed directly by the runtime (Neko VM, Adobe Flash Player, Adobe AIR). Haxe API and platform-specific API is available.
- Language Targets produce source code (AS3, C++, C#, Java). Most source code must be compiled by a third-party compiler to produce an executable file (Flex SDK, GNU Compiler Collection (GCC), Microsoft Visual C++, .NET Framework, Java compiler). JavaScript and PHP code can be run directly, since the runtime uses just-in-time compilation. Inline code written in the target language can be inserted at any point in the application, thereby supporting the entire platform API; even features missing from the Haxe wrapper API.
- External Modules are type definitions (
extern class
in Haxe) that describe the types of native APIs or libraries, so the Haxe compiler can use static type-checking.
See also
- Comparison of IDE choices for Haxe programmers
- Dart (programming language)
- Nim (programming language)
- Opa (programming language)
- Clojure
- CoffeeScript
- TypeScript
- Scala (programming language)
- Vala (programming language)
- Emscripten
- OpenFL
References
- ^ "Haxe Download List".
- ^ https://haxe.org/download/list/
- ^ "Nicolas' announcement of spelling change on Haxe official mail list".
- ^ a b c d Ponticelli, Franco (2008-02-11). Professional haXe and Neko. Wiley. ISBN 0470122137.
- ^ Ivanov, Michael (2011-05-24). Away3D 3.6 Cookbook. Packt Publishing Ltd. ISBN 1849512817.
- ^ Doucet, Lars (2015-06-03). "Haxe/OpenFL for home game consoles". Gamasutra.
- ^ a b c d e f g h i j k l m Introduction to the Haxe Standard Library, Haxe Docs
- ^ Target Specific APIs, Introduction to the Haxe Standard Library, Haxe Docs
- ^ a b Doucet, Lars (2014-06-24). "Dear Adobe: Support Haxe, save your Tools". Gamasutra.
- ^ "Haxe Interview". Io Programmo. 2009-04-01: 1–6.
{{cite journal}}
: Cite journal requires|journal=
(help) - ^ a b Grden, John; Mineault, Patrick; Balkan, Aral; Hughes, Marc; Arnold, Wade (2008-07-16). The Essential Guide to Open Source Flash Development. Apress. p. Chapter 9 (Using Haxe). ISBN 1430209941.
- ^ Fisher, Matt (2013-01-01). HTML5 for Flash Developers. Packt Publishing Ltd. ISBN 1849693331.
- ^ "Hello Lua! - Haxe". Retrieved 2016-07-09.
- ^ "hxnodejs (4.0.9)". Retrieved 2016-07-09.
- ^ a b Haxe, iPhone & C++ At Last, GameHaxe website
- ^ List of IDEs supporting Haxe, Haxe Foundation
- ^ as3hx, AS3 to Haxe converter, Haxe source code repository
- ^ CS2HX - C# to haXe converter, CodePlex project hosting
- ^ Haxe Compiler Targets, Haxe Docs
- ^ Companies using Haxe, Haxe Docs
- ^ "Haxe 3.2 Release". Github.
- ^ "Haxe mailing list post on naming". Archived from the original on 2007-03-28.
- ^ MTASC Compiler, MTASC website
- ^ "Haxe license page". Archived from the original on 2012-05-12.
- ^ "Blog post mentioning Android port progress".
- ^ "How to get started with Haxe 2.06 and the webOS PDK [archived on WayBackMachine]". Archived from the original on October 22, 2014.
- ^ "Haxe introduction page". Archived from the original on 2012-05-04.
- ^ AS3 vs haXe performance, SplashDust website
- ^ AS3 Performance Optimization, Starling Wiki
- ^ a b Dyachenko, Vadim (2013-12-05). "On "You can't make good HTML5 games in Haxe"". Yellow After Life.
- ^ Kaya, Talha (2014-07-04). "OpenFL & Haxe, A Bumpy Start". Gamasutra.
- ^ "Haxe language reference". Archived from the original on 2012-05-02.
- ^ "Haxe reference detailing the use of enum". Archived from the original on 2012-05-11.
- ^ "haxe/Option.hx at development · HaxeFoundation/haxe". Github.
- ^ "haxe/Either.hx at development · HaxeFoundation/haxe". Github.
- ^ "Language Features". Haxe - The Cross-platform Toolkit. Haxe Foundation. Retrieved 30 April 2015.
- ^ "haxe/TestGADT.hx at development · HaxeFoundation/haxe". Github.
- ^ Server mode command-line:
haxe --wait [host:]port