Macro basics: Add a function by `@:build`

I would like to generate functions via macros. So it’s almost like here in the manual, but I can’t seem to get the syntax right. (Actually what I’m trying to do with this in the end is I need to know whenever there has been write access on “meta-tagged” variables. :face_with_monocle: :stuck_out_tongue: )

(Try code here Try Haxe !)

@:build( Macro.build() )
class Test {
    static function main() {
        foo(); // should do `trace("hello")`
    }
}
import haxe.macro.Expr;
import haxe.macro.Context;

class Macro {
    
    public static function build() : Array<Field> {

        var fields = Context.getBuildFields();

        var todo : haxe.macro.Function;
        todo.expr = macro { trace("hello"); };
        todo.args = [];
        todo.ret = macro : Void;

        var f : Field = {
            name : "foo",
            pos : Context.currentPos(),
            kind : FFun( todo ),
            access : [AStatic,APublic],
            doc : null,
            meta : [],
        }

        fields.push(f);

        return fields;
    }
}

This should be really close… but it says:

Macro.hx:11: characters 9-13 : Uncaught exception field access on null
Test.hx:1: characters 1-8 : Called from here

Also compared my code to Generate dispatch code - Macros - Haxe programming language cookbook and [macro] Build macro and type expr, I try to learn all the correct syntax with macros.

Thank you! :slight_smile:

var todo : haxe.macro.Function;

The error was right after all. You forgot to assign a value, so it’s null.

You need to create a new anonymous structure (the thing with the curly braces), and it’ll need args to qualify as a Function. Everything else can be added later.

var todo : haxe.macro.Function = {
    args: []
};
todo.expr = macro { trace("hello"); };
todo.ret = macro : Void;

It’s also fine if you start with all the optional stuff, like you do with Field.

var f : Field = {
    name : "foo",
    pos : Context.currentPos(),
    kind : FFun( todo ),
    access : [AStatic,APublic], //optional
    doc : null, //optional
    meta : [], //optional
}

(Looks like you’ll get a couple minor errors once you fix this one. An extra comma after meta, and a missing semicolon after the close curly brace.)

2 Likes

Thank you!