Macro breakdown · August 1, 2026

Registration by Declaration

One small macro turns annotated member functions into a construct-owned command set.

Core/Macro/CommandGroup.range
macro commandGroup(): Construct {			#environment {		extension #environment.target.Declaration.identity {			enum Command {				case invalid									case #commandDeclaration.identity				}			}			function runCommandLine(): Int {				return 64			}		}	}}

1. Mark the registrable members

command targets a Function. Its empty body is intentional: it supplies typed annotation identity, rather than a runtime registry or a wrapper around the function.

2. Discover the registrations

The group macro targets the enclosing Construct. Its Declaration.members query is local to that target, and filter(all: @command) retains only functions carrying the marker. The result is a typed, ordered collection of command declarations.

3. Validate the contract

A command group with no registrations is not meaningful. Before generating anything, the macro reports a targeted diagnostic: @commandGroup requires at least one @command function.

4. Generate the closed command set

#environment emits an extension on the target construct. Within it, #commands.map runs at macro time and splices one case per registered declaration into Command. Adding @command function help() therefore adds case help; no second list can drift out of sync.

5. Dispatch is the next boundary

The generated runCommandLine() deliberately returns 64 today. It proves that the macro can generate and attach a callable entry point, but it does not yet parse argv or invoke a registered function. That later dispatch work builds on this registration slice rather than changing what registration means.