构建宏中的数组类型问题

Array typing issue in build macro

注意:我的问题 #4417 已关闭,但我不想成为那个为同一件事打开另一个问题的人。

基于 #3132[ { "a": 1, "b": 2 }, { "a": 2 } ] 不会编译,除非您专门将其键入 Array<Dynamic> 或包含两者的任何类型。我想这很好,但是在下面的构建宏中,我没有地方可以输入数组,我得到了一个错误。

一般来说,我可以使用 untyped (http://try.haxe.org/#3dBf5) 使地图文字符号工作,但我不能在这里这样做,因为我的类型还没有构建。

macro public static function test():Array<Field> {

    var fields = Context.getBuildFields();

    // parse the JSON
    var o = Context.parseInlineString('{ "arr": [ { "a": 1, "b": 2 }, { "a": 2 } ] }', Context.currentPos());

    // ["test" => json] map literal notation
    var a = [{ expr : EBinop(OpArrow, macro $v { "test" }, o), pos : Context.currentPos() }];

    // creates: "public var json:StringMap<Dynamic> = ['test' => json];"
    var nf:Field = {
        name : "json",
        doc : "docs",
        meta : [],
        access : [APublic],
        kind : FVar(macro : haxe.ds.StringMap<Dynamic>, { expr : EArrayDecl(a), pos : Context.currentPos() } ),
        pos : Context.currentPos()
    };

    fields.push(nf);

    return fields;
    // error: Arrays of mixed types... 
}

在事先不知道 json 的结构是什么的情况下,我能做些什么吗?

您仍然可以通过构造一个中间 EUntyped(o) 表达式(更简单地说 macro untyped $o)来使用 untyped

或者,您可以遍历已解析的对象并将 ECheckTypeDynamic 表达式添加到每个数组,生成类似 ([...]:Array<Dynamic>).

的内容

在构建地图字面量表达式之前,此方法的实现类似于使用已解析的 o 对象调用以下 checkTypeArrays 函数。

static function checkTypeArrays(e:Expr):Expr
{
    return switch (e) {
    case { expr : EArrayDecl(vs), pos : pos }:
        macro ($a{vs.map(checkTypeArrays)}:Array<Dynamic>);
    case _:
        haxe.macro.ExprTools.map(e, checkTypeArrays);
    }
}

对此的改进是仅将失败的数组 (:Array<Dynamic>) 包装在 Context.typeof(expr).