#if macro
import haxe.macro.Type;
import haxe.macro.Context;
using haxe.macro.PositionTools;
/**
* Callback on generating code from context
*/
private function mygenerate(types:Array<Type>, filterFileName: String):Void {
var buf = new StringBuf();
for (atype in types) {
// trace(atype);
var aref = atype.getParameters()[0].get();
var apos = Context.getPosInfos(aref.pos);
//trace(apos);
if(filterFileName != null && apos.file != filterFileName) continue;
switch (atype) {
case TMono(t):
trace(t + "::" + aref.pos);
case TEnum(t, params):
var t_ref = t.get();
//trace(t.toString() + "::" + aref.pos + "::" + params.toString());
buf.add('\nenum ${t_ref.name} {\n');
var enumFields = [];
for (efield in t_ref.constructs) {
//trace(efield);
var ebuf = new StringBuf();
ebuf.add('\t${efield.name}');
switch(efield.type) {
case TEnum(_, _): ebuf.add(";\n");
case TFun(args, _):
ebuf.add("(");
for (i in 0...args.length) {
var arg = args[i];
if (i > 0)
ebuf.add(", ");
var type_name = switch(arg.t) {
case TAbstract(t, params): t.get().name;
default:
throw 'Unsupported paramter ${arg.t}';
null;
};
ebuf.add('${arg.name}: ${type_name}');
}
ebuf.add(");\n");
default:
throw 'Unsupported paramter ${efield.type}';
}
enumFields.insert(efield.index, ebuf.toString());
}
for(elm in enumFields) buf.add(elm);
buf.add("}\n");
//trace(buf.toString());
case TInst(t, params):
var t_ref = t.get();
trace(aref.name + "::" + aref.pos /*.getInfos().min*/ + "::" + params.toString());
var classFields = t_ref.fields.get();
buf.add('\nclass ${t_ref.name} {\n');
//trace(classFields);
if(t_ref.constructor != null) trace(t_ref.constructor.get());
for (ifield in classFields) {
trace(ifield);
buf.add('\t${ifield.name};\n');
}
trace(t_ref.statics.get());
buf.add("}\n");
//trace(buf.toString());
case TType(t, params):
trace(aref.name + "::" + aref.pos /*.getInfos().min*/ + "::" + params.toString());
case TFun(args, ret):
trace(args + "::" + aref.pos + "::" + ret);
case TAnonymous(a):
trace(a + "::" + aref.pos);
case TDynamic(t):
trace(t + "::" + aref.pos);
case TLazy(f):
trace(f + "::" + aref.pos);
case TAbstract(t, params):
trace(aref.name + "::" + aref.pos /*.getInfos().min*/ + "::" + params.toString());
}
}
trace(buf.toString());
}
function set_on_generate(?ffname: String) {
haxe.macro.Context.onGenerate(function(types:Array<Type>){mygenerate(types, ffname);});
}
#end
haxe "TestOnGenerate.hxml"
MyOnGenerate.hx:58: Test::#pos(TestOnGenerate.hx:16: lines 16-30)::[]
MyOnGenerate.hx:62: {name: new, isFinal: false, namePos: #pos(TestOnGenerate.hx:22: characters 19-22), isPublic: true, isAbstract: false, doc: null, params: [], pos: #pos(TestOnGenerate.hx:22: lines 22-26), kind: FMethod(MethNormal), meta: {get: #fun, remove: #fun, has: #fun, extract: #fun, add: #fun}, overloads: overloads, isExtern: false, type: TFun([{name: name, t: TInst(<...>,[]), opt: false},{name: x, t: TAbstract(<...>,[]), opt: false},{name: y, t: TAbstract(<...>,[]), opt: false}],TAbstract(Void,[])), expr: #fun}
MyOnGenerate.hx:64: {name: name, isFinal: false, namePos: #pos(TestOnGenerate.hx:18: characters 14-18), isPublic: true, isAbstract: false, doc: null, params: [], pos: #pos(TestOnGenerate.hx:18: characters 3-26), kind: FVar(AccNormal,AccNormal), meta: {get: #fun, remove: #fun, has: #fun, extract: #fun, add: #fun}, overloads: overloads, isExtern: false, type: TInst(String,[]), expr: #fun}
MyOnGenerate.hx:64: {name: x, isFinal: false, namePos: #pos(TestOnGenerate.hx:19: characters 14-15), isPublic: true, isAbstract: false, doc: null, params: [], pos: #pos(TestOnGenerate.hx:19: characters 3-22), kind: FVar(AccNormal,AccNormal), meta: {get: #fun, remove: #fun, has: #fun, extract: #fun, add: #fun}, overloads: overloads, isExtern: false, type: TAbstract(Float,[]), expr: #fun}
MyOnGenerate.hx:64: {name: y, isFinal: false, namePos: #pos(TestOnGenerate.hx:20: characters 14-15), isPublic: true, isAbstract: false, doc: null, params: [], pos: #pos(TestOnGenerate.hx:20: characters 3-22), kind: FVar(AccNormal,AccNormal), meta: {get: #fun, remove: #fun, has: #fun, extract: #fun, add: #fun}, overloads: overloads, isExtern: false, type: TAbstract(Float,[]), expr: #fun}
MyOnGenerate.hx:64: {name: toString, isFinal: false, namePos: #pos(TestOnGenerate.hx:27: characters 19-27), isPublic: true, isAbstract: false, doc: null, params: [], pos: #pos(TestOnGenerate.hx:27: lines 27-29), kind: FMethod(MethNormal), meta: {get: #fun, remove: #fun, has: #fun, extract: #fun, add: #fun}, overloads: overloads, isExtern: false, type: TFun([],TInst(String,[])), expr: #fun}
MyOnGenerate.hx:67: [{name: _count, isFinal: false, namePos: #pos(TestOnGenerate.hx:17: characters 14-20), isPublic: false, isAbstract: false, doc: null, params: [], pos: #pos(TestOnGenerate.hx:17: characters 3-30), kind: FVar(AccNormal,AccNormal), meta: {get: #fun, remove: #fun, has: #fun, extract: #fun, add: #fun}, overloads: overloads, isExtern: false, type: TAbstract(Int,[]), expr: #fun}]
MyOnGenerate.hx:58: TestOnGenerate::#pos(TestOnGenerate.hx:32: lines 32-37)::[]
MyOnGenerate.hx:67: [{name: main, isFinal: false, namePos: #pos(TestOnGenerate.hx:33: characters 21-25), isPublic: false, isAbstract: false, doc: null, params: [], pos: #pos(TestOnGenerate.hx:33: lines 33-36), kind: FMethod(MethNormal), meta: {get: #fun, remove: #fun, has: #fun, extract: #fun, add: #fun}, overloads: overloads, isExtern: false, type: TFun([],TAbstract(Void,[])), expr: #fun}]
MyOnGenerate.hx:58: TestOnGenerate_Fields_::#pos(TestOnGenerate.hx:1: character 1)::[]
MyOnGenerate.hx:67: [{name: _version, isFinal: true, namePos: #pos(TestOnGenerate.hx:1: characters 7-15), isPublic: true, isAbstract: false, doc: null, params: [], pos: #pos(TestOnGenerate.hx:1: characters 1-24), kind: FVar(AccNormal,AccNever), meta: {get: #fun, remove: #fun, has: #fun, extract: #fun, add: #fun}, overloads: overloads, isExtern: false, type: TInst(String,[]), expr: #fun},{name: getVersion, isFinal: false, namePos: #pos(TestOnGenerate.hx:5: characters 10-20), isPublic: true, isAbstract: false, doc: Get version string. , params: [], pos: #pos(TestOnGenerate.hx:5: lines 5-7), kind: FMethod(MethNormal), meta: {get: #fun, remove: #fun, has: #fun, extract: #fun, add: #fun}, overloads: overloads, isExtern: false, type: TFun([],TInst(String,[])), expr: #fun}]
MyOnGenerate.hx:84:
enum Color {
Red;
Green;
Blue;
RGB(r: Int, g: Int, b: Int);
}
class Test {
name;
x;
y;
toString;
}
class TestOnGenerate {
}
class TestOnGenerate_Fields_ {
}
Trying to understand how to use
haxe.macro.Context.onGenerate(types:Array<Type>)to create custom generators I noticed that thetypesparameter comes with a strange order instead of the declaration order (line number) see the output bellow, this make it's usage a bit more involved than if it came ordered by file/line number, also probably in doing a working example several corner cases will surface and internal changes can be made to make life easy for Haxe users.Would be nice to have an entry in the
Code Cookbookwith a simple functional example and I suggest the one bellow as starting point (generate Haxe again for simplicity), any comments/suggestions/improvements are welcome !Output: