Skip to content

Custom Annotations & Scope Injection

Flame empowers systems engineers to declare custom annotations using the annotation keyword. Annotations in Flame are first-class runtime and compile-time constructs: they accept typed parameters, execute initialization logic, and return data that is automatically injected directly into the decorated function’s local scope.


[!IMPORTANT] Naming Convention: Custom annotations must begin with an uppercase letter (e.g., Logger, not logger). The compiler enforces this via a mandatory lint rule to ensure annotations remain easily distinguishable from standard functions.

You define custom annotations using the annotation keyword, specifying parameters and an explicit return type:

// Declare an annotation that returns a formatted logger prefix string
export annotation Logger(prefix: String) -> String {
return $"[{prefix}] "
}
// Declare an annotation that initializes a route configuration formula
export annotation Route(method: String, path: String) -> Formula {
return formula {
method: method,
path: path,
timestamp: 1785940000
}
}

2. Automatic Value Injection into Functions

Section titled “2. Automatic Value Injection into Functions”

When you decorate a function with a custom annotation, Flame evaluates the annotation at runtime and automatically injects the returned value directly into the function’s local scope as a mutable variable named after the annotation (accessible via lowercase or PascalCase):

@Logger("AUTH_SERVICE")
fn authenticate_user(username: String) {
// 'logger' (or 'Logger') is automatically available in local scope from @Logger!
print(logger + "Authenticating user: " + username)
// The injected variable is mutable and can be dynamically modified in scope
logger = logger + "[SECURE] "
print(logger + "Access granted.")
}
authenticate_user("admin")
[AUTH_SERVICE] Authenticating user: admin
[AUTH_SERVICE] [SECURE] Access granted.

3. Mutable State & Complex Formula Injection

Section titled “3. Mutable State & Complex Formula Injection”

Custom annotations can return complex formulas, structs, or state containers, making them invaluable for middleware pipelines and contextual dependency injection:

export annotation Context(service_name: String) -> Formula {
return formula {
service: service_name,
request_count: 0
}
}
@Context("PAYMENT_GATEWAY")
fn process_transaction(amount: Float) {
// Access formula properties directly from the injected 'context' variable
context.request_count += 1
print($"Service: {context.service}, Requests: {context.request_count}, Amount: ${amount}")
}
process_transaction(99.95)

Flame also comes packed with native annotations for testing (@Test, @Setup, @Cleanup) and declarative CLI building (@Cli, @Command).

To learn how to use @Cli and @Command to assemble powerful interactive system utilities and subcommands with zero boilerplate, visit the comprehensive reference on Built-in Annotations & CLI Builder.