package; #if macro import haxe.macro.Context; import haxe.macro.Expr; #end /** * CompilationOption allows us to use compile-time variables for advanced conditional compilation. */ class CompilationOption { #if macro /** * Internal storage of the options. */ static var storage = new Map(); #end /** * Set `key` to `value`. * * For simplicity `value` can only be constant Bool/Int/Float/String or null. * Array and structures are also possible, check: * http://haxe.org/manual/macros#constant-arguments * * Set `force` to true in order to override an option. * But be careful overriding will influenced by compilation order which may be hard to predict. */ @:overload(function (key:String, value:Bool, ?force:Bool = false):Void{}) @:overload(function (key:String, value:Int, ?force:Bool = false):Void{}) @:overload(function (key:String, value:Float, ?force:Bool = false):Void{}) @:overload(function (key:String, value:String, ?force:Bool = false):Void{}) macro static public function set(key:String, value:Dynamic, ?force:Bool = false) { if (!force && storage.exists(key)) throw key + " has already been set to " + storage.get(key); storage.set(key, value); return macro {}; //an empty block, which means nothing } /** * Return the option as a constant. */ macro static public function get(key:String):Expr { return Context.makeExpr(storage.get(key), Context.currentPos()); } /** * Tell if `key` was set. */ macro static public function exists(key:String):ExprOf { return Context.makeExpr(storage.exists(key), Context.currentPos()); } /** * Removes an option. Returns true if there was such option. */ macro static public function remove(key:String):ExprOf { return Context.makeExpr(storage.remove(key), Context.currentPos()); } /** * Dump the options as an object with keys as fields. * eg. trace(CompilationOption.dump()); */ macro static public function dump():ExprOf { var obj = {}; for (key in storage.keys()) { Reflect.setField(obj, key, storage.get(key)); } return Context.makeExpr(obj, Context.currentPos()); } }