One language.
Every platform.
Continued.
A strict superset of Haxe 4.3, built on hxc, a faithful Haxe compiler written in Haxe. Every valid Haxe program compiles unchanged, and keeping it that way is the project's first commitment. On that foundation: the language features the community has asked for, a modern toolchain, and a compiler built so that adding platforms is cheap.
01Compatibility
Your code already works here
hx+ isn't a fork. It contains Haxe 4.3, checked against the reference compiler with Haxe's own test suites. Our compatibility rules:
A stable std, guaranteed
For code on the 4.3 edition, existing standard-library APIs are not changed and not removed. New designs are built alongside, in new namespaces. Deprecation is a warning, never a break. Newer editions can change defaults or drop deprecated APIs, but only for modules that opt in.
Contextual keywords only
No identifier that is legal today stops being legal. New syntax arrives without reserving a single word your code might already use.
Editions for the long term
Long-term evolution happens through per-module editions, in the pattern Rust proved. Code written against the 4.3 edition keeps compiling, in the same build as new code.
02Architecture
Why a new compiler
What makes Haxe worth using is how far one codebase reaches: web, native, mobile and server. Keeping that going takes a compiler built for it.
Written in Haxe
The compiler is implemented in the language its community writes every day. If you write Haxe, you can read, debug, and improve your own compiler. Rust, Go, C# and Kotlin all made the same move.
Checked against the real compiler
hxc is tested against the reference Haxe 4.3 compiler with Haxe's own test suites, and the output is compared byte for byte. A target counts as conformant when it passes the same suite.
Cheaper targets
Every hxc generator is ordinary Haxe code. Next, every target moves behind one interface: a package of Haxe source compiled into hxc, with what it can do, its own filter passes, its generator and its build step. The built-in targets will use the same interface, so the people who need a platform can maintain it themselves, and the conformance suite tells them when it's right.
More targets, less risk
Haxe runs on other people's runtimes, so when a platform dies, code that can only run there dies with it. Haxe outlived Flash because the same code could move to other targets. Every target is one more place to land.
03The compiler
hxc: the compiler underneath
Underneath hx+ sits hxc, a faithful Haxe 4.3 compiler, written in Haxe and checked against the reference compiler with Haxe's own test suites.
Most serious languages end up compiling themselves
- Cfrom assemblyself-hosted since the 1970s
- Rustfrom OCamlrustc, self-compiling since 2011
- Gofrom Centirely Go as of 1.5
- C#from C++Roslyn, C# in C#
- Kotlinfrom Javacompiler written in Kotlin
- Haxefrom OCamlhxc
Rust's first compiler was written in OCaml and was replaced once Rust could compile itself. TypeScript went the other way: Microsoft moved its compiler to Go for speed, because TypeScript compiles to JavaScript. Haxe compiles to native code, so hxc is self-hosted and still a native binary.
- Self-hosted. The compiler is written in Haxe, so if you write Haxe you can read, debug and fix your own compiler in the editor you already use.
- Checked, not trusted. Haxe's unit suite at zero failures, with output and compiler messages compared byte for byte against the reference compiler.
- Native. Built with hxcpp into a native binary, so being written in Haxe doesn't cost speed.
- Built to be extended. Every generator is ordinary Haxe code, and targets are moving behind one interface, so the typer and optimizer will ask a target what it can do instead of which target it is.
# install it from haxelib
$ haxelib install hxc
# then use it wherever you would run haxe
$ haxelib run hxc build.hxml
Same command line, same hxml.
04In the browser
The compiler, in a browser tab
Because hxc is ordinary Haxe, it compiles to WebAssembly like any other Haxe program. The result runs entirely client-side: write Haxe, compile it, run it, and share it by link, with no build server and nothing to install. OpenFL projects compile and render the same way.
That's haxe.run, the playground every hx+ proposal will ship with, so the community can argue about a feature by running it.
05The language
What hx+ adds
First, the features Haxe developers have requested for years. Then a public RFC pipeline, where every proposal ships with a live playground so the community debates by trying, not imagining.
// Real constants, evaluated at compile time
const TAU = 2 * Math.PI;
// try / catch / finally, at last
function save(state:GameState) {
var file = File.write(SAVE_PATH);
try {
file.writeString(state.serialize());
} catch (e:IoError) {
Log.warn('Save failed: ${e.message}');
} finally {
file.close();
}
}
try / catch / finally
Requested for over a decade. Implemented directly in the compiler, lowered per target
to native finally where the platform has one.
const: real constants
Initializers evaluated at compile time and spliced as literals, powered by the
compiler's own eval engine. A guarantee final never gave you.
Records & structural equality
Declarations with derived equality, hashing, and copying, generated at compile time. The end of hand-rolled deep-equals in every project.
Modern networking
A clean-sheet, dual-stack networking package: IPv6 at last, TLS and WebSockets as part of it, and an HTTP client and server. The legacy API stays working.
Coroutines, absorbed
Structured async on the Haxe 4.3 base, on our own schedule: modern ergonomics and the full target matrix, without choosing between them.
Compile-time toolkit
nameof, static assert, and compile-time file embedding,
powered by the eval engine the compiler already carries.
Proposed for the RFC pipeline
Nearly every item here traces to a longstanding request in the Haxe issue tracker, some open for a decade: this is largely the community's own wishlist, aged in public. The deeper type-system work, shown dashed, arrives through editions where it must.
06Platforms
Targets
Tier 1 targets are maintained by the core team and release-gated on full conformance. Tier 2 targets are community-maintained through the Target SDK, measured by the same public suite. A community target that keeps passing can move up a tier. The targets marked considering are the kind the SDK is meant to let communities own.
Tier 1core maintained
- JavaScript
- C++ hxcpp
- eval macros
- cppia
- JVM bytecode
Comingin order of need
- Rust in progress
- C# modern .NET
- Java modern JVM
- WebAssembly WasmGC
- PHP
- Python
- Lua
ConsideringSDK-shaped
- Kotlin
- TypeScript emission
- Go
- Swift
Tier 2: any community target that sustains conformance through the SDK.
Tiers can change
A Tier 2 target whose community keeps it conformant can move up. HashLink bytecode and Flash are Tier 2: welcome, but not promised.
Retiring Neko
Neko is a custom runtime the ecosystem maintains by hand, no products ship on it, and eval, cppia and HashLink cover what it does. We'll retire a target nobody depends on, never one people rely on.
How targets will plug in
The pipeline stays fixed. The target fills its slots.
We're moving hxc's targets behind one interface, starting with C++. Once they're there, the typer, filters and optimizer stop testing which target is selected and read what it declared it can do instead. Everything target-specific arrives through three kinds of contribution, and the built-in targets use exactly the same interface as anyone else's.
- configuretarget
- parse & typecore
- filters+ target passes
- analyzercore
- filters+ target passes
- generatetarget
- buildtarget
Capabilities
Plain data, resolved once before typing: overloads, null padding, capture policy, analyzer and optimizer rules. Read in the hot paths as fields, so a plugged-in target compiles as fast as a built-in one.
Passes
Filters the target places at named slots in the compiler's pipeline, before or after a named pass. The order itself never changes.
Stages
Whole-program calls: configure, generate, and build, where the target chooses its own runtime and toolchain.
A second C++ backend, beside the first
C++ moves behind the interface first, so a second C++ backend can grow next to the
original instead of replacing it in place. It starts byte-identical, diverges on purpose with
the original as its live reference, and pairs with a runtime of its own, which makes changes
that need both sides possible, such as precise GC roots. It reports itself as C++, so
#if cpp code in Lime, OpenFL and native extensions compiles unchanged.
A different kind of target
Shaders, in the same language and the same types
Graphics code is the daily work of much of this ecosystem, written today in a separate language, with separate types, checked by nothing until it fails at runtime. A shader target compiles a restricted subset of hx+ to SPIR-V, with WGSL, GLSL, and HLSL alongside.
What makes it useful is that both sides use the same types, so uniforms, vertex attributes and buffer layouts are checked by the compiler instead of turning up as a black screen.
// one declaration, both sides of the boundary
@:uniform var time:Float;
@:uniform var tint:Vec4;
@:shader(fragment)
function main(uv:Vec2):Vec4 {
var wave = sin(uv.x * 12 + time) * 0.5;
return tint * (0.5 + wave);
}
One language, every engine
Most Haxe code that reaches consumers ships inside a game engine. The community proved the demand and the technique; these deserve a toolchain that treats them as first-class.
Unreal Engine
Building on the hxcpp path unreal.hx proved in commercial production: Haxe classes as UCLASS citizens, Blueprint interop, full engine API access.
Godot
The GDExtension route via hxcpp, as HxGodot demonstrates, with the Rust target as a second integration avenue as it matures.
Unity
Riding the new C# target: Haxe compiling to idiomatic, modern C# that Unity consumes natively.
07Developer experience
The toolchain is the language
What pushes teams away from Haxe usually isn't syntax. It's tooling.
Real dependency management
Per-project, lockfile-based, reproducible builds with content hashes. Vendoring for studio CI. A registry with target and edition compatibility metadata, and a bridge so existing haxelib packages keep working from day one.
Diagnostics as a product
Error messages with explanations, suggestions, and documented error codes. The same structured output that helps you repair code is what makes AI-assisted development precise.
The live loop
An official REPL, powered by the compiler's own eval engine. Watch-mode builds and hot-reloadable scripting. The tight development loop as a toolchain feature, not an accident.
Editions for the long run
Strict null safety by default, delivered as an edition your project adopts module by module. The language moves; nobody's code is left behind.
hxia: Haxe Intermediate Assembly
A scripting layer for shipped applications: one artifact that loads into the native build and the web build of the same program. The runtime is Haxe compiled into the host, so script values are host values, with no marshalling boundary and no second heap. Untrusted content runs on a metered, capability-gated tier; trusted content takes the fastest engine each host already has. Modding, plugins, and live content, portably.
08The plan
Roadmap
Where things stand, honestly. This work did not begin recently: the earliest prototypes date to the Haxe 3 era. Today hxc 0.6.6 is on haxelib. It compiles real projects and passes an 18-gate parity battery against the reference 4.3 compiler: Haxe's unit suite with JavaScript and C++ output byte-identical across the dead-code and analyzer settings, Haxe's sys and threads suites under its interpreter, every hxcpp test suite, the warm compilation server, and a rebuild of its own source. It builds Lime and OpenFL applications, and compiled to WebAssembly it runs in the browser, which is what the haxe.run playground is built on. hxia runs: one mod, compiled once, loads into the C++ and JavaScript builds of the same game and plays identically. hxc also generates JVM bytecode, and the experimental Rust backend runs. The hx+ language features and the modern networking package are designed and specified but not yet shipped. They land in the order below, and nothing here should be read as claiming otherwise.
Phases are ordered by what depends on what, and every phase ships something usable on its own.
-
Battery green
Phase 1: Parity
Haxe's own suites at parity with the reference 4.3 compiler: eval and macros, then JavaScript, then C++ and cppia. The final gate: Lime and OpenFL build and run, unmodified.
-
Underway
Phase 2: In the browser
The compiler running client-side at haxe.run: write, compile, run, share. Community spaces go public alongside the playground.
-
Next
Phase 3: hx+ 1.0
Editions,
finally,const, the transpile-to-Haxe mode, and the Target SDK on the target interface, which C++ moves behind first. The Rust backend ships as a preview. The first RFCs open with the release. -
Planned
Phase 4: The platform
Modern networking (IPv6, TLS, HTTP, WebSockets), the package manager with its haxelib bridge, and the official REPL. Pipeline features begin landing on a steady cadence.
-
Planned
Phase 5: Widening the matrix
Rust to full conformance. Clean-sheet C# and Java. WebAssembly on WasmGC. PHP, Python, and Lua carried forward as their conformance suites go green.
-
Planned
Phase 6: Engines
First-class integration for Unreal Engine, Godot, and Unity: gameplay code written once, moving between engines the way Haxe already moves between platforms.
09The document
Read the whitepaper
The full case: why we built it, the compiler, the compatibility rules, licensing and the plan.
An invitation
Try it
Bring your existing code; it should simply compile. When it doesn't, that's a bug against a promise, and we want the report.
Argue with it
The first RFCs open with the first release. If a feature is wrong, say so with a playground link showing why. That is how this language will be governed.
Build a target
If there's a platform you need and the ecosystem lacks, the Target SDK and its conformance suite are there for that. You don't need anyone's permission.
Haxe's original idea, one language for every platform, is worth keeping, and we built the tools to keep it.
10Questions
FAQ
Is this a fork of Haxe?
No. hx+ contains Haxe 4.3. Your code compiles unchanged, and keeping it that way is the project's first commitment. hxc is a faithful Haxe 4.3 compiler, and hx+ is a strict superset on top of it.
Why not just contribute to the official compiler?
The problem isn't a shortage of hands; it's structural. An OCaml codebase limits contributors to people who know both worlds well. hxc changes the structure instead. Nothing is held back: everything we build is open, and MPL code can go into GPL projects, so upstream can take any of it.
What stops hx+ from meeting the same fate it responds to?
Incentives and design. The people maintaining this toolchain ship the ecosystem's most used frameworks on it, so keeping it healthy isn't optional for us. It also doesn't depend on a small group's attention: the compiler is written in the language its users already know, correctness is checked by test suites instead of living in a few people's heads, and targets are owned by the communities that need them.
Will my existing code or libraries break?
No. That is the one promise this entire project is architected around. Existing std APIs are stable and stay in place, new syntax is contextual-keyword only, divergence is opt-in, and the narrow exceptions (security fixes, platform withdrawals) are published in advance.
Will my editor and build setup keep working?
Yes. The compiler presents the same CLI and hxml interface, works with existing haxelib workflows, and speaks the same display and diagnostics protocol that powers today's IDE plugins.
How do I try hxc?
Install it from haxelib with haxelib install hxc, then run
haxelib run hxc build.hxml wherever you would run haxe. The package includes the
compiler for Windows x64; on other platforms, build it from source (see
GitHub). Or try it with nothing installed at haxe.run.
How would I add a target?
Write it as a package of Haxe source: the capabilities it declares, any filter passes it needs, a generator and a build step. Put it on the class path and rebuild hxc with hxc. The built-in targets are written the same way, and you test yours with the same conformance gate that brought hxc to parity.
Why base on Haxe 4.3 rather than tracking Haxe 5?
Haxe 4.3 is the last release line with the full target matrix, and the target matrix is the point. The language evolves independently on that base, with its own release cadence, and absorbs individual improvements from any source when they serve the goal.
Who controls hx+?
An open RFC process, in public, with working playground demos attached to every proposal. The compatibility guarantees are standing commitments, not preferences.
What license?
Mozilla Public License 2.0 wherever the code is ours to license. File-level copyleft keeps compiler improvements open; applications and engines that embed the toolchain take on no obligations for their own code.