如何创建一个宏来生成一个在 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" } ]}
)
});

我试图用宏完成的事情是可能的吗?如果是这样,可以指导我完成此操作的步骤吗?

谢谢。

问题是你试图将其输出为单个标识符,而它实际上是一个点路径,它应该表示为第一个EIdentEField链。幸运的是,Haxe 有一个方便的"路径"统一:尝试$p{path.split(".")}(其中path是你的"entities.Foo"字符串)。

在对 API 参考进行了更多挖掘之后,我想出了该怎么做。事实证明,我需要TypedExpr,而不仅仅是一个标识符常量。

具有ModuleTypeTClassDeclTTypeExpr将产生正确的结果。 所以我上面的示例代码变成:

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;
}

最新更新