I've been practising metaprogramming with Nim recently.
I've not found macros to be simple, or at least not as simple as the phrase 'code substitution' itself suggests.
Thus I took extensive notes while doing these exercises, which I leave here in their entirety. I hope they will help your understanding should you be newly dipping your toes in the topic of macros. (Leave a note if you find them helpful!)
Each exercise builds on earlier knowledge, so you may want to study/try them in order. I've verified the example code to work, but let me know otherwise.
Beginner Level: quote do
& backticks
info(expr) macro - Print the type/value of any expression.
double(x) macro - Take an identifier and generate code that doubles its value in-place.
logvars(a, b, c) macro - Log several variables at once.
Intermediate Level: basic AST use
assertPositive(expr) macro - Check if the expression is > 0.
swap(a, b) macro - Swap the values of two variables.
timed(expr) macro - Measure and print how long an expression takes to run.