Building enums is analogous to building classes with a simple mapping:
FVar.FFun.import haxe.macro.Context; import haxe.macro.Expr; class EnumBuildingMacro { macro static public function build():Array<Field> { var noArgs = makeEnumField("A", FVar(null, null)); var eFunc = macro function(value:Int) {}; var fInt = switch (eFunc.expr) { case EFunction(_, f): f; case _: throw "false"; } var intArg = makeEnumField("B", FFun(fInt)); return [noArgs, intArg]; } static function makeEnumField(name, kind) { return { name: name, doc: null, meta: [], access: [], kind: kind, pos: Context.currentPos() } } }
@:build(EnumBuildingMacro.build()) enum E {} class Main { static public function main() { switch (E.A) { case A: case B(v): } } }
Because enum E is annotated with a :build metadata, the called macro builds two constructors A and B "into" it. The former is added with the kind being FVar(null, null), meaning it is a constructor without argument. For the latter, we use reification to obtain an instance of haxe.macro.Expr.Function with a singular Int argument.
The main method proves the structure of our generated enum by matching it. We can see that the generated type is equivalent to this:
enum E { A; B(value:Int); }