Skip to content

Declarations

Andrew Lind edited this page Jun 18, 2026 · 2 revisions

Supported declaration forms, end to end:

  • Classes and interfaces (pure-virtual).
  • Enums — pre-C++11 struct E_ { enum … }. A parameterized enumAdd(a:Int, b:Int) — lowers to the tagged-value idiom: the same tag enum plus a copyable value class with per-variant payload fields and inline static factories, Op::Add(1, 2), so ADT values construct, pass, and store by value with no heap or union, plus structural ==/!= — same tag, equal payload, with pointer payloads compared by address (Haxe compares enum values by constructor + arguments via Type.enumEq); a recursive payload is flagged — a by-value class cannot contain itself.
  • enum abstract — an Int backing reuses the enum idiom with explicit member values, including sibling-referencing bit-flag expressions like AB = A | B; a String/Float backing becomes a namespace of typed static const constants, namespace X_ { static const std::string A = "…"; }, with the type mapping straight to its underlying C++ type.
  • Typedef structs and aliases, the fixed-width UInt8/16/32 shims, and extern interop wiring (which emits no code of its own, only the includes it contributes).

Mutually-recursive classes in one module need no manual ordering: Hatchet emits a targeted forward declaration (class B;) for any class/interface/ADT it defines that is referenced before its own definition — and only those, never extern types. (A forward declaration uses the type's emitted name, so a @:native-renamed type is declared under its renamed name.) Since Hatchet classes are reference types (every cross-class member/param/return is a pointer), a forward declaration is always sufficient, so cyclic type graphs "just work".


Related: Value Types & Abstracts for value classes and abstract Name(U) newtypes, and Metadata for @:native and the extern keyword.

Clone this wiki locally