Using Haxe macros to instantiate a class with parameters

Building fields manually like that is somewhat tedious - I'd recommend to use class reification instead, where you can express the field as regular Haxe code:

macro class {
    static var _pool = new Pool(/* clazz */);
}

This bypasses the "Invalid number of type parameters" issue entirely - just let type inference do the trick and omit the type parameter in new Pool().

The argument for the constructor call is of course variable, so we still need to use some expression reification. exp.Entity is a field expression, so we have to use $p{}. We can construct the type path needed for it by combining clazz.pack and clazz.name:

class PoolBuilder {
    static public macro function build():Array<Field> {
        var fields = Context.getBuildFields();
        var clazz = Context.getLocalClass().get();
        var path = clazz.pack.concat([clazz.name]); // ["exp", "Entity"]

        var extraFields = (macro class {
            static var _pool = new Pool($p{path});
        }).fields;
        return fields.concat(extraFields);
    }
}

This generates the following code (as can be seen in exp/Entity.dump with -D dump=pretty):

static var _pool:exp.Pool<exp.Entity> = new exp.Pool(exp.Entity);

If you prefer adding fields by fields.push({...}) instead of using class reification, you can trigger type inference by using null as a type in FVar(null, pool):

static public macro function build() : Array<Field> {
    var fields = Context.getBuildFields();
    var clazz = Context.getLocalClass().get();

    var path = clazz.pack.concat([clazz.name]); // ["exp", "Entity"]
    var pool = macro new exp.Pool($p{path});
    fields.push({
        name: "_pool",
        access: [APrivate, AStatic],
        pos: Context.currentPos(),
        kind: FVar(null, pool)
    });

    return fields;
}

This is using @gama11 trick for path. This generates the exact same code as @gama11 answer (and can be checked in the same way).

Tags:

Macros

Haxe