Octo programs are assembled in one long linear pass. There are a few minor exceptions to this, like forward-referenced labels, but the conceptual model is not recursive or scoped. It works very much like a Forth.
A program is a sequence of tokens. Each statement, like "sprite" or "i := NNN", consumes some number of tokens from that sequence. The name of a previously-declared macro is a statement, (an invocation) which consumes zero or more tokens (as arguments), and then dumps a list of tokens (the macro body) into the program's token sequence, substituting arguments as it goes. Another way to think about it is that macro invocations are always the head of a statement.
Constant expressions (inside { }) are their own separate domain from normal assembly, and macros usually only interact with them while substituting arguments as part of their expansion process. It's also worth noting that bindings created by ":calc" are global (much like aliases), and can be redefined as many times as needed over the course of assembly; they are not evaluated specially in relation to macro bodies or constrained to the scope of a macro where they appear.
Does that all make sense? Could you provide more context for what you're trying to accomplish?