Haxe, the Ultimate Transpiler

Haxe is an awesome language that can cross-compile to many other languages, such as Javascript, C++, C#, Python, Java, Lua, PHP, ActionScript 3, Flash (byte code), and Neko (byte code). For Flash and Neko, Haxe can compile to byte codes, whereas for the other targets, Haxe acts as a source-to-source translator/compiler (transpiler).

If you’ve heard of TypeScript, then Haxe is pretty similar. It is statically typed, and it also supports type inference. TypeScript is also a transpiler, but it only compiles to Javascript. With Haxe, you have the option of transpiling to many other languages. The Haxe compiler is capable of doing a number of optimizations, such as constant folding, function inlining, and dead-code elimination. More Haxe language features after the jump.

The Jump

Features Overview

Haxe has a number of cool features that may not be available on the target language itself. Your class methods can be marked as inline, allowing codes to be inserted at call-site. There’s static extensions, which works similarly to the one in C#. Pattern matching allows you to match against complex structures and Algebraic Data Types. But my favorite is macros, allowing you to do metaprogramming.

Macros allow you to extend the language further, by writing codes that execute at compile-time, which generates other expressions before being compiled to the target language. This allows you to define your own syntax, for example, a custom for loop that unrolls itself when compiled. Instead of manually unrolling a loop, which affects readability, a macro could allow you to optimize while still having readable codes.

Getting Started

Installing Haxe

To install Haxe, head over to https://haxe.org/download/ and download it for your operating system. If you’re on Windows, Haxe is also available on Chocolatey and can be installed with:

choco install haxe

Getting an IDE

On Windows, I’d recommend using FlashDevelop. There’s also HaxeDevelop which is a custom FlashDevelop distribution for Haxe. You can also use Atom with the language-haxe package. Here’s a list of other Haxe IDEs and code editors compatible with Haxe.

Try it on Your Browser

Want to just try out some of the language features online, but setting it up locally in your computer is a bit too much? You can try it online at http://try.haxe.org/.

Writing a Haxe Program

Hello World in Haxe

Open up your favorite editor. If you’re using FlashDevelop/HaxeDevelop (which I’ll refer to as HaxeDevelop from here on), create a new Haxe project.

Create a HelloWorld.hx:

class HelloWorld
{
    public static function main():Void
    {
        trace("Hello World!");
    }
}

On HaxeDevelop, simply click the “Play” button and it’ll compile and run your program. On any other text editors, you may have to build from the command-line. Open the command prompt or terminal.

To build to neko target, and run it:

haxe -main HelloWorld -neko app.n
neko app

To build to Javascript and run it with node:

haxe -main HelloWorld -js app.js
node app.js

You can also link it to your HTML page, and if you open your browser’s console, you should see the “Hello World” message. This is what the contents of app.js looks like:

(function (console) { "use strict";
var HelloWorld = function() { };
HelloWorld.main = function() {
	console.log("Hello World!");
};
HelloWorld.main();
})(typeof console != "undefined" ? console : {log:function(){}});

For certain targets like C++, C# and Java, you also need to have a its compiler installed. You also specify the output folder instead of an output file:

haxe -main HelloWorld -cpp bin/cpp
cd bin/cpp
HelloWorld.exe

Here’s a full list of compiler command-line switches.

haxe -main HelloWorld -js bin/js/app.js
haxe -main HelloWorld -as3 bin/as3
haxe -main HelloWorld -swf bin/swf/app.swf
haxe -main HelloWorld -neko bin/neko/app.n
haxe -main HelloWorld -php bin/php
haxe -main HelloWorld -cpp bin/cpp
haxe -main HelloWorld -cs bin/cs
haxe -main HelloWorld -java bin/java
haxe -main HelloWorld -python bin/py/app.py

Using Libraries in Haxe

Haxelib is the library manager that comes with Haxe. You can use it to download user-submitted libraries, or upload your own. Here’s an example on how to install the moon-core library:

haxelib install moon-core

On HaxeDevelop, you need to add the library reference to your project settings. To do so, at the menu, click on Project > Properties... > Compiler Options, and add moon-core to the libraries.

Then, to use the Range class in the HelloWorld example:

import moon.core.Range;

class HelloWorld
{
    public static function main():Void
    {
        for (i in Range.from(3, 7, 2)) {
            trace('$i: Hello World!');
        }
    }
}

On HaxeDevelop, you can simply click the play button, and it’ll run. To manually build it, you need to add the -lib moon-core to your build arguments like so:

haxe -lib moon-core -main HelloWorld -js app.js
node app.js

Haxelib documentation is available online, and you can browse the libraries at http://lib.haxe.org.

Simplifying Command-Line Arguments

If you’re building from the command-line, you may notice that the command-line arguments can get quite long. Lets move your source files into a sub-folder called src. Now you need to indicate to haxe where your class paths are using the -cp switch:

haxe -lib moon-core -cp src -main HelloWorld -js app.js

Sometimes, you may even want to build to multiple targets:

haxe -lib moon-core -cp src -main HelloWorld -js app.js
haxe -lib moon-core -cp src -main HelloWorld -neko app.n
haxe -lib moon-core -cp src -main HelloWorld -python app.py

You can simplify those by creating a whatever.hxml file containing one command-line argument on each line. And then build with haxe whatever.hxml.

Here’s an example. Create a build.hxml:

-lib moon-core
-cp src
-main HelloWorld
-js app.js

# separator indicating another build
--next

-lib moon-core
-cp src
-main HelloWorld
-neko app.n

--next

-lib moon-core
-cp src
-main HelloWorld
-neko app.py

And then run haxe build.hxml to build for both targets. If you notice, there’s still some repetition, and we can simplify it further by using --each.

-lib moon-core
-cp src
-main HelloWorld

# everything above is the common stuff
--each
-js app.js
--next
-neko app.n
--next
-python app.py

Tip: What if your build config gets more complicated?
I wrote moon-run to allow you to store multiple build configs as well as run configs, in a nested JSON structure. So you can build with a command like hx build webserver chatserver jsclient where webserver, chatserver and jsclient are configs stored in haxe.json. Then run with hx run something.

Haxe Resources

It's dangerous to go alone! Take this.

References and Frameworks

Online Communities