2015-10-02 19 views
5

Dizinde bulunan bazı dosyalara bağlı olarak belirli bir Modüle yeni bazı Türler eklemek istiyorum. Haxe'de, Modül/Sınıfları makrolara sahip bir Modüle nasıl eklersiniz?

Ben aslında bir Modülü altındaki @:file(...) embed sınıfların bir demet doldurmak çalışıyorum. Şimdiye kadar bulmak mümkün oldum ne

//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 { } 

Ben Embeds.hx modülünü değiştirmek gerekebilir olmasıdır. Bu yüzden Context.getModule(Context.getLocalModule())'a baktım. Yeni bir türü sıfırdan tanımlamanın tek yolu gibi göründüğünden, TypeDefinition'u da inceledim.

Context.getModule(...) sorun olsa bir dizi Array<Type> değil Array<TypeDefinition> döndürdüğünü, bu yüzden kendisine yeni TypeDefinition ekleme olamaz (artı O, ughh nasıl yazılacağını anlamaya gerekir). Muhtemelen benim üzerimde kötü bir varsayım var, ama ben daha fazla TypeDefinition ekleyerek bu modülde dinamik olarak daha fazla çeşit sağlayabileceğimi düşündüm.

Hala söyleyebilirim Makrolar'ın çok yeniyim!

DÜZENLEME

Ben sadece dinamik yazabilirsiniz doğrudur/a FileSystem/Dosyayla derleme zaman yeni Embeds.hx dosyanın üzerine çözüm yazma, ama bundan önce en az bir kez derlemek gerek ima senin IDE'nin otomatik tamamlama işlemi, oluşturulan Embeds.* sınıflarını alabilir (benim durumumda FlashDevelop). Artı tanımlı klasöre her zaman yeni dosyalar bırakılır, aynı sorun: IDE'nin bunu tespit etmesinden önce derlemeniz gerekir. Evet, gerçekten otomatik tamamlama :) Sen başlatma makro kullanabilirsiniz

cevap

6

inşa makro iyidir başlayarak:

Sonra aslında Context.defineModule kullanabilirsiniz yeni sınıflar/modüller oluşturmak için. Sınıf alanları oluşturabilir ve türleri oluşturabilirsiniz.

Şimdi
#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 

kullanmak için:

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

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

Güzel ve tam kod örneği

Burada sadece bir türü ve ilgili alanı oluşturacak bir makro var! Teşekkürler. Soru, 'Tmp' makro sınıftan geliyor Tmp, haxe.io.BytesData 'bölümünü uzatıyor? Ve hala haxe sürümü yerine flash.utils.ByteArray uzatabilir miyim (iki arasında dürüst olmak için fark emin değilim ...)? – bigp

+0

Bir dummy sınıf adı kullanıyorum çünkü burada dinamik değeri nasıl kullanacağımı anlamadım ... BytesData Flash ByteArray ile aynıdır - muhtemelen bunu da kullanabilirsiniz. – Philippe

İlgili konular