Preprocess
A # at the start of a line triggers a preprocessing directive: before compilation, source is trimmed by symbol conditions. A good fit for forks like “the same code, with the editor build carrying an extra set of debug functions”.
Conditional Blocks
#if EDITOR
func Mode() -> string => "editor";
#elif SHIPPING
func Mode() -> string => "shipping";
#else
func Mode() -> string => "default";
#endif
func main() -> int
{
print(Mode());
return 0;
}defaultThe host does not define EDITOR, so it evaluates as 0/false and the #else branch applies; Mode() returns “default”. Symbols are injected by the host (DefinedSymbols / SymbolValues); in a direct CLI run none are defined.
The Directive Set
| Directive | Kind | Form |
|---|---|---|
#if expr | block | starts a conditional block (occupies the whole line) |
#elif expr | block | a branch |
#else / #endif | block | fallback / end |
#SYM | prefix | symbol defined → activates the next declaration/statement |
#!SYM | prefix | negated |
#[expr] | prefix | parenthesized expression |
Prefix forms attach directly in front of a single declaration or statement and trim only that one:
#DEBUG
public val Verbose: bool = true;Undefined Symbols Always Warn
Every symbol in an #if / #elif / prefix directive that is not in the host’s symbol set raises an MS1214 warning; this warning is what keeps such mistakes visible. Numeric symbols can take part in expression comparisons (#elif DEBUG >= 2).
Notes
#triggers only at the start of a line; a#mid-line is an ordinary character.- Preprocessing runs at the very front of compilation; trimmed-out code never reaches the parser, so each side of a fork only needs to stand on its own syntactically.
