Macros 使用宏获取Haxe函数参数类型的最佳方法是什么?

Macros 使用宏获取Haxe函数参数类型的最佳方法是什么?,macros,haxe,Macros,Haxe,我想使用宏获取Haxe函数的参数类型,并将其转换为一种简写字符串形式,有点像JNI/Java方法签名,但没有返回类型 这里的动机是提供对函数参数类型的访问,而不必在运行时缓慢搜索运行时类型信息。例如,假设您想要构造一个图形小部件来调用一个接受参数的函数。您需要每个函数参数的类型来创建正确的spinbox、textbox和selectbox小部件,以调整将传递给函数的值 所以问题是,如何用宏保存Haxe函数参数类型?这是一个适用于一些基本类型的宏,以及基于这些类型的任何摘要。它将函数参数类型映射到

我想使用宏获取Haxe函数的参数类型,并将其转换为一种简写字符串形式,有点像JNI/Java方法签名,但没有返回类型

这里的动机是提供对函数参数类型的访问,而不必在运行时缓慢搜索运行时类型信息。例如,假设您想要构造一个图形小部件来调用一个接受参数的函数。您需要每个函数参数的类型来创建正确的spinbox、textbox和selectbox小部件,以调整将传递给函数的值


所以问题是,如何用宏保存Haxe函数参数类型?

这是一个适用于一些基本类型的宏,以及基于这些类型的任何摘要。它将函数参数类型映射到字符串。例如,函数类型
String->Float->Int->String->Void
映射到
sfis
Float->Float->Int
映射到
ff
等:

package;

import haxe.macro.Expr;
import haxe.macro.Context;
import haxe.macro.Type;
import haxe.macro.ExprTools;

// Map some Haxe types to string ids
@:enum abstract TypeMapping(String) from (String) {
    var BOOL = "b";
    var FLOAT = "f";
    var INT = "i";
    var STRING = "s";
}

class Util
{
    public macro static function getParameterTypes(f:Expr):ExprOf<String> {
        var type:Type = Context.typeof(f);
        if (!Reflect.hasField(type, 'args')) {
            throw "Parameter has no field 'args'";
        }
        var t = type.getParameters()[0];

        var args:Array<Dynamic> = Reflect.field(type, 'args')[0];

        var signature:String = "";
        for (i in 0...args.length) {            
            switch(args[i].t) {
                case TAbstract(t, p):
                    var underlyingTypeName = Std.string(t.get().type.getParameters()[0]);
                    switch(underlyingTypeName) {
                        case "Bool":
                            signature += TypeMapping.BOOL;
                        case "Float":
                            signature += TypeMapping.FLOAT;
                        case "Int":
                            signature += TypeMapping.INT;
                        case "String":
                            signature += TypeMapping.STRING;
                        default:
                            throw "Unhandled abstract function parameter type: " + underlyingTypeName;
                    }
                case CString:
                    signature += TypeMapping.STRING;
                default:
                    throw "Unhandled function parameter type: " + args[i];
            }
        }
        return macro $v{signature};
    }
}
包;
导入haxe.macro.Expr;
导入haxe.macro.Context;
导入haxe.macro.Type;
导入haxe.macro.ExprTools;
//将某些Haxe类型映射到字符串ID
@:枚举抽象类型映射(字符串)自(字符串){
var BOOL=“b”;
var FLOAT=“f”;
var INT=“i”;
var STRING=“s”;
}
类Util
{
公共宏静态函数getParameterTypes(f:Expr):ExprOf{
变量类型:type=Context.typeof(f);
if(!Reflect.hasField(输入'args')){
throw“参数没有字段'args';
}
var t=type.getParameters()[0];
变量args:Array=Reflect.field(类型为'args')[0];
var签名:String=“”;
对于(i in 0…args.length){
开关(args[i].t){
病例表(t,p):
var underlyngTypeName=Std.string(t.get().type.getParameters()[0]);
开关(参考类型名称){
案例“Bool”:
签名+=TypeMapping.BOOL;
案例“浮动”:
签名+=TypeMapping.FLOAT;
案例“Int”:
签名+=TypeMapping.INT;
大小写“字符串”:
签名+=TypeMapping.STRING;
违约:
抛出“未处理的抽象函数参数类型:”+underyingTypeName;
}
案例编号:
签名+=TypeMapping.STRING;
违约:
抛出“未处理的函数参数类型:”+args[i];
}
}
返回宏$v{signature};
}
}
另一个问题是如何使它适用于所有类型,而不仅仅是显式处理的类型。为此,可以使用每个函数参数的类型名/类名/路径填充字符串数组,并返回该字符串而不是单个字符串。这里有一个尝试,请注意,它不适用于函数参数(可能还有其他内容):

公共宏静态函数getFullParameterTypes(f:Expr):ExprOf{ 变量类型:type=Context.typeof(f); if(!Reflect.hasField(输入'args')){ throw“参数没有字段'args'; } 变量args:Array=Reflect.field(类型为'args')[0]; var pos=haxe.macro.Context.currentPos(); var签名:数组=[]; 用于(0中的i…参数长度){ 变量argType:Type=args[i].t; var s; 开关(argType){ 案例TFun(t,r): s=经济(CString(“功能”); 抛出“尚未使用函数参数”; 个案: s=EConst(CString(argType.getParameters()[0].toString()); } signature.push({expr:s,pos:pos}); } 返回宏$a{signature}; }
public macro static function getFullParameterTypes(f:Expr):ExprOf<Array<String>> {
    var type:Type = Context.typeof(f);
    if (!Reflect.hasField(type, 'args')) {
        throw "Parameter has no field 'args'";
    }
    var args:Array<Dynamic> = Reflect.field(type, 'args')[0];

    var pos = haxe.macro.Context.currentPos();
    var signature:Array<Expr> = [];

    for (i in 0...args.length) {
        var argType:Type = args[i].t;
        var s;
        switch(argType) {
            case TFun(t, r):
                s = EConst(CString("Function"));
                throw "Not working with function parameters yet";
            case _:
                s = EConst(CString(argType.getParameters()[0].toString()));
        }
        signature.push({expr: s, pos: pos});
    }
    return macro $a{signature};
}