Haxe Macros-用“异步功能”替换“功能”

时间:2019-12-16 21:44:03

标签: javascript function replace macros haxe

我希望将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可以帮助我)?

2 个答案:

答案 0 :(得分:2)

我认为您的一般选择是:

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

答案 1 :(得分:0)

不知道您是否考虑过一些更简单的方法,但是在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);
  }
}