Haxe 宏 - 将 "function" 替换为 "async function"

Haxe Macros - replace "function" with "async function"

我希望在将 haxe 转换为 JavaScript 时,将异步添加到其方法中。 我有 Haxe 代码:

@:expose
class Main implements IAsync {    
    static function main() {
        trace("test");
    }       

    static function testAwait() {
        return 1;
    }
}

而这段代码转换成这样的代码:

. . .
Main.testAwait = function() {
    return Main.test();
};
. . .

我希望能够将此代码中的 function 替换为 async function。 例如:

Main.testAwait = async function() {
    return Main.test();
};

但我只能更改示例代码宏的方法名称:

package haxe_test;

import haxe.macro.Expr;
import haxe.macro.Context;   
using haxe.macro.Tools;
using haxe_test.AsyncBuilder;

class BuildHub {
    macro static public function build():Array<Field> {
        var fields = Context.getBuildFields();
        var testFunc:Function = {
            expr: macro return $v{1},
            ret: null,
            params: [],
            args: []
        };

    fields.push({
        name:  "testAwait",
        access:  [Access.AStatic],
        kind: FieldType.FFun(testFunc),
        pos: Context.currentPos(),
    });
    return fields;  
}

如何将function替换为async function? UPD:我简化了代码。也许有什么选项编译器或 JSGenApi 可以帮助我)?

我认为您的一般选择是:

  • 在构建宏中收集有关异步 types/fields 的信息,然后在 haxe.macro.Context.onAfterGenerate 中使用它来修改输出文件。由于 Haxe 代码始终缩进,您可以使用几个正则表达式(我曾经制作了一个宏,以这种方式将输出文件拆分为多个按包文件)。
  • haxe.macro.ExampleJSGenerator 做一个稍微修改的副本,以便在感兴趣的方法声明之前添加 async。由于不需要对表达式打印进行任何更改,这也很容易。

不确定您是否考虑过更简单的事情,但在 Haxe 4 中您可以这样做:

class Test {
  static function main() {
    var value = await( async(testAsync) );
    trace(value);
  }

  static function testAsync() return 1;

  static inline function await<T>(fn:Void->Void):T {
    return js.Syntax.code("await {0}()", fn);
  }
  static inline function async<T>(fn:Void->Void):T {
      return js.Syntax.code("async () => {0}()", fn);
  }
}

或同时进行:

class Test {
  static function main() {
    var value = asyncAwait( testAsync );
    trace(value);
  }

  static function testAsync() return 1;

  static inline function asyncAwait<T>(fn:Void->Void):T {
      return js.Syntax.code("(async () => { await {0}() })()", fn);
  }
}