正如@Gama11 所暗示的,你的宏函数实际上没有问题,你从哪里调用它有问题。 (Haxe 4 可能对这些检查更加严格。)
如果你有:
Main.hx
class Main
{
public static function main()
{
// Can call get from here:
var cvar = MacroUtil.get('cvar');
MacroUtil.some_macro_function();
trace('Hello world! cvar=${ cvar }');
}
}
MacroUtil.hx
import haxe.macro.Context;
import haxe.macro.Expr;
class MacroUtil
{
macro public static function get(key:String):Expr
{
return Context.makeExpr(Context.definedValue(key), Context.currentPos());
}
macro public static function some_macro_function()
{
// Cannot call get from here:
var cvar:Expr = get('cvar');
trace('will trace at compile time, and cvar is ${ cvar }');
return macro trace('will trace at runtime');
}
}
然后执行它:haxe -x Main -D cvar=abc
这将产生您遇到的错误。这是因为在some_macro_function中,你已经在宏上下文中,所以不能从那里调用宏函数get。
有几种方法可以解决这个问题。
一种方法
您可以使用#if macro / if !macro 来检测宏上下文并进行相应调整。因此,尽管这看起来很愚蠢,但它确实解决了您的特定问题:
class MacroUtil
{
#if !macro macro #end public static function get(key:String):Expr
{
这个函数签名说,如果我已经在宏上下文中,不要认为这个函数是宏函数。那时它只是一个静态助手。请记住,它返回一个Expr,而不是像在主上下文中那样的字符串。
如果您在一个文件中混合使用宏函数和非宏函数,您可能还需要使用#if macro 来避免这种情况。
另一种方法
您可以将宏函数重构为宏函数和宏助手。它有点冗长,但可能更清楚发生了什么:
MacroUtil.hx
import haxe.macro.Context;
import haxe.macro.Expr;
class MacroUtil
{
macro public static function get(key:String):Expr
{
return Context.makeExpr(MacroHelpers.get_define(key), Context.currentPos());
}
macro public static function some_macro_function()
{
// Cannot call get from here:
var cvar:String = MacroHelpers.get_define('cvar');
trace('will trace at compile time, and cvar is ${ cvar }');
return macro trace('will trace at runtime');
}
}
class MacroHelpers
{
public static function get_define(key:String):String
{
return Context.definedValue(key);
}
}
如果你这样做,那么你的宏函数都调用MacroHelpers,非宏函数调用MacroUtils。请注意,助手返回一个字符串,然后由调用站点将其转换为表达式,如果这是他们想要的。