We are very excited about our newest release. If you're first hearing about it, Haxe is a language that compiles to many targets; JavaScript, C++, C#, Java, Python, Lua, PHP, Flash, HashLink and Neko. Code once written in Haxe can be compiled to any target Haxe supports. Meanwhile, Haxe has a fine grained blend between object oriented and functional programming and because it's strictly typed it helps catch bugs before it even runs and makes you work more efficiently by enabling great tooling support. It even allows compile-time syntax-transformation with so called macros. If you never used Haxe before, download it today or you can even try it directly in your browser.
We made a big leap in this release and now we’d love to share some of the new features with you!
1. Three new targets
It is not rare for a new Haxe release to add a new target, but this is the first release to add three new targets at once. These are:
HashLink
We introduced the HashLink target in 3.4 RC1, which is already explained in the previous series of blogposts. HashLink is a Haxe target that can be run either via HashLink Virtual Machine/JIT or be converted to C code. It has very fast compile times, comparable to the Neko target and a lot of raw speed. HashLink is created and maintained by Nicolas Cannasse, original creator of the Haxe compiler and designer of the Haxe language. We hope you will try HashLink and share your thoughts. For Haxe 4.0 we are considering to replace Neko with HashLink for macro execution.
Lua
The Lua target was first introduced in the WWX2016 talk “Shooting for the Moon: Haxe lands on Lua”. You might ask why Haxe and Lua? The answer is, why not? Haxe is a familiar programming language, since it is ECMAScript-based. Haxe is used often in game development and can now be used for scripting in games (e.g. WoW, Factori), game engines (CryEngine, Defold, Moai, Love) but also for editors (like Neovim, VIM). All from your own shared codebase, which is a nice community match. Haxe and Lua communities are similar: creative, independent, mindful. We want to thank Justin Donaldson for all his work on Lua target.
So which Lua version do we support, you ask? Lua 5.1, Lua 5.2, LuaJit 2.0, LuaJit 2.1 and with partial support backwards compatibility flags Lua 5.3.
PHP7
We introduced the PHP7 target in Haxe 3.4 RC2. It can be enabled with -D php7
. PHP7, as advertised is an important change for PHP since the release of PHP5 in 2004, bringing performance improvements, reduced memory consumption, and new language features. The Haxe PHP7 target gives you the opportunity to use PHP7, but with your favorite language.
2. Even better IDE support
We collaborated with the FlashDevelop team to create our own custom distribution for Haxe called “HaxeDevelop”. As with FlashDevelop, this is a great, but now even more light-weight option for Windows users.
Additionally, there is now also a Haxe extension for Visual Studio Code (aka VSCode). This was done by implementing Microsoft’s Language Server Protocol for Haxe. The Language Server Protocol is used between a client (the Haxe extension) and a “language smartness provider” (the server) to integrate features like completion, goto definition and alike into a code editor, which means the Haxe Language Server could in the future be used to add Haxe support to IDEs other than just VSCode. Note that a lot of the more advanced features of the VSCode extension are made possible by major improvements to Haxe’s compiler services. This includes features such as document / workspace symbols or code lens.
Furthermore, we made a number of improvements to our API documentation. This is nice for documentation hints which most code editors support. We also put some effort into providing API docs in the js.html package for our Haxe/JavaScript users.
3. Improved C++ code output
While Haxe tries to create the most optimal code for each target, reading through the output code can be hard sometimes. Our Haxe C++ target maintainer Hugh did a great job in making the output noticeably cleaner. It is now much easier to make the connection between original Haxe and generated C++ code, since the latter is annotated with the corresponding Haxe line numbers via HXLINE()
:
To achieve this, the C++ generator was largely rewritten using a much cleaner architecture than before.
4. Static code analysis
As you might know Haxe is an optimizing compiler. In Haxe 3.2 we introduced the static analyzer, which was hidden under a compiler flag (-D analyzer
). Our compiler developer Simon briefly explained the analyzer on WWX2016. The static analyzer takes care of const propagation, copy propagation, local dead code elimination, fusion and purity inference.
In Haxe 3.4 the static analyzer has settled and runs by default, so the -D analyzer
flag has been removed. To have extra optimizations the -D analyzer-optimize
can be used. This builds a control flow graph and then the optimizer (if enabled) does some optimizations on that, like folding expressions, removing dead code, etc. This optimization flag is not enabled by default because of too many vars being eliminated for hxcpp, in Haxe 4.0 it will be enabled by default. Try it out yourself and share your results, we absolutely love the optimizations.
5. New language additions: Any, import.hx, @:structInit
Any
Any
is a new type that is available in the standard library. It is a more type-safe alternative to Dynamic
, which allows arbitrary field access:
var foo:Dynamic = 0.1; foo.methodDoesNotExist(); // runtime error
With Any
, this is not possible - to be able do anything with its value, an explicit cast is necessary, hopefully reminding the developer to do a type check first:
var foo:Any = 0.1; foo.methodDoesNotExist(); // Any has no field methodDoesNotExist()
To learn more about Any
, read the original haxe-evolution proposal about it.
import.hx
import.hx
is a special Haxe file: it can only contain imports and usings, but no type declarations. The imports and usings in it are made available to all Haxe modules in the same directory or in subdirectories. For instance, you could make the StringTools
extension methods available in your entire project by placing an import.hx
with this content in the project’s root directory:
using StringTools;
We have already written about import.hx
in more detail in a previous blog post.
@:structInit
@:structInit
is a new metadata that can be used to annotate classes. It then allows that class to be instantiated using structure literal syntax, instead of just the traditional new
-syntax. Here's an example (try.haxe):
class Test { static function main() { function printPoint(p:Point) trace(p.x, p.y); printPoint(new Point(5, 2)); // 5,2 printPoint({ x: 5, y: 2 }); // 5,2 } } @:structInit class Point { public var x:Int; public var y:Int; public function new(x:Int, y:Int) { this.x = x; this.y = y; } }
More of the new features can be found in the changelogs of Haxe 3.4 and its release candidates.
Looking back
It is really great to see what Haxe has become, a powerful, versatile eco-system which can be used for many different applications. Special thanks to the Haxe team and everyone who contributed to this release, which are located all over the world. We have worked with open source for a long time now, Haxe has become really solid because of these people. But also because of the feedback and contributions from the community. Many thanks!
Moving forward: Haxe 4.0
Once the major issues and regressions have been sorted out, our next release will be Haxe 4.0, which we’re all very excited about. We are making plans to define what Haxe 4.0 will look like and which elements/changes/features it should have. We will make some internal changes, tooling improvements and probably many more interesting new features which we will share when we have a solid plan. What we can tell is it will have short lambdas (arrow functions), as requested by the community.
Make sure you download the latest release and try it on your projects, let us know what you think of this new release.