Skip to content

Instantly share code, notes, and snippets.

@skial
Created October 29, 2014 11:35
Show Gist options
  • Select an option

  • Save skial/11928684eb90c8bbbf28 to your computer and use it in GitHub Desktop.

Select an option

Save skial/11928684eb90c8bbbf28 to your computer and use it in GitHub Desktop.
How to collect values across multiple @:autoBuild macro runs. Using Haxe 3.2.0 (git build development @ 3a255a8).
-main Main
-js test.js
--next
-cmd node test.js
package ;
import haxe.ds.StringMap;
import haxe.macro.Compiler;
import haxe.macro.Printer;
import haxe.macro.Type;
import haxe.macro.Expr;
import haxe.macro.Context;
using StringTools;
using haxe.macro.MacroStringTools;
/**
* ...
* @author Skial Bainn
*/
class Macro {
public static var previous:String = 'Helper';
public static var parent:ClassType = null;
public static var processed:StringMap<String> = new StringMap();
public static var values:Array<Expr> = [];
public static function build() {
var cls:ClassType = Context.getLocalClass().get();
var path = cls.pack.toDotPath( cls.name );
var fields = Context.getBuildFields();
parent = cls;
var superCls = cls.superClass;
while (superCls != null) {
var c = superCls.t.get();
var n = c.pack.toDotPath( c.name );
parent = c;
if (!processed.exists(n)) {
for (field in c.fields.get()) {
for (meta in field.meta.get()) if (meta.name == 'f' && meta.params != null) {
values = values.concat( meta.params );
}
}
processed.set(n, '');
}
superCls = c.superClass;
}
if (!processed.exists( path )) {
for (field in fields) for (meta in field.meta) if (meta.name == 'f' && meta.params != null) {
values = values.concat( meta.params );
}
processed.set( path, '' );
}
var helperName = 'H${Math.random()}'.replace('.', '_');
var helperClass = {
pack:[], name: helperName, pos: cls.pos,
meta: [ { name:':native', params:[macro 'Helper'], pos:cls.pos }, { name:':keep', params:[], pos:cls.pos } ],
kind: TDClass(), fields:[{name:'values', access:[APublic, AStatic], kind:FVar(macro:Array<String>, macro $a{values}), pos:cls.pos}]
}
Context.defineType( helperClass );
Compiler.exclude( previous );
previous = helperName;
return fields;
}
}
package ;
/**
* ...
* @author Skial Bainn
*/
class Main {
public static function main() new Main();
public function new() {
new A();
trace( Helper.values );
}
}
class Helper {
public static var values:Array<String> = [];
}
// Need to use an interface as opposed to putting it
// on `A` so `A` actually gets passed to the build
// macro.
@:autoBuild( Macro.build() )
interface Builder{}
class A implements Builder {
@f('1') public var a:String = 'a';
public function new() {}
}
class B extends A {
@f('2') public var b:String = 'b';
public function new() { super(); }
}
class C extends B {
@f('3') public var c:String = 'c';
public function new() { super(); }
}
class D extends C {
@f('4') public var d:String = 'd';
public function new() { super(); }
}
(function () { "use strict";
var console = (1,eval)('this').console || {log:function(){}};
function $extend(from, fields) {
function Inherit() {} Inherit.prototype = from; var proto = new Inherit();
for (var name in fields) proto[name] = fields[name];
if( fields.toString !== Object.prototype.toString ) proto.toString = fields.toString;
return proto;
}
var Helper = function() { };
var Main = function() {
new A();
console.log(Helper.values);
};
Main.main = function() {
new Main();
};
var Builder = function() { };
var A = function() {
this.a = "a";
};
A.__interfaces__ = [Builder];
var B = function() {
this.b = "b";
A.call(this);
};
B.__super__ = A;
B.prototype = $extend(A.prototype,{
});
var C = function() {
this.c = "c";
B.call(this);
};
C.__super__ = B;
C.prototype = $extend(B.prototype,{
});
var D = function() {
this.d = "d";
C.call(this);
};
D.__super__ = C;
D.prototype = $extend(C.prototype,{
});
Helper.values = ["1","2","3","4"];
A.__meta__ = { fields : { a : { f : ["1"]}}};
B.__meta__ = { fields : { b : { f : ["2"]}}};
C.__meta__ = { fields : { c : { f : ["3"]}}};
D.__meta__ = { fields : { d : { f : ["4"]}}};
Main.main();
})();
>haxe build.hxml
[ '1', '2', '3', '4' ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment