-
Notifications
You must be signed in to change notification settings - Fork 0
Metadata
Hatchet reacts to two kinds of metadata, kept deliberately separate. (Internally Hatchet matches
metadata by name and ignores the @:/@ prefix, but the prefix matters to other Haxe targets,
so write each tag in the form shown.)
Real metadata whose meaning Hatchet matches, so the same source stays valid and keeps compiling under hxcpp:
| Tag | Effect in Hatchet |
|---|---|
@:native("a::b::Name") |
Rename the emitted C++ symbol (and namespace) — the type/function is still Hatchet's to emit, just under that name. Orthogonal to extern
|
@:include("p.h") / @:include("<h>")
|
Emit an #include (quoted for a project header, angle-bracketed verbatim for a system one) |
@:cppFileCode('…') |
Inject verbatim C++ at that point in a body (also real hxcpp) |
@:headerCode('…') |
Inject verbatim C++ into the generated header (after the #includes, before the declarations), on any module — also real hxcpp. On the prelude source (StdAfx.hx) it is instead merged into the prelude (see The Prelude) |
@:overload(function(...){}) |
Resolve a call to the matching C++ overload by argument type, else a hard error |
@:isVar |
Force a physical backing field for a property (so (get,never) keeps storage) |
@:op(...) |
(on an abstract method) operator overloading → a C++ operator forwarding to the method: @:op([]) read → operator[], @:op(A op B) → binary operator op, prefix unary @:op(-A)
|
@:to / @:from
|
(on an abstract method) @:to → an implicit conversion operator; @:from (static) → a converting constructor |
@:stackOnly |
A value class that also obeys hxcpp's stack-residence rule — may not be nested as a field/element (flagged, steering to an abstract). Portable; use for genuine stack-only value types |
A type whose implementation lives in hand-written C++ is declared extern (extern class /
extern interface / extern enum, all valid Haxe): Hatchet emits no definition for it, only
type-checks and references it, and pulls its @:include into anything that uses it. This is separate
from @:native, which only renames — combine them to bind to a specific C++ name
(extern @:native("jobject") class JObject).
Hatchet's own. The guiding rule: a user-metadata tag exists only for a C++ reality Haxe genuinely
cannot express — now that value-types-with-methods are abstract newtypes, that comes down to a few
things: manual memory ownership, zero-cost extern interop glue (@proxy), a VC6-safe
ordered-map representation (@orderedMap), and shared-library / C-ABI symbol export
(@libexport / @cexport — Haxe's own @:decl / @:abi turned out to be inbound-only, see the note
above). Anything Haxe can say — operators, casts, value types via abstract, external types via
extern, access levels — is expressed in real Haxe, not invented here. Because these are plain user
metadata, every other Haxe target ignores them, so the source stays portable.
| Tag | Effect |
|---|---|
@owned |
A field the owning object frees in its destructor (a scalar via delete, a container element-by-element) |
@sink |
Ownership leaves the current scope (it is not freed here). On a parameter (@sink val:T) it marks a consuming position; on a call argument (foo(@sink v), new Quad(@sink new Vertex(...))) it hands that argument off at the call; on a local declaration (@sink var x = new X(...)) it suppresses the scope-close free of x (the inverse of @delete var) |
@delete |
Free a marked local (@delete var x = …) at scope close |
@proxy("native::Name") |
Binds a Haxe type to a native C++ class it is never emitted for — either a transparent handle you call through, or a base you subclass. See Interop via @proxy
|
@orderedMap |
(on a Map<K,V> field) store it as two insertion-ordered parallel vectors (m_keys/m_vals) instead of a std::map — an ordered map that also sidesteps std::map (key-sorted, and fragile on VC6). Operations (get/set/exists/remove/keys, for (k => v in m)) lower to scans over the vectors; using the field as a whole value is a hard error. See Container Semantics
|
@libexport |
(on a class) export it from the shared library via the portable <PREFIX>_CLASS visibility macro — __declspec(dllexport) on MSVC, __attribute__((visibility("default"))) on GCC/Clang, nothing elsewhere. Platform-neutral by design (covers Windows DLLs and Unix .so/.dylib) |
@cexport |
(on a module-level function) export it across a C ABI: emitted as an extern "C" global at file scope with the portable export/calling-convention macros (HATCHET_EXPORT/HATCHET_CALL) |
The ownership tags (@owned / @sink / @delete) are covered in detail on
Memory Ownership.
Both paths compile under hxcpp and Hatchet (the compile-time guarantee); only their runtime
representation can differ, and Hatchet's emitted C++98 is the authoritative runtime (see the note on
Home). The reference-semantic path — plain class plus @owned/@sink/@delete — even
behaves the same under both (hxcpp's GC ignores the ownership tags; Hatchet's analysis uses them). The
value-semantic path — abstract Name(U) and @:stackOnly — is a flat value type under Hatchet, but
under hxcpp its representation depends on the underlying (an anonymous-structure underlying is a heap
object there), so copy-vs-share behaviour can diverge. Validate such behaviour on the transpiled C++98.
Hatchet is licensed under the MIT License — see LICENSE. (c) 2026 Andrew Grant Lind
Getting Started
Language Support
- Declarations
- Value Types & Abstracts
- Members & Access
- Statements & Expressions
- Types & Nullability
- Conditional Compilation
- Memory Ownership
Semantics & Interop
Internals