簡體   English   中英

如何創建一個生成一個在Haxe中按名稱動態知道的構造函數數組的宏?

[英]How to create a macro that generates an array of constructors known dynamically by name in Haxe?

我的目標是javascript

我有一個在Context.onGenerate()上運行的宏,它將完全限定類型名稱的子集保存到文件中。 然后,另一個構建宏(將在下一個buid上運行)從文件中讀取類型名稱列表,以便創建向一個類添加靜態字段,該類應該在數組中保存這些類型(構造函數)。

我想從第二個宏生成的字段將是這樣的:

public static _entities:Array<Class<entities.Entity>> = [
    entities.Foo,
    entities.Bar,
    ...
];

哪個會生成以下javascript

MyClass._entities = [ entities_Foo, entities_Bar, ... ];

現在我嘗試手動編寫字段以確保一切正常生成 - 確實如此。 但是我無法弄清楚編寫宏的正確方法,我不得不添加一個標識符常量作為數組表達式的值,它始終以“未知標識符”錯誤結束:

var id = { expr: EConst( CIdent( "entities.Foo" ) ), 
           pos: Context.currentPos() };

var ex  = EArrayDecl([ id ]);

fields.push( {
    name    : "_entities",
    access  : [Access.APublic, Access.AStatic ],
    pos     : Context.currentPos(),
    kind    : FVar( 
                macro:Array<Class<entities.Entity>>,

                // I've tried writing it without reification: (see above vars)
                { expr: ex, pos:Context.currentPos() }

                // Or w/ reification:
                macro $a{[ $i{ "entities.Foo" } ]}
              )
});

我正在嘗試用宏來完成什么? 如果是這樣可以指導我完成這個步驟?

謝謝。

問題是,你想輸出它作為一個標識符,而它實際上是一個點的路徑,這應該被表示為鏈EField s到第一EIdent 幸運的是,Haxe有一個方便的“路徑” 具體權利:嘗試$p{path.split(".")} (其中path是你的"entities.Foo"字符串)。

在對API參考進行了一些挖掘后,我想出了如何做到這一點。 事實證明我需要TypedExpr而不僅僅是標識符常量。

模塊類型TClassDeclTTypeExpr將產生正確的結果。 所以上面的示例代碼變成:

static function getTypeRef( name:String ):Ref<ClassType>
{
    var type = Context.getType( name );

    switch( type )
    {
        default: return Context.error( "Expected a ClassType", Context.currentPos() );
        case TInst( cr, _ ):
            return cr;
    }
}


static function getTypes()
{
    // Obtain ClassType by identifier
    var fooCls = getTypeRef( "entities.Foo" );

    // Get a TypedExpr for the ClassType
    var typedExpr:TypedExpr = {
        expr : TTypeExpr( TClassDecl( fooCls ) ),
        t    : TInst( fooCls, [] ),
        pos  : Context.currentPos()
    };

    // Convert to Expr
    var expr:Expr = Context.getTypedExpr( typedExpr );

    var fields = Context.getBuildFields();

    fields.push( {
        name    : "_entities",
        access  : [Access.APublic, Access.AStatic ],
        pos     : Context.currentPos(),
        kind    : FVar( 
                    macro:Array<Class<entities.Entity>>,
                    macro $a{[ ${expr} ]}   // <- Now it works here
                  )
    });

    return fields;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM