Haxe Macros - replace “function” with “async function”

I want that when converting haxe to JavaScript, asynchronous is added to its methods. I have Haxe code:

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

    static function testAwait() {
        return 1;
    }
}

And this code is converted to such a code:

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

I wanted to be able replace function to async function in this code. For example:

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

But I can only change the name of the method for example code macros:

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;  
}

How replace function to async function? UPD: I simplified code. Maybe is anythings options compilers or JSGenApi can help me)?

Answers:

Answer

I think your general options would be:

  • Collect information about async types/fields in build macros, then use that in haxe.macro.Context.onAfterGenerate to modify the output file. Since Haxe code is consistently indented, you can get away with a couple regular expressions (I once made a macro that'd split the output file into multiple by-package files this way).
  • Make a slightly modified copy of haxe.macro.ExampleJSGenerator to prepend async before method declarations of interest. Since you do not need any changes to expression printing, this is also pretty easy.
Answer

Not sure if you considered something more simple but in Haxe 4 you can do something like this:

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);
  }
}

or do both at same time:

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);
  }
}

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.