COMMUNITY

Macro iterate over another macro function

(Aartzrc) #1

I have some functions that generate arrays of lookup data at run time. It would be better to have them created at compile time via macros so I tried to convert them to macro code. The first layer was easy but I’m having trouble understanding how to call a macro from another macro to continue the ‘chaining’ of data build functions.

Example usage here that pre-builds a ‘bit array’ at compile time:
http://try-haxe.mrcdk.com/#68B2b

When the var bitBlock = BitBuildMacro.getBitBlock(2); line is uncommented the compiler complains:

BitBuildMacro.hx:13: characters 52-57 : haxe.macro.Expr should be Int
BitBuildMacro.hx:13: characters 52-57 : { pos : haxe.macro.Position, expr : haxe.macro.ExprDef } should be Int
BitBuildMacro.hx:13: characters 52-57 : For function argument 'w'

Although an Int is passed in it gets converted to an expression when passed to the nested function call, so I need to de-expression-ify that or something? And if I allow BitBuildMacro.getBitRow to accept Expr does that break calling it directly with Int values?

Thanks for any help!

(Rudy Ges) #2

Macro functions return expressions (haxe.macro.Expr), not Int, Bool, etc.

You’ll have to separate the creation of the macro expression and the logic itself, to be able to call getBitBlock from getBitBlocks, etc.

This doesn’t return the results you were expecting, but it seems like a problem in the logic you provided which I did not modify (except renaming points to blocks because it didn’t exist): http://try-haxe.mrcdk.com/#90831 (updated)

(Dan Korostelev) #3

Actually, macros can accept basic types directly, if the expression passed to the call is constant: https://haxe.org/manual/macro-constant-arguments.html

1 Like
(Rudy Ges) #4

Oh, yeah. Still have to deal with the expr vs value return, though.

(Aartzrc) #5

Ah, fantastic work and thanks. I see how it should be structured now. The data should be kept ‘pure’ until the very end when it gets dumped out as an expression. I had only used simple single function macros before so this threw me off.

The #if macro / #end around the sub-functions is just to keep them from being called outside the macro? I can see a way that a ‘pre-build’ of some data at compile time, and then a ‘lazy build’ during run time would come in handy by re-using the same _getBitxx calls.