Created
January 14, 2020 20:49
-
-
Save Antriel/83276dec9fa51affebb3855ab1232dad to your computer and use it in GitHub Desktop.
Build macro to take all public functions of a class and add (lazy) singleton static function equivalents.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package antriel.macros; | |
import haxe.macro.Expr; | |
import haxe.macro.Context; | |
import haxe.macro.Expr.Position; | |
import haxe.macro.Type.ClassType; | |
using Lambda; | |
class Singletonize { | |
public static macro function build(selfInit:Bool = false):Array<Field> { | |
var fields = Context.getBuildFields(); | |
// var type:ClassType = switch Context.getLocalType() { case TInst(r, _): r.get(); case _: null; } | |
// var supFields = type.superClass == null ? [] : type.superClass.t.get().fields.get(); | |
if(fields.find(function(f) return f.name == "new") == null) {//add empty new if needed | |
fields.push({ | |
name: "new", | |
access: [], | |
kind: FFun({ args: [], ret: null, expr: macro { } }), | |
pos: Context.currentPos() | |
}); | |
} | |
for(i in 0...fields.length) switch(fields[i]) { | |
case { name: name, pos: pos, kind: FFun({ args: args, ret: ret }), access: access } | |
if(name != "new" && access.has(APublic)): | |
fields[i].name = '_${name}';//TODO possible optimization: mangle names to be shorter | |
var argsExpr:Array<Expr> = args.map(function(a) return macro $i{a.name} ).array(); | |
fields.push({ | |
name: name, | |
access: [APublic, AStatic, AInline], | |
kind: FFun({ | |
args: args, | |
ret: ret, | |
expr: macro return ${{ | |
expr: ECall({ | |
expr: EField(macro inst, '_'+name),//inst.<name> | |
pos: Context.currentPos() | |
}, argsExpr),//inst.<name>(...) | |
pos: Context.currentPos() | |
}} | |
}), | |
pos: pos | |
}); | |
case { name: "new", kind:FFun({expr:{expr:EBlock(exprs)}}) }: | |
if(!selfInit) exprs.push(macro inst = this); | |
case _: | |
} | |
//add super fields | |
// for(f in supFields) switch(f) { | |
// case { name: name, isPublic: true, kind: FMethod } | |
// } | |
// this would be a bit complex (extern overloaded methods), gonna do it manually for current need | |
fields.push({ | |
name: "inst", | |
access: [APrivate, AStatic], | |
kind: FVar(haxe.macro.TypeTools.toComplexType(TInst(Context.getLocalClass(), [])), | |
!selfInit ? null : { | |
pos: Context.currentPos(), | |
expr: ENew({ | |
pack: Context.getLocalClass().get().pack, | |
name: Context.getLocalClass().get().name | |
}, []) | |
}), | |
pos: Context.currentPos() | |
}); | |
return fields; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment