简体   繁体   English

在Haxe中,如何使用宏向模块添加类型/类?

[英]In Haxe, how do you add Types/Classes to a Module with macros?

I'd like to dynamically add some new Types to a given Module based on some files found in a directory. 我想基于目录中的一些文件动态地向给定模块添加一些新类型。

I'm essentially trying to populate a bunch of @:file(...) embed classes at the bottom of a Module. 我本质上是试图在模块的底部填充一堆@: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 { }

What I've been able to find so far is that I might have to alter the Embeds.hx module. 到目前为止我能找到的是我可能必须改变Embeds.hx模块。 So I looked into Context.getModule( Context.getLocalModule() ) . 所以我研究了Context.getModule( Context.getLocalModule() ) I've also looked into TypeDefinition since it seems like the only way to define a new type from scratch. 我也研究过TypeDefinition因为它似乎是从头开始定义新类型的唯一方法。

The problem with Context.getModule(...) though is that it returns an array Array<Type> , not Array<TypeDefinition> , so I can't append new TypeDefinition to it (plus I have to figure out how to write those, ughh ). Context.getModule(...)的问题是它返回一个数组Array<Type> ,而不是Array<TypeDefinition> ,所以我不能为它添加新的TypeDefinition (另外我必须弄清楚如何编写那些, )。 That's probably a bad assumption on my part, but I thought by simply appending more TypeDefinition to it I could dynamically provide more types in the module. 这对我来说可能是一个不好的假设,但我想通过简单地添加更多的TypeDefinition我可以动态地在模块中提供更多类型。

I'm still very new to Macros as you can tell! 你可以说,我对Macros还是很新的!

EDIT 编辑

It's true that I could just dynamically write/overwrite a new Embeds.hx file at compile-time with a FileSystem / File write solution, but that implies needing to compile at least once before your IDE's auto-completion can pickup the generated Embeds.* classes (FlashDevelop in my case). 确实,我可以使用FileSystem / File写入解决方案在编译时动态编写/覆盖新的Embeds.hx文件,但这意味着在IDE自动完成之前需要至少编译一次才能获取生成的Embeds.*类(我的情况下是FlashDevelop)。 Plus anytime new files are dropped in the defined folder, same problem: you need to compile first before the IDE detects it. 加上任何时候在定义的文件夹中删除新文件,同样的问题:您需要在IDE检测到之前先编译。 Yes, I really like auto-completion :) 是的,我真的很喜欢自动完成:)

Starting from the build macro is good. 从构建宏开始是好的。 You can build class fields and create types. 您可以构建类字段并创建类型。

Here's a macro which will just generate one type and a corresponding field: 这是一个只生成一种类型和相应字段的宏:

#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

Now to use it: 现在使用它:

trace(Embed.strings_json); // [ByteArray]

@:build(AutoEmbed.build('some/folder'))
class Embeds
{
    // generate field strings_json pointing to class STRINGS_JSON
}

You can use initialization macro : http://haxe.org/manual/macro-initialization.html to execute macro before typing occurs. 您可以使用初始化宏: http//haxe.org/manual/macro-initialization.html在键入之前执行宏。

Then to actually create new classes/modules you can use Context.defineModule : http://api.haxe.org/haxe/macro/Context.html#defineModule 然后,为了实际创建新的类/模块,您可以使用Context.defineModule: http//api.haxe.org/haxe/macro/Context.html#defineModule

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM