在 Haxe 中,如何使用宏将 Types/Classes 添加到模块中?
In Haxe, how do you add Types/Classes to a Module with macros?
我想根据在目录中找到的一些文件向给定模块动态添加一些新类型。
我实际上是在尝试在模块底部填充一堆 @:file(...)
嵌入 类。
//This is the module I'm targeting to append embedded ByteArray subtypes (see below)
@:build(macros.AutoEmbed.build("some/folder/"))
class Embeds {
//Empty on purpose, just let the Macro do its thing!
}
// At "macro-time", it should generate these:
@:file("some/folder/ui_main.xml")
class UI_MAIN_XML extends flash.utils.ByteArray { }
@:file("some/folder/config.template.json")
class CONFIG_TEMPLATE_JSON extends flash.utils.ByteArray { }
到目前为止我能找到的是我可能必须更改 Embeds.hx
模块。所以我调查了 Context.getModule( Context.getLocalModule() )
。我也研究了 TypeDefinition
因为它似乎是从头开始定义新类型的唯一方法。
Context.getModule(...)
的问题在于它 returns 是一个数组 Array<Type>
,而不是 Array<TypeDefinition>
,所以我无法将新的 TypeDefinition
附加到它(加上我必须弄清楚如何写那些,呃)。这对我来说可能是一个错误的假设,但我认为通过简单地向其附加更多 TypeDefinition
我可以在模块中动态提供更多类型。
如您所知,我对宏还是很陌生!
编辑
的确,我可以在编译时使用 FileSystem / File write 解决方案动态 write/overwrite 一个新的 Embeds.hx
文件,但这意味着在您的 IDE 的自动完成可以获取生成的 Embeds.*
类 之前至少需要编译一次(在我的例子中是 FlashDevelop)。另外,无论何时将新文件放入定义的文件夹中,同样的问题:您需要在 IDE 检测到它之前先进行编译。是的,我真的很喜欢自动完成:)
您可以使用初始化宏:http://haxe.org/manual/macro-initialization.html 在键入之前执行宏。
然后要实际创建新的 classes/modules 你可以使用 Context.defineModule : http://api.haxe.org/haxe/macro/Context.html#defineModule
从构建宏开始就好了。您可以构建 class 字段并创建类型。
这是一个只生成一种类型和相应字段的宏:
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
class AutoEmbed
{
macro static public function build(folder:String):Array<Field>
{
var inClass = Context.getLocalClass().get();
// explore folder and create those:
var fileName = 'resource/strings.json';
var name = fileName.split('/').pop().split('.').join('_');
var valueExpr = makeType(inClass.pack, name, fileName);
var field = {
name: name,
access: [APublic, AStatic, AInline],
kind: FVar(null, valueExpr),
pos: Context.currentPos()
}
return [field];
}
static function makeType(pack:Array<String>, name:String, fileName:String)
{
var pos = Context.currentPos();
var className = name.toUpperCase();
var cdef = macro class Tmp extends haxe.io.BytesData { }
cdef.pack = pack.copy();
cdef.name = className;
cdef.meta = [{
name: ':file',
params: [Context.makeExpr(fileName, pos)],
pos: pos
}];
haxe.macro.Context.defineType(cdef);
return {
expr:EConst(CIdent(className)),
pos:pos
};
}
}
#end
现在开始使用它:
trace(Embed.strings_json); // [ByteArray]
@:build(AutoEmbed.build('some/folder'))
class Embeds
{
// generate field strings_json pointing to class STRINGS_JSON
}
我想根据在目录中找到的一些文件向给定模块动态添加一些新类型。
我实际上是在尝试在模块底部填充一堆 @:file(...)
嵌入 类。
//This is the module I'm targeting to append embedded ByteArray subtypes (see below)
@:build(macros.AutoEmbed.build("some/folder/"))
class Embeds {
//Empty on purpose, just let the Macro do its thing!
}
// At "macro-time", it should generate these:
@:file("some/folder/ui_main.xml")
class UI_MAIN_XML extends flash.utils.ByteArray { }
@:file("some/folder/config.template.json")
class CONFIG_TEMPLATE_JSON extends flash.utils.ByteArray { }
到目前为止我能找到的是我可能必须更改 Embeds.hx
模块。所以我调查了 Context.getModule( Context.getLocalModule() )
。我也研究了 TypeDefinition
因为它似乎是从头开始定义新类型的唯一方法。
Context.getModule(...)
的问题在于它 returns 是一个数组 Array<Type>
,而不是 Array<TypeDefinition>
,所以我无法将新的 TypeDefinition
附加到它(加上我必须弄清楚如何写那些,呃)。这对我来说可能是一个错误的假设,但我认为通过简单地向其附加更多 TypeDefinition
我可以在模块中动态提供更多类型。
如您所知,我对宏还是很陌生!
编辑
的确,我可以在编译时使用 FileSystem / File write 解决方案动态 write/overwrite 一个新的 Embeds.hx
文件,但这意味着在您的 IDE 的自动完成可以获取生成的 Embeds.*
类 之前至少需要编译一次(在我的例子中是 FlashDevelop)。另外,无论何时将新文件放入定义的文件夹中,同样的问题:您需要在 IDE 检测到它之前先进行编译。是的,我真的很喜欢自动完成:)
您可以使用初始化宏:http://haxe.org/manual/macro-initialization.html 在键入之前执行宏。
然后要实际创建新的 classes/modules 你可以使用 Context.defineModule : http://api.haxe.org/haxe/macro/Context.html#defineModule
从构建宏开始就好了。您可以构建 class 字段并创建类型。
这是一个只生成一种类型和相应字段的宏:
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
class AutoEmbed
{
macro static public function build(folder:String):Array<Field>
{
var inClass = Context.getLocalClass().get();
// explore folder and create those:
var fileName = 'resource/strings.json';
var name = fileName.split('/').pop().split('.').join('_');
var valueExpr = makeType(inClass.pack, name, fileName);
var field = {
name: name,
access: [APublic, AStatic, AInline],
kind: FVar(null, valueExpr),
pos: Context.currentPos()
}
return [field];
}
static function makeType(pack:Array<String>, name:String, fileName:String)
{
var pos = Context.currentPos();
var className = name.toUpperCase();
var cdef = macro class Tmp extends haxe.io.BytesData { }
cdef.pack = pack.copy();
cdef.name = className;
cdef.meta = [{
name: ':file',
params: [Context.makeExpr(fileName, pos)],
pos: pos
}];
haxe.macro.Context.defineType(cdef);
return {
expr:EConst(CIdent(className)),
pos:pos
};
}
}
#end
现在开始使用它:
trace(Embed.strings_json); // [ByteArray]
@:build(AutoEmbed.build('some/folder'))
class Embeds
{
// generate field strings_json pointing to class STRINGS_JSON
}