Nitpick Macros, Metaprogramming & Attributes

Nitpick provides highly controlled compile-time metaprogramming. It rejects C-style text-substitution macros in favor of AST-aware, hygienic macros and explicit compile-time evaluation.

1. Compile-Time Macros

Macros allow for code generation and abbreviation without sacrificing type safety. * Definition: macro:name = (args) { ... }; * Invocation: name!(args);

2. Compile-Time Evaluation (comptime)

Nitpick can aggressively evaluate deterministic functions entirely at compile-time, baking the resulting values directly into the binary to save runtime cycles. * Function marking: Prefix a function with comptime func:name = ... * Invocation forcing: Wrap an expression in comptime(expr) to force the compiler to resolve it statically. If it cannot be resolved (e.g., depends on I/O), compilation fails.

comptime func:compute_hash = int32(string:input) { ... };

func:main = int32() {
    // Evaluated at compile time; runtime cost is 0.
    int32:hash = comptime(compute_hash("static_string"));
}

3. Conditional Compilation (cfg)

Like Rust, Nitpick uses cfg attributes to include or exclude code based on target architecture, OS, or custom flags. * Attribute syntax: #[cfg(target_os = "linux")] above a function or struct. * Macro syntax: cfg!(target_os = "linux") evaluates to a boolean within normal control flow.

4. Inlining Hints

While the LLVM backend makes its own inlining decisions during optimization (-O3), you can manually hint or force the compiler’s behavior: * inline : Suggests the compiler should inline this function. * noinline : Strictly forbids the compiler from inlining this function (useful for profiling or reducing binary bloat on cold paths).