统一宏中的泛型类型

时间:2016-02-25 06:05:10

标签: macros haxe

我想使用宏来检查函数是否返回特定的泛型类型,比如说Array,所以如果函数返回Array<Dynamic>Array<String>,甚至是通用Array<T>

所以我尝试使用Context.unify Array<Dynamic>。它适用于Array<String>Array<Dynamic>但是当type参数为“generic”时失败,因为ComplexType Array<T>不会转换为带Type not found: T的Type(请参阅代码下面)。是否有任何可能的方法来实现我的目标?

package;

#if macro
import haxe.macro.Context;
using haxe.macro.ComplexTypeTools;
#end

#if !macro @:build(Macros.build()) #end
class Main 
{
    public function test<T>():Array<T>
    {
        return [];
    }
}

class Macros
{
    public static function build()
    {
        #if macro
        var fields = Context.getBuildFields();
        for(field in fields)
        {
            switch(field.kind)
            {
                case FFun(f):
                    // try to unify Array<String> with Array<Dynamic>
                    trace(Context.unify((macro:Array<String>).toType(), (macro:Array<Dynamic>).toType())); 
                    // true

                    // try to unify Array<T> with Array<Dynamic>
                    trace(Context.unify(f.ret.toType(), (macro:Array<Dynamic>).toType())); 
                    // Type not found: T
                default:
            }
        }
        return null;
        #end
    }
}

1 个答案:

答案 0 :(得分:2)

更新

因此,检查TPath不是最好的主意。 基于先前关于动态可分配给任何类型的假设,我们可以用Dynamic替换不可转换的类型参数(例如Array<T> = Array<Dynamic>)并尝试统一它。

static function toTypeExt(c:ComplexType):Null<haxe.macro.Type>
{
    try {
        return c.toType();          
    } catch (error:Error)
    {                   
        switch (c)                          
        {
            case TPath(p):                  
                //deep copy of the TPath with all type parameters as Dynamic
                var paramsCopy = [for (i in 0...p.params.length) TPType(macro:Dynamic)];
                var pCopy:TypePath = {
                    name: p.name,
                    pack: p.pack,
                    sub: p.sub,
                    params: paramsCopy
                }
                var cCopy = TPath(pCopy);

                //convert after
                return cCopy.toType();
            default:                    
        }
    }

    return null;
}

在构建宏中使用 toTypeExt()而不是toType。

trace(Context.unify(toTypeExt(f.ret), (macro:Array<Dynamic>).toType()));

对我来说看起来更像是一种解决方法,但是关于ComplexTypeTools.toType有一个奇怪的事情 - 它会在使用方法类型参数失败时使用类类型参数成功。

OLD ANSWER

统一无法工作,因为无法将带有类型参数的ComplexType转换为Type(在该上下文中)。但是,由于您正在与Array统一,因此可以安全地假设任何数组都将与它统一(因为任何类型都可以分配给Dynamic http://haxe.org/manual/types-dynamic.html)。

可能不是 pritiest 解决方案,但是简单的TPath检查就是这里的方法:

    case FFun(f):                   
        switch (f.ret) {
                case TPath({ name: "Array", pack: [], params: _ }):
                    trace("Yay!");
                default:                            
        }