Haxe 4:宏中未捕获的异常

问题描述

我在Haxe 3中使用过这样的代码

macro public static function get(key:String)
{
    return Context.makeExpr(Context.definedValue(key),Context.currentPos());
}

但是,在迁移到Haxe 4之后,该编译失败并出现错误

宏未捕获的异常

该如何将该功能迁移到Haxe 4?为了避免此问题,是否有更好的方法来访问构建标志?

解决方法

正如@ 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。请注意,帮助程序返回了一个String,然后由调用站点将其转换为表达式(如果他们想要的话)。

,

我们最终删除了整个get方法,并将出现的事件切换为改为使用Compiler.getDefine(),Haxe 3和4均支持。

我认为,我们面临的问题与以下事实有关:从我们的测试运行器脚本中调用了此静态宏get,因此很可能是某个宏在其中调用另一个宏的地方。尽管如此,我还是尝试将杰夫·沃德(Jeff Ward)建议的解决方案放在适当的位置,但始终得到相同的结果。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...