Skip to content

Releases: andrewglind/hatchet

v0.3.3 — VC6-safe conversions at call sites (2026-09-22)

Choose a tag to compare

@github-actions github-actions released this 22 Sep 01:53
bed2bad

Release Notes

Conversion hazards at call sites, routed around in the generator rather than worked around in Haxe.

Narrowing conversions are explicit casts

A value stored into a smaller scalar than it has now says so — (uint16_t)(base + 1),
(float)(a * 0.5) — instead of relying on the implicit conversion. The conversion happens either
way (Haxe arithmetic on Int is int arithmetic and on Float is double arithmetic), so nothing
changes at runtime; it silences MSVC C4244, and it is the one lever the generator has against a VC6
/O2 miscompile in which a uint16_t narrowed from a loop-derived int takes the first
iteration's value on every iteration — correct element count, repeated values. Whether the cast
suppresses that is unconfirmed: it needs a real VC6 Release build to tell.

Applied wherever the target type is known — a call argument, a local or field initialiser or
assignment, a return, a container element, a struct-literal field — and only for genuine
narrowings: a smaller destination of the same kind, or a floating value into an integer. Literals
are written in the target type already, so they are not cast. C++ integral promotion is
accounted for: n + 1 where n is a cpp.UInt16 is an int expression, so storing it back into a
uint16_t is a narrowing and is cast.

Pushed values are bound to an element-typed local

std::vector<T>::push_back takes const T&, so an argument that is not already a T lvalue
materialises a temporary at the call site and binds the reference to that. push, insert and
unshift now bind such an argument to a named local of the element type first:

uint16_t _elem2 = (uint16_t)(base + 1);
indices.push_back(_elem2);

Left inline: a literal, a plain local or this field already of the element type, a
struct/array/map literal (already hoisted into an element-typed temp), and a pointer element type
(nothing converts, and hoisting a new would disturb the ownership lowering). Alias typedefs are
looked through, so a local declared Tileset still pushes straight into an Array<Tile> with no
redundant copy.

This began as a suspected fix for the VC6 miscompile above; that diagnosis was wrong — the fault
survives it, and the narrowing is the isolated trigger. It is kept as hardening: binding the
reference to a named variable is the shape hand-written C++ would have, at no runtime cost.

Floating literals and narrowings in cpp.Float32 contexts

Every Haxe floating literal was emitted as a C++ double literal, whatever it landed in, so a
cpp.Float32 (C++ float) target narrowed at the conversion — which MSVC reports as C4305 on each
line. A literal in a float context is now emitted with the f suffix, in every position where
the target type is known: an argument to a cpp.Float32 parameter, a local or field initialiser or
assignment, a return, an Array<cpp.Float32> element, and a struct-literal field.

camera->SetPerspective(70.0f, 0.1f, 100.0f);   // was 70.0, 0.1, 100.0 — C4305

An expression (rather than a literal) narrowing into a float context is the C4244 counterpart,
covered by the explicit casts above — this->fx = (float)(someFloatValue);.

Arithmetic keeps Haxe's semantics: Float arithmetic is double arithmetic whatever it is assigned
to, so an operand keeps its double literal and return a * 0.5; still computes in double,
narrowing once at the end (return (float)(a * 0.5);). Suffixing the operand would silently make
the computation single-precision — a behaviour change rather than a cosmetic one. Genuine Float /
double contexts are untouched.

Install hatchet 0.3.3

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.3.3/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.3.3/hatchet-installer.ps1 | iex"

Download hatchet 0.3.3

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

v0.3.2 — Member types resolve where they are declared (2026-09-17)

Choose a tag to compare

@github-actions github-actions released this 17 Sep 01:50
7fa88c8

Release Notes

A correctness release fixing two lowering bugs that share one root cause. When a module imports
two types with the same leaf name — typically a @proxy handle and an unrelated native value
struct, such as a ui.Vertex proxy alongside a gfx.Vertex struct — Hatchet could pick the wrong
one while typing the members of the other module's types.

Fixes

  • A member's type resolves in the module that declares it. The field types of a typedef
    struct or class, a property's field type, and a method's return type were resolved in the scope
    of the module using them rather than the module declaring them.

  • Types recovered from a C++ spelling match the qualified name. A vector's element type or a
    map's value type is recovered from its emitted spelling (std::vector<gfx::Vertex>). That lookup
    used only the leaf name (Vertex), so it too could land on a same-named type in another
    namespace; it now matches namespace + name exactly, falling back to the leaf name only when no
    qualified match exists.

Existing code whose type names don't collide generates byte-identical output.

Install hatchet 0.3.2

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.3.2/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.3.2/hatchet-installer.ps1 | iex"

Download hatchet 0.3.2

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

v0.3.1 — Static fields (2026-07-20)

Choose a tag to compare

@github-actions github-actions released this 20 Jul 03:31
6a80a01

Release Notes

Class static fields are now lowered as genuine class-scoped statics instead of being
mistakenly emitted as per-instance members. A scalar / String static with a literal
initializer (or none) is a plain class static — static T NAME; in the header, with an out-of-line
T Class::NAME = <literal>; definition — and reads as Class::NAME.

Otherwise the field is lowered as a Meyers singleton: a static T& NAME() accessor whose
function-local static holds the value and is initialised on the first call, read as
Class::NAME(). This is the case for any struct / container / reference-typed static (C++98
cannot constant-initialise one as a class-scope data member) and for a scalar with a non-literal
initializer
(a call, new, arithmetic, …) — deferring it to first use rather than running it at
an unspecified point in the C++ static-initialisation order (the "static init order fiasco"). A
function-local static is initialised exactly once by the language, so no guard flag is needed;
when the initializer builds a temporary (e.g. an array), that setup is folded into a one-off
_init_* helper so it too runs once. A final field returns const T& (it is immutable); a var
stays writable through the returned reference. Reads resolve correctly whether written bare inside
the class or qualified (Class.NAME) from elsewhere.

Because the accessor-vs-data-member choice is driven by the field's type, a consuming
extern / @proxy binding — which carries no initializer — reads the field the same way the
producing class emits it: a struct-typed static bound through an extern is called
(native::Class::NAME()), matching the native Meyers accessor, while a scalar static final stays
a plain data-member read.

Install hatchet 0.3.1

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.3.1/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.3.1/hatchet-installer.ps1 | iex"

Download hatchet 0.3.1

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

v0.3.0 — `@sink` in more positions (2026-07-13)

Choose a tag to compare

@github-actions github-actions released this 13 Jul 03:12

Release Notes

@sink means what it always has — ownership leaves here; this scope does not free the value
but until now it could only be written on a parameter. This release lets you write it where
the hand-off actually happens: on a call argument and on a local declaration.

Metadata is allowed on any expression

Haxe permits @meta expr on any expression, but Hatchet's expression parser had no arm for a
leading metadata token. Expression-position metadata now parses and is transparent to
type and value — it changes nothing about how the wrapped expression lowers. Metadata other than
@sink is carried but inert, matching hxcpp, which ignores expression-position metadata at the
C++ target.

@sink on a call argument and a local declaration

The same transfer semantics as a @sink parameter, now available at two more sites:

  • A @sink new X(...) call argument is emitted inline — not hoisted into a scope-owned
    local that the caller deletes.
  • A @sink local call argument (an already-owned local) has its scope-close delete
    dropped, transferring the object to the callee.
  • A @sink var x = new X(...) local declaration suppresses the scope-close delete of x
    entirely — the inverse of @delete var — for when ownership is handed off with no single call
    to attach the marker to.

@sink is an assertion that ownership leaves the current scope, so it applies even
when the destination is opaque to Hatchet (an @:native class, or a hand-off the analysis cannot
follow) — it overrides the escape analysis. If nothing actually takes ownership the result is a
leak, never a double-free. @sink on a value local or argument (nothing to hand off) is a
no-op and warns.

Install hatchet 0.3.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.3.0/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.3.0/hatchet-installer.ps1 | iex"

Download hatchet 0.3.0

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

v0.2.9 — Type-resolution & arithmetic fixes (2026-07-11)

Choose a tag to compare

@github-actions github-actions released this 11 Jul 04:37
02d1717

Release Notes

A correctness release fixing three lowering bugs. A Module.func() call that targets a
module-level function no longer emits a bogus class qualifier; a typedef alias is now fully
transparent — it takes on the shape of whatever it names, everywhere; and mixed Int/Float
arithmetic infers Float, so a var bound to it no longer truncates. The fixed-C-array
"fill" detection added during the raw-pointer work — undocumented since v0.2.8 — is removed.

Fixes

  • Module.func() for a module-level function drops the class qualifier. Haxe lets you
    call a module-level function through the module name — Palette.mix(a, b) where mix is
    declared at the top of Palette.hx, not a member of the primary class Palette. Such a
    function lowers to a namespace free function, so Hatchet no longer emits the non-existent
    Palette::mix(...); it emits mix(...) (namespace-qualified as needed, e.g. util::mix).
    A genuine static member (Registry.slot(...)) still uses scope resolution,
    Registry::slot(...).

  • A typedef alias is fully transparent. A Haxe typedef X = Y is the same type as Y
    everywhere, but Hatchet made shape decisions (pointer-vs-value, reference-vs-container,
    by-value-vs-const&, member dispatch) from the alias name rather than its target — so an
    alias only behaved correctly for a couple of shapes. Aliases are now resolved through
    before every such decision, while the alias name is kept in the emitted spelling. Fixes,
    across every alias shape:

    • typedef Color = cpp.UInt32 (primitive) — passed by value (optional gets a default),
      not const Color& or a Color* pointer.
    • typedef Panel = Widget (a class) — a Panel* with -> dispatch, not a sliced
      by-value Panel; methods/fields resolve through the alias (panel.tag()w->tag()).
    • typedef Ints = Array<Int> (container) — passed const Ints& (Haxe's shared-reference
      semantics), not a silent by-value copy.
    • typedef Vertex = Pt (a { … } struct) — const Vertex&, with working field access
      (v.x).
    • typedef Name = String — keeps the const Name& optimization; an optional ?n:Name
      defaults to "".
    • Null<Ptr> where typedef Ptr = cpp.RawPointer<T> — a single pointer, no longer Ptr*
      (a double pointer). A custom iterator reached through an alias now iterates transparently.
  • Mixed Int/Float arithmetic infers Float. An arithmetic operator's result type was
    taken from the left operand alone, so intField / floatField (and +, -, *, %) was
    inferred Int. A var r = intField / floatField was then declared int and truncated the
    double the expression actually computes. Arithmetic now promotes to Float when either
    operand is a Float, matching C++'s (and Haxe's) usual arithmetic conversions. Int-only
    arithmetic, shifts, and the existing Int / Int → Float double-division cast are unchanged.

Removed: fixed-C-array "fill" detection

The raw-pointer work briefly special-cased cpp.Pointer.ofArray(...).raw written into fixed
C-array storage, warning that a bare .raw cannot fill a native T[N]. That handling was
de-documented in v0.2.8 and is now removed entirely: cpp.Pointer.ofArray(a).raw is simply
the address of the first element (&(a)[0]), with no position-dependent diagnostics. The
general .raw intrinsics (cpp.Pointer.fromStar(x).raw, cpp.Pointer.ofArray(a).raw) are
unchanged.

Install hatchet 0.2.9

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.2.9/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.2.9/hatchet-installer.ps1 | iex"

Download hatchet 0.2.9

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

v0.2.8 — C-style arrays & raw-pointer interop (2026-07-02)

Choose a tag to compare

@github-actions github-actions released this 02 Jul 03:51

Release Notes

A native-interop release: hxcpp's raw-pointer types now lower and the .raw pointer
intrinsics are recognised. Dynamic / Any become the faithful spelling for an opaque
void* and {} for that role is deprecated. A latent cast-ascription miscompile is fixed.
Internally the parser and code generator were split into focused modules with a reorganised
test suite. The @:decl / @:abi deprecation warnings added in v0.2.7 are removed (those
metadata are now silently parsed-and-ignored).

hxcpp raw-pointer interop types lower to C pointers

The hxcpp pointer interop family now maps to native C++ pointers, joining cpp.Pointer<T>:

  • cpp.RawPointer<T> and cpp.Star<T>T*
  • cpp.ConstStar<T>const T*
  • cpp.Voidvoid, so cpp.RawPointer<cpp.Void> / cpp.Star<cpp.Void> give void*

These resolve at every use site (field, parameter, local, return) and index as C pointers
(p[i]), so a Haxe binding to a native struct with a T* / const T* / void* member
transpiles faithfully.

Dynamic / Any are the opaque void*; {} for that role is deprecated

Dynamic and Any in an emitted position now erase to void* — an opaque pointer that
carries anything (Any is abstract Any(Dynamic), so both are Dynamic-backed at runtime).
Dynamic also keeps its existing @:overload-marker role.

Because Dynamic (opaque value) and cpp.RawPointer<cpp.Void> (opaque pointer) are now the
faithful spellings, using the empty structure {} as a void* type is deprecated. It
still lowers to void* so existing sources keep working, but now emits a non-fatal
deprecation warning naming the replacement; the void* lowering will be removed in a future
release. (In hxcpp {} is a structure object, not a raw pointer — this was a Hatchet-ism.)

.raw pointer intrinsics

The cpp.Pointer .raw accessors used to satisfy hxcpp are recognised and lowered:

  • cpp.Pointer.fromStar(x).raw — the developer's intent to view x as a raw pointer:
    emits x when x is already a pointer, else takes its address &(x). This is the
    supported way to accept a ?data:Dynamic argument and store it as void*
    (this.data = cpp.Pointer.fromStar(data).raw;).
  • cpp.Pointer.ofArray(a).raw — a pointer to the first element, &(a)[0].

Reference semantics: mutable-reference getters, const-ref parameter writes

  • Write-restricted getters return T&. A generated getter for a container
    (std::vector / std::map) or value-struct field now returns a mutable reference (T&)
    rather than a const T copy, so Haxe's reference-type mutation through a getter works:
    obj.items[k] = v; and in-place struct mutation compile and take effect.
  • Assigning through a const& value-struct parameter is a hard error. A value-struct
    parameter lowers to const T&; writing through it is now reported up front instead of
    emitting non-compiling C++.

Fixes

  • Array-literal cast-ascription element type. ([...] : Array<cpp.UInt8>) built a
    std::vector<int> and then assigned it to a std::vector<uint8_t> — a type clash that
    would not compile. A container ascription now pins the element type through the literal, so
    the vector is built as std::vector<uint8_t> directly.

@:decl / @:abi deprecation warnings removed

v0.2.7 renamed the export behaviours to @libexport / @cexport and made @:decl / @:abi
emit a deprecation warning. Those warnings are now removed: @:decl / @:abi are Haxe
inbound-only metadata and are purely parsed-and-ignored, with no diagnostic.

Internal

  • The monolithic parser.rs and codegen/mod.rs were split into focused submodules
    (parser/{decls,expr,stmt,types}, codegen/{header,amalgam}, codegen/source/{control,loops}),
    and the single tests/source_codegen.rs was reorganised into topic-scoped files
    (codegen_core, codegen_control, codegen_intrinsics, codegen_ownership, codegen_proxy,
    codegen_rawptr, codegen_types) sharing a tests/common helper module. No behavioural change.

Install hatchet 0.2.8

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.2.8/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.2.8/hatchet-installer.ps1 | iex"

Download hatchet 0.2.8

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

v0.2.7 — Export metadata `@libexport` / `@cexport` (2026-06-26)

Choose a tag to compare

@github-actions github-actions released this 25 Jun 23:02
ad1ce08

Release Notes

A metadata-correctness release with a breaking rename (deprecation path is provided).

Haxe-faithful @:decl / @:abi; export behaviours move to @libexport / @cexport

Hatchet repurposed @:decl and @:abi for outbound (producing) C++:
@:decl decorated a class for shared-library export (<PREFIX>_CLASS), and @:abi
turned a free function into a global extern "C" export. The Haxe compiler
source shows both metadata are inbound-only and unrelated to that, So the two
Hatchet behaviours have been renamed to dedicated custom metadata,
and @:decl / @:abi are now parsed and ignored.

Using @:decl / @:abi tokens now emits a non-fatal deprecation
warning
naming the replacement.

Bare @:decl / @:abi now have no effect beyond the warning, and will be removed in a future release.

Migration steps

  • replace @:decl on an exported class with @libexport
  • replace @:abi on an exported function with @cexport

Install hatchet 0.2.7

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.2.7/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.2.7/hatchet-installer.ps1 | iex"

Download hatchet 0.2.7

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

v0.2.6 — Scalar type ascriptions (2026-06-25)

Choose a tag to compare

@github-actions github-actions released this 24 Jun 23:41
ac5c6d3

Release Notes

A correctness release: a scalar-numeric type-check expression now emits a real C++ cast, so the ascribed
arithmetic type is honoured at the value level instead of being silently narrowed. No breaking changes.

(expr : Type) pins the C++ arithmetic type

A type-check / ascription expression (expr : Type) was treated as a pure compile-time hint: the inner
expression was emitted unchanged and only its internal type was relabelled. For a scalar-numeric target
that lost the developer's intent — (Std.parseFloat(s) : cpp.Float32) still emitted a double (atof),
and (0.0 : cpp.Float32) a double literal, so a cpp.Float32-returning function silently narrowed its
result on return.

When the ascribed type is a built-in arithmetic scalar (Int, Float, Single/cpp.Float32, Bool,
the fixed-width integers, …), Hatchet now emits an explicit C cast to that type, matching what hxcpp
generates:

function toFloat(s:String):cpp.Float32 {
  return (s != null) ? (Std.parseFloat(s) : cpp.Float32) : (0.0 : cpp.Float32);
}

now lowers both arms to float((float) atof(s.c_str())) and ((float) 0.0) — so the ternary type
matches the float return with no implicit narrowing.

Non-scalar ascriptions keep the existing no-op behaviour: a class-typed null ((null : Widget)), an
empty container literal (([] : Array<Int>)), or a String adopt the ascribed type without an unwanted
or unbuildable cast.

Install hatchet 0.2.6

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.2.6/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.2.6/hatchet-installer.ps1 | iex"

Download hatchet 0.2.6

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

v0.2.5 — Haxe-aligned `untyped` & `cpp.ConstCharStar` (2026-06-24)

Choose a tag to compare

@github-actions github-actions released this 23 Jun 21:44
be53767

Release Notes

A correctness release: untyped now matches Haxe's actual semantics, raw C++ injection moves to the
__cpp__ intrinsic it belongs to, and the cpp.ConstCharStar interop type lowers. No breaking changes
for the supported untyped idiom — see below.

untyped and __cpp__ aligned with Haxe

Previously untyped <expr> was a lexical construct: it sliced the raw source to the end of the
statement and emitted it verbatim, bypassing all transpilation. That conflated two separate Haxe
mechanisms and meant the canonical escape hatch untyped __cpp__("…") was broken (it emitted the literal
text __cpp__("…")).

The two concepts are now distinct, matching Haxe:

  • untyped <expr> is the typer escape hatch. The operand is parsed and transpiled like any other
    expression; the only effect is that its static type is treated as opaque (Dynamic), so type-driven
    checks relax. It binds as a normal unary prefix rather than swallowing to the next ;.
  • __cpp__("…", a, b) (Haxe's cpp.Syntax.code) is the raw-injection intrinsic. The format string
    is emitted verbatim, with {0}, {1}, … placeholders replaced by the transpiled arguments — so
    real Hatchet expressions can be spliced into hand-written C++ (__cpp__("::fmaxf({0}, {1})", v, lo)
    ::fmaxf(v, lo)). Because Hatchet only ever targets C++, the call is recognised with or without the
    untyped wrapper Haxe needs to silence its unknown-identifier error.

The common existing idiom untyped someCName(args) is unaffected: the call is now transpiled normally and
produces identical output.

cpp.ConstCharStar lowers to const char*

hxcpp's cpp.ConstCharStar interop type now maps to const char* (joining cpp.StdStringstd::string
and the rest of the primitive mappings).

Install hatchet 0.2.5

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.2.5/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.2.5/hatchet-installer.ps1 | iex"

Download hatchet 0.2.5

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

v0.2.4 — Typedef-alias containers & method visibility (2026-06-23)

Choose a tag to compare

@github-actions github-actions released this 23 Jun 00:22

Release Notes

A correctness release: escape analysis now sees through typedef aliases to the containers they name,
and class methods land in the right C++ visibility section. No breaking changes.

Escape analysis sees through typedef alias containers

Escape analysis now peels typedef aliases (typedef Matrix = Array<Row>) before counting Array nesting,
so aliased containers are tracked at their true depth. A local container of owned (new-d) elements that
flows into an owned alias-typed field is recognised as escaping and is no longer freed at end of scope.

A nullable alias container (Null<Indicies> where typedef Indicies = Array<Int>) also keeps its
pointer-ness through alias resolution, so container methods on it dereference correctly — indices.map(…)
lowers to (*indices).size() / (*indices)[i].

Class methods lower to the correct C++ visibility

A class method lands in the C++ public section only when it is explicitly public; everything else —
including Haxe's default (no modifier) access, which is private — lowers to protected, mirroring how
fields are grouped.

Custom property accessors are the exception: a get_x / set_x backing a public property is promoted to
public even when the accessor itself is private, keeping it at least as visible as the property it serves.

Install hatchet 0.2.4

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewglind/hatchet/releases/download/v0.2.4/hatchet-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/andrewglind/hatchet/releases/download/v0.2.4/hatchet-installer.ps1 | iex"

Download hatchet 0.2.4

File Platform Checksum
hatchet-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
hatchet-x86_64-apple-darwin.tar.xz Intel macOS checksum
hatchet-x86_64-pc-windows-msvc.zip x64 Windows checksum
hatchet-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
hatchet-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum