Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines
(+2)

Hey, gearing up for the Jam and playing around with Octo a bit. One thing I'm trying to get my head around is macros and when and how they're allowed to be nested. As far as I can tell, if I try a macro invocation inside a calc or byte, it will be undefined - is that expected? Is there any way I can fully expand a (possibly nested) macro call, before it gets sent to a byte, or am I picturing things completely wrong?

(+1)

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?