Like Lisp macros, basically. I don't know if I'd try for Schemely hygienic macros, but maybe. At least to begin with, I'll just do good old Lisp 1.5 eval-it-twice macros. That is, you evaluate the macro call, and then you evaluate what the macro returns.
We already have half of what macros do, because we have the ability to declare a procedure input to be of an Unevaluated type (Any Unevaluated, Number Unevaluated, Boolean Unevaluated). Now what we need is a way for the macro to report a script which will then be evaluated in the caller's environment.
In Lisp this is really easy to build because a program is just a list, i.e., it's data and you can easily tear it apart and put it together. That's not the case in Snap!, so I need to use something like @pumpkinhead's library to convert between scripts and syntax trees.