Skip to content

Instantly share code, notes, and snippets.

@YellowAfterlife
Created May 3, 2024 12:32
Show Gist options
  • Save YellowAfterlife/e1d3408d2601cdbbfff7dd756ed9b2e0 to your computer and use it in GitHub Desktop.
Save YellowAfterlife/e1d3408d2601cdbbfff7dd756ed9b2e0 to your computer and use it in GitHub Desktop.
C-style enum macros for Haxe
import haxe.macro.Context;
import haxe.macro.Expr;
/**
* http://yal.cc/haxe-c-style-enum-macros/
* NB! You can use `@:enum abstract` for this since Haxe 3.1 and `enum abstract` since Haxe 4
* @author YellowAfterlife
*/
class IntEnum {
public static macro function build():Array<Field> {
switch (Context.getLocalClass().get().kind) {
case KAbstractImpl(_.get() => { type: TAbstract(_.get() => { name: "Int" }, _) }): // OK
default: Context.error(
"This macro should only be applied to abstracts with base type Int",
Context.currentPos());
}
var fields:Array<Field> = Context.getBuildFields();
var nextIndex:Int = 0;
var getNameCases:Array<Case> = [];
for (field in fields) {
var value:String = null;
switch (field.kind) {
case FVar(t, { expr: EConst(CInt(int)) }): { // `var some = 1;`
value = int;
nextIndex = Std.parseInt(value) + 1;
};
case FVar(t, null): { // `var some;`
value = Std.string(nextIndex++);
field.kind = FVar(t, { expr: EConst(CInt(value)), pos: field.pos });
};
default:
}
if (value != null) getNameCases.push({
values: [{ expr: EConst(CInt(value)), pos: field.pos }],
expr: { expr: EConst(CString(field.name)), pos: field.pos }
});
} // for (field in fields)
var getNameExpr:Expr = {
expr: ESwitch(macro this, getNameCases, macro null),
pos: Context.currentPos()
};
fields.push((macro class Magic {
public function getName():String return $getNameExpr;
}).fields[0]);
return fields;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment