Skip to Content

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; }
default

The 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

DirectiveKindForm
#if exprblockstarts a conditional block (occupies the whole line)
#elif exprblocka branch
#else / #endifblockfallback / end
#SYMprefixsymbol defined → activates the next declaration/statement
#!SYMprefixnegated
#[expr]prefixparenthesized 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.
Last updated on October 11, 2026