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); }