Equivalence check.
See Node.opIndex.
Semantic hash. Depends only on this macro node's id.
Provides an iterator over this node's in-edges.
Provides an iterator over this node's out-edges.
Frees all resources allocated by this node and sets it to an uninitialized state.
Initializes a macro node, must be later disposed.
Links this macro node to its external definition.
Edges (of any kind) which point into this node.
Edges (any kind) which point out from this node.
Post-move adjusts in-edge slots' owner pointer.
Macro nodes represent Gyre subgraphs defined elsewhere (external to the graph where they're being used). A Gyre (sub)program is said to be concrete if it contains no macro nodes, otherwise it is abstract. This part of Gyre's design is influenced by ANDF, which enabled IR "producers" (front ends) to pass along unexpanded macros to IR "installers" (back ends).
Abstract Gyre graphs can't be directly compiled to machine code, since backends wouldn't be able to lower macro nodes without their definition. Still, having abstract Gyre graphs has its uses. One example is when the compiler doesn't (yet) have the information it needs to concretize a graph: it may lack target-specific information which is required for code generation. Another one is to enable more target-specific optimizations: if every "high-level" operation was lowered to a generic implementation using only primitive nodes, back ends with special support for that operation wouldn't (easily) be able to re-discover it in order to generate specialized code. "Premature lowering is the root of all evil", and macro nodes aim to avoid it.
Without any other rules, macro nodes would probably end up harming portability: abstract Gyre graphs could only be compiled by back ends providing all the right macro definitions. RULE: Thus, a portable Gyre program must carry definitions for all of its macros (and macros cannot be recursive). Such definitions must allow any compliant Gyre back end to correctly compile programs by concretizing them through a simple process of macro expansion (i.e. substituting macro nodes for their definition until there are no more macro nodes in the graph). The intention is that macros must always have the same semantics, but a Gyre compiler with intimate knowledge of a specific macro can do a better job at optimizing programs using it.
Just like linker-resolved symbols, macro nodes need to be uniquely identified. It is this identification which allows the compiler to, later in the compilation pipeline, substitute the macro node with (i.e. "link in") its definition.
Gyre's mechanism for structural abstraction, the macro node.
One can imagine macro nodes as holes: parts of a Gyre program which will only be filled later, like extern definitions in a C-like language, which the linker is responsible for resolving.