chamberlainpi
chamberlainpi

Reputation: 5251

In Haxe, how do you read a variable name inside of a Macro?

I'm trying to use Macros to convert some variable declarations from this:

function test():Void {
    var someComp:Component = __SOME_MACRO__();

    // Or...
    @getCompById var someComp:Component;

    // Or even simpler...
    getCompById(someComp, Component); //do some fancy macro magic...
    // Also, if it's not possible/easy with a variable ...
    getCompById("someComp", Component); //with a string of the variable name.
}

... to this:

function test() {
    var someComp:Component = cast container.getCompById("someComp");
}

I'm leaning more toward the 3rd option (shorter syntax, same results).

But I have no idea how to write the macro (should it take a String as parameter? An expression?) and how to properly return that as a macro expression.

This is the (broken) code I've got so far:

macro static function getCompById(someVar:Expr, typeVar:Expr) {
    return macro {
        var someVar:typeVar = cast container.getCompById("someVar");
    };
}

Any ideas?

Upvotes: 2

Views: 351

Answers (1)

Waneck
Waneck

Reputation: 2470

The issue with the code you posted is first that you'd need reification escaping mechanisms for this to work correctly - so the first change would be to use the macro escapes:

return macro var $someVar:$typeVar = cast container.getCompById($v{someVar});

Now there will be some problems with this: It's expecting someVar to be of type String, and typeVar to be of type ComplexType. It's easy to get the string component from an Expr. It's not so easy however to transform an Expr into ComplexType. The easiest way to do that is to use the tink_macros library and use asComplexType

So the (untested) code will look something like:

using tink.MacroAPI;
using haxe.macro.Tools;
macro static function getCompById(someVarExpr:Expr, typeVarExpr:Expr)
{
  var typeVar = typeVarExpr.toString().asComplexType();
  switch (someVarExpr.getIdent())
  {
    case Success(someVar):
      return macro var $someVar:$typeVar = cast container.getCompById($v{someVar});
    case Failure(error): throw error;
  }
}

Upvotes: 5

Related Questions