Skip to content

Instantly share code, notes, and snippets.

@Simn

Simn/Main.hx Secret

Created September 3, 2013 12:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Simn/8ae509cc3824099c1567 to your computer and use it in GitHub Desktop.
Save Simn/8ae509cc3824099c1567 to your computer and use it in GitHub Desktop.
Generic builder macro
@:genericBuild(MyMacro.build())
class MyValue<T> {
var value:T;
public function new() { }
public function set(t:T) {
value = t;
}
public function get():T {
return value;
}
}
class Main {
static public function main() {
var x = new MyValue<String>();
x.set("foo");
trace(x.get());
}
}
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.Tools;
using Lambda;
class MyMacro {
public static function build():Type {
var t = Context.getLocalType();
switch(t.follow()) {
case TInst(cr, tl):
var c = cr.get();
var params = c.params;
function mapType(t:Type) return switch(t.follow()) {
case TInst(cr, []) if(switch(cr.get().kind) { case KTypeParameter(_): true; case _: false; }):
t.applyTypeParameters(params, tl);
case t:
t.map(mapType);
}
function mapExpr(e:TypedExpr) return e;
function mapVar(v:TVar) {
return {
capture: v.capture,
id: v.id,
extra: v.extra,
name: v.name,
t: mapType(v.t)
}
}
function convertField(cf:ClassField):Field {
var kind = switch(mapType(cf.type.follow())) {
case TFun(args, ret):
var e = switch(cf.expr().mapWithType(mapExpr, mapType, mapVar).expr) {
case TFunction(tf): Context.getTypedExpr(tf.expr);
case _: throw false;
}
FFun({
args: args.map(function(arg) return {
name: arg.name,
opt: arg.opt,
type: arg.t.toComplexType(),
value: null
}),
ret: cf.name == "new" ? null : mapType(ret).toComplexType(),
expr: e,
params: []
});
case t:
FieldType.FVar(t.toComplexType());
}
return {
name: cf.name,
pos: cf.pos,
access: cf.isPublic ? [APublic] : [],
kind: kind
}
}
var fields = c.fields.get();
if (c.constructor != null) fields.push(c.constructor.get());
var name = cr.toString() + "_" + tl.map(function(t) return t.follow().toString()).join("_");
Context.defineType({
name: name,
pack: [],
pos: Context.currentPos(),
meta: [],
params: [],
isExtern: false,
kind: TDClass(),
fields: fields.map(convertField)
});
return Context.getType(name);
case _: throw false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment