Hope you’re having a great day. Today, we’re getting into the nitty-gritty of Haxe black magic, aka Macros. But, let’s describe what macros allow you to do in Haxe.
Power Of Macros
Macros allow you to write code that generates code. That’s essentially what macros allow you to do in Haxe. Now, at the first, you may think that’s not necessary. But, there are great uses for this that can save you a lot of time. You can parse files and embed them into your code, create specific classes automatically, or add fields to your pre-existing classes. All this stuff, you may have had to do by hand, all handled by a single function in your application.
Cool right? The best part, all of this happens before your program is compiled to its final output. With that said, I’m sure you’re wondering how you could write your own. While macros are not easy and are black magic to some degree. They can help you better understand the programming language and make your life easier. So, how do you write your own macro?
Writing Your Own Build Macro
To write your own macro, first, you’ll have to make sure that your macro is executed in the macro context. In Haxe, these functions are written with the macro keyword. This function is tapped into the Haxe AST (Abstract Syntax Tree) and allows you to create expressions; expressions are just Haxe code. Here is an example from a project of mine of what a function signature for a macro would look like.
As you can see all we’ve done is add the macro function signature and what the macro should return. In this case, we are returning an array of Field type; fields are properties that exist on a class. Now, this is just the first step, here’s an example of a macro that creates a function on a command class using Aseprite’s gui.xml. See the below example.
Here’s the XML. Now, let’s get into the actual code below.
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
Now, this might seem like a lot of code, but every step is commented to give you an idea of what each section is doing. The most important parts are the buildFields. Build fields are what is attached to the class once you return from this function. They build the fields onto the class. The switch case is used to create different types for our build field at the end, allowing us to make the gif you saw at the top of this post. Now, this is a function, but the function must be applied to something; in Haxe, we use build macros like so:
Before you even compile your code, that build macro will be applied, allowing you to use those commands in your code in a type-safe manner and saving you time, because all of the code in this case will be up to date with the Aseprite spec. If you’d like to see the code this project is used in you can find it here.
I hope this serves as a soft introduction to haxe macros and there is definitely more to come. Stay tuned!! Next time, you’ll get an introduction into how to write macros that add other field types using expression reification.
For more information or any comments, leave them below and I will reply with any information that I have.