Как получить тип параметра метода класса с макросом? - PullRequest
2 голосов
/ 02 мая 2019

Как получить тип параметра метода класса с помощью макроса?

class A{
 public function new(){
  //this how get method out arg[0] Type with macro?
  var arg0IsInt:Bool=arg0IsInt(out);
 }
 public function out(a:Int){ return true; }

 macro public function arg0IsInt(e:Expr):Bool{
 } 

}

Я собираюсь вызвать метод, у которого есть параметр для типа, когда я создаю букву.

Ответы [ 2 ]

3 голосов
/ 02 мая 2019

Вы можете передать out макросу выражения и затем использовать Context.typeof(). Результатом будет тип функции (TFun), первый аргумент которого вы можете проверить, используя сопоставление с шаблоном .

Вот рабочий пример:

import haxe.macro.Context;
import haxe.macro.Expr;

class Main {
    static function main() {
        new Main();
    }

    public function new() {
        trace(arg0IsInt(out)); // true
        trace(arg0IsInt(out2)); // false
    }

    public function out(a:Int) {}

    public function out2(a:Float) {}

    macro static function arg0IsInt(func:Expr):Expr {
        return switch Context.typeof(func) {
            case TFun(args, _):
                switch args[0].t {
                    case TAbstract(_.get() => t, _) if (t.name == "Int" && t.pack.length == 0):
                        macro true;
                    case _:
                        macro false;
                }
            case _:
                throw 'argument should be a function';
        }
    }
}

Int является abstract, и чтобы убедиться, что это не просто какой-то случайный реферат с именем Int в каком-то другом пакете, мы проверяем, что он находится в пакете верхнего уровня (pack.length == 0).

2 голосов
/ 02 мая 2019

На самом деле вы можете пойти очень далеко с сопоставлением с образцом:

import haxe.macro.Context;
import haxe.macro.Expr;

class Test {
    static function main() {
        new Test();
    }

    public function new() {
        trace(arg0IsInt(out)); // true
        trace(arg0IsInt(out2)); // false
    }

    public function out(a:Int) {}

    public function out2(a:Float) {}

    macro static function arg0IsInt(func:Expr):Expr {
        return switch Context.typeof(func) {
            case TFun(_[0] => {t: TAbstract(_.get() => {name: 'Int', pack: []}, _)}, _): macro true;
            case TFun(_): macro false;
            case _: throw 'argument should be a function';
        }
    }
}
...