Skip to content

Instantly share code, notes, and snippets.

@Antriel
Last active May 15, 2020 10:57
Show Gist options
  • Save Antriel/f8c2ebf673de026ff5e2772155ea2ab3 to your computer and use it in GitHub Desktop.
Save Antriel/f8c2ebf673de026ff5e2772155ea2ab3 to your computer and use it in GitHub Desktop.
Haxe Macros – Convert Expr of EnumValue to value inside macro context
import haxe.macro.ExprTools;
import haxe.macro.Context;
import haxe.macro.Type;
import haxe.macro.Expr;
import Type in StdType;
class ExprToEnumVal {
public static macro function foo(e:Expr) {
return switch exprToEnum(e, macro:ExprToEnumVal.Foo, Foo) {
case A: macro null;
case B(i): macro $v{i};
case C(f): macro 'nested';
}
}
#if macro
static function getTyped(e:Expr, as:ComplexType = null) {
if (as == null)
return try Context.typeExpr(e) catch (e:Dynamic) null;
var wrapped = getTyped(macro($e : $as));
switch wrapped.expr {
case TParenthesis({expr: TCast(e, m)}):
return e;
case _:
throw "Invalid.";
}
}
static function makeEnum(fa:FieldAccess, params:Array<Dynamic>) {
switch fa {
case FEnum(_.get() => e, ef):
var fullPath = e.pack.concat([e.name]).join('.');
var enm = StdType.resolveEnum(fullPath);
var val = StdType.createEnum(enm, ef.name, params);
return val;
case _:
throw "Invalid.";
}
}
static function typedExprToEnum(e:TypedExpr):Dynamic {
return switch e.expr {
case TField(e, fa): makeEnum(fa, []);
case TCall({expr: TField(e, fa)}, el):
var params = [
for (p in el)
try ExprTools.getValue(Context.getTypedExpr(p)) catch (e:Dynamic) {
if (p.t.match(TEnum(_)))
typedExprToEnum(p);
else
Context.error('Unimplemented enum param $p.', p.pos);
}
];
makeEnum(fa, params);
case other: Context.error('Invalid expr.', e.pos);
}
}
static function exprToEnum<T>(expr:Expr, enumCT:ComplexType, enumT:Enum<T> = null):T {
var typed = getTyped(expr, enumCT);
if (typed != null)
return typedExprToEnum(typed);
else
return null;
}
#end
}
enum Foo {
A;
B(i:Int);
C(f:Foo);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment