我想创建一个为我生成此代码的宏:
if (myEntity.get(Attack) == null) myEntity.add(new Attack());
if (myEntity.get(Confused) == null) myEntity.add(new Confused());
if (myEntity.get(Defend) == null) myEntity.add(new Defend());
if (myEntity.get(Offense) == null) myEntity.add(new Offense());
在代码中,我想这样声明/使用它:
EntityMacroUtils.addComponents(myEntity, Attack, Confused, Defend, Offense);
当前的宏函数如下所示:
macro public static function addComponents(entity:ExprOf<Entity>, components:Array<ExprOf<Class<Component>>>):Expr
{
var exprs:Array<Expr> = [];
for (componentClass in components)
{
var instance = macro $e { new $componentClass() }; // problem is here
var expr = macro if ($entity.get($componentClass) == null) $entity.add(instance);
exprs.push(expr);
}
return macro $b{ exprs };
}
此宏函数不正确,我得到了错误:
EntityMacroUtils.hx:17:字符22-43:找不到类型:$ componentClass
问题是我不知道如何定义new $componentClass()
。我该如何解决?
我也想避免Type.createInstance
在输出代码中使用。
以编程方式生成实例化代码的一种方法是使用“老式”枚举AST建筑(兼容Haxe 3.0.1+):
// new pack.age.TheClass()
return {
expr:ENew({name:"TheClass", pack:["pack", "age"], params:[]}, []),
pos:Context.currentPos()
};
可以使用修正来改进语法:
// new pack.age.TheClass()
var typePath = { name:"TheClass", pack:["pack", "age"], params:[] };
return macro new $typePath();
现在,为了方便使用“实例化助手”函数语法,我们需要进行一些扭曲,以从宏函数中接收的表达式中提取类型路径:
// new Foo(), new pack.Bar(), new pack.age.Baz()
instantiate(Foo, pack.Bar, pack.age.Baz);
macro static function instantiate(list:Array<Expr>)
{
var news = [for (what in list) {
var tp = makeTypePath(what);
macro new $tp();
}];
return macro $b{news};
}
#if macro
static function makeTypePath(of:Expr, ?path:Array<String>):TypePath
{
switch (of.expr)
{
case EConst(CIdent(name)):
if (path != null) {
path.unshift(name);
name = path.pop();
}
else path = [];
return { name:name, pack:path, params:[] };
case EField(e, field):
if (path == null) path = [field];
else path.unshift(field);
return makeTypePath(e, path);
default:
throw "nope";
}
}
#end
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句