Annotations & Metaprogramming (std.annotation)
The std.annotation module delivers Flame’s built-in metaprogramming engine. It provides custom annotations with deep reflection capabilities, allowing them to inspect declarations, extract callable function references, and dynamically wrap or transform function behavior.
1. Quick Start
Section titled “1. Quick Start”Inside any custom annotation declaration, call annotation.context() to retrieve the current AnnotationContext:
import std.annotation
annotation Route(path: String) { let ctx = annotation.context()
print($"Decorated symbol: {ctx.target.name}") print($"Declaration kind: {ctx.target.kind}") print($"Compiler version: {ctx.compiler.version}") print($"Target platform: {ctx.build.platform}")}
@Route(path = "/users")fn list_users() -> String { return "users"}2. API Reference
Section titled “2. API Reference”annotation.context() -> AnnotationContext
Section titled “annotation.context() -> AnnotationContext”Returns the active AnnotationContext populated with metadata about the annotated target declaration and the compilation environment.
import std.annotation
annotation Example { let ctx: AnnotationContext = annotation.context()}AnnotationContext
Section titled “AnnotationContext”The root metadata object returned by annotation.context():
export struct AnnotationContext { target: TargetMetadata compiler: CompilerInfo module: ModuleInfo build: BuildInfo}| Field | Type | Description |
|---|---|---|
target |
TargetMetadata |
Reflection metadata and operations on the decorated declaration. |
compiler |
CompilerInfo |
Information about the active Flame compiler toolchain. |
module |
ModuleInfo |
Identification and path of the current module file. |
build |
BuildInfo |
Compilation target, release mode, platform OS, and architecture. |
TargetMetadata
Section titled “TargetMetadata”Represents the symbol (function, struct, enum, or variable) to which the annotation is applied:
export struct TargetMetadata { name: String kind: String parameters: [ParameterInfo] return_type: String annotations: [AnnotationInfo]}| Property | Type | Description |
|---|---|---|
name |
String |
The identifier of the annotated symbol (e.g. "fetch_user"). |
kind |
String |
The declaration kind: "function", "struct", "enum", or "variable". |
parameters |
[ParameterInfo] |
An ordered list of parameter metadata (for functions). |
return_type |
String |
Return type signature string (e.g. "String", "Int", or "Nil"). |
annotations |
[AnnotationInfo] |
Array of all annotations attached to this target declaration. |
Methods on TargetMetadata
Section titled “Methods on TargetMetadata”ref() -> Unknown
Section titled “ref() -> Unknown”Returns a callable reference to the annotated function.
- When invoked,
ref()executes the target function’s underlying body without re-triggering attached annotations (preventing recursive re-entrancy). - Ideal for web router registration, event dispatchers, and task queues.
annotation Route(path: String) { let ctx = annotation.context() let handler = ctx.target.ref() // handler can now be stored in a router table and called on demand}transform(transformer: Unknown) -> Unknown
Section titled “transform(transformer: Unknown) -> Unknown”Wraps or transforms the annotated function. Flame supports two transformer signatures:
-
Direct Interceptor Closure: Receives the original callable reference as its first argument, followed by the target function’s parameters:
ctx.target.transform((ref, arg1: String) {print($"Before calling {ctx.target.name}")let result = ref(arg1)print($"After calling {ctx.target.name}")return result}) -
Higher-Order Factory Closure: Receives the original callable reference and returns a replacement closure:
ctx.target.transform((ref) {return (arg1: String) {let result = ref(arg1)return $"[WRAPPED: {result}]"}})
ParameterInfo
Section titled “ParameterInfo”Describes a parameter declared on the annotated function:
export struct ParameterInfo { name: String type: String has_default: Bool is_ref: Bool is_mut: Bool}| Field | Type | Description |
|---|---|---|
name |
String |
Parameter name identifier. |
type |
String |
Type annotation as written in code (or "Unknown" if untyped). |
has_default |
Bool |
Whether a default value expression is specified. |
is_ref |
Bool |
true if passed by reference (&). |
is_mut |
Bool |
true if mutable (mut or &mut). |
AnnotationInfo
Section titled “AnnotationInfo”Describes an annotation attached to the declaration:
export struct AnnotationInfo { name: String args: [String]}| Field | Type | Description |
|---|---|---|
name |
String |
Annotation name (e.g. "Route", "Logged"). |
args |
[String] |
List of argument expressions supplied to the annotation. |
CompilerInfo
Section titled “CompilerInfo”Reflects the executing Flame compiler:
export struct CompilerInfo { name: String version: String}| Field | Type | Description |
|---|---|---|
name |
String |
Always "flame". |
version |
String |
Toolchain semver string (e.g. "0.5.7"). |
ModuleInfo
Section titled “ModuleInfo”Reflects the current source file module:
export struct ModuleInfo { name: String filepath: String}| Field | Type | Description |
|---|---|---|
name |
String |
Name of the current file or module. |
filepath |
String |
File system path to the declaring .fm file. |
BuildInfo
Section titled “BuildInfo”Reflects target platform compilation settings:
export struct BuildInfo { target: String mode: String platform: String arch: String features: [String]}| Field | Type | Example Values | Description |
|---|---|---|---|
target |
String |
"native", "web", "wasm" |
Compilation target architecture. |
mode |
String |
"debug", "release" |
Active build optimization mode. |
platform |
String |
"linux", "darwin", "windows" |
Host operating system. |
arch |
String |
"x86_64", "aarch64" |
CPU architecture. |
features |
[String] |
["threads", "simd"] |
Enabled compiler feature flags. |
3. Real-World Use Cases
Section titled “3. Real-World Use Cases”Use Case 1: Web Router Handler Registration (target.ref())
Section titled “Use Case 1: Web Router Handler Registration (target.ref())”In modern backend frameworks, annotations are used to register route endpoints directly into a routing table without manual boilerplate:
import std.annotation
let route_table: [Formula] = []
export annotation GET(path: String) { let ctx = annotation.context() let handler = ctx.target.ref()
route_table.push(formula { method: "GET", path: path, name: ctx.target.name, handler: handler })}
// Declare endpoints@GET(path = "/api/v1/health")fn get_health() -> String { return "ok"}
@GET(path = "/api/v1/users")fn get_users() -> String { return "{\"users\": [\"Alice\", \"Bob\"]}"}
// Dispatch incoming requestfn dispatch_request(path: String) -> String { for route in route_table { if route.path == path { let handler = route.handler return handler() } } return "404 Not Found"}
print(dispatch_request("/api/v1/health")) // Output: "ok"Use Case 2: Function Wrapping & Interception (target.transform())
Section titled “Use Case 2: Function Wrapping & Interception (target.transform())”Use ctx.target.transform() to wrap functions with logging, authentication checks, or result formatting:
import std.annotation
export annotation Logged { let ctx = annotation.context()
ctx.target.transform( (ref, msg: String) { print($"[AUDIT START] Invoking '{ctx.target.name}' with payload: {msg}") let result = ref(msg) print($"[AUDIT END] '{ctx.target.name}' completed.") return $"[LOGGED: {result}]" } )}
@Loggedfn submit_order(order_id: String) -> String { return $"Order #{order_id} processed"}
let res = submit_order("9942")print(res)// Output:// [AUDIT START] Invoking 'submit_order' with payload: 9942// [AUDIT END] 'submit_order' completed.// [LOGGED: Order #9942 processed]Use Case 3: Performance Timing & Profiling
Section titled “Use Case 3: Performance Timing & Profiling”Automatically time any function execution with zero boilerplate:
import std.annotationimport std.time
export annotation Benchmark { let ctx = annotation.context()
ctx.target.transform( (ref, n: Int) { let start = time.now() let result = ref(n) let elapsed = time.since(start) print($"[BENCHMARK] {ctx.target.name}({n}) finished in {elapsed}ms") return result } )}
@Benchmarkfn compute_fibonacci(n: Int) -> Int { if n <= 1 { return n } return compute_fibonacci(n - 1) + compute_fibonacci(n - 2)}Built-in First-Class @Benchmark Harness
Section titled “Built-in First-Class @Benchmark Harness”Flame provides a built-in, first-class @Benchmark annotation and dedicated CLI runner (flame bench). Unlike a simple timing wrapper, the benchmark engine performs automated warmup runs, executes repeated measurement iterations using a zero-allocation monotonic hardware clock, and outputs detailed statistical profiles.
Declaring Benchmarks
Section titled “Declaring Benchmarks”Decorate any parameterless function with @Benchmark:
@Benchmarkfn json_parse() { let data = parse_json(input)}Configurable Benchmark Options
Section titled “Configurable Benchmark Options”Pass configuration parameters directly to @Benchmark:
| Parameter | Type | Default | Description |
|---|---|---|---|
warmup |
Int |
10 |
Number of unmeasured warmup iterations to prime caches and branch predictors. |
iterations |
Int |
100 |
Number of timed measurement iterations. |
group |
String |
"" |
Grouping identifier for automated comparative benchmark tables. |
name |
String |
Function Name | Custom human-readable label for reporting. |
@Benchmark( warmup: 100, iterations: 1000, group: "json", name: "Standard JSON Parser")fn benchmark_standard_json() { let parsed = json.read("dataset.json")}
@Benchmark( warmup: 100, iterations: 1000, group: "json", name: "Fast Streaming JSON")fn benchmark_fast_json() { let parsed = json.fromJson(raw_bytes)}Running Benchmarks via CLI
Section titled “Running Benchmarks via CLI”Execute every benchmark across your project using:
flame benchOr target a specific benchmark file:
flame bench tests/json_bench.fmStatistical Report Output
Section titled “Statistical Report Output”Flame’s benchmark engine generates comprehensive statistical metrics for every benchmark:
[PASS] @Benchmark benchmark_standard_json Benchmark: Standard JSON Parser
Warmup 100 iterations Iterations 1,000 iterations
Time total 182.43 ms avg 18.24 µs min 15.81 µs max 31.92 µs p50 17.92 µs p95 21.44 µs p99 26.73 µs
Throughput 54,812 ops/sec
Memory allocated 2.41 MB per op 246 B
Result: PASS
────────────────────────────────────────────────────────── Benchmark Group: json Benchmark time/op ops/sec ────────────────────────────────────────────────────────── Fast Streaming JSON 11.02 µs 90,744 Standard JSON Parser 18.24 µs 54,812 ────────────────────────────────────────────────────────── improvement +65.5% ──────────────────────────────────────────────────────────Use Case 4: Struct & Model Reflection
Section titled “Use Case 4: Struct & Model Reflection”Annotations can decorate structs and enums to inspect schema structures for ORMs or serializers:
import std.annotation
let registered_entities: [Formula] = []
export annotation Entity(table: String) { let ctx = annotation.context()
registered_entities.push(formula { symbol: ctx.target.name, kind: ctx.target.kind, table: table })}
@Entity(table = "accounts")struct Account { id: Int email: String is_active: Bool}
print($"Registered table: {registered_entities[0].table} for struct {registered_entities[0].symbol}")// Output: Registered table: accounts for struct AccountUse Case 5: Platform & Architecture Guards
Section titled “Use Case 5: Platform & Architecture Guards”Use ctx.build and ctx.compiler to validate target platform requirements at declaration time:
import std.annotation
export annotation LinuxOnly { let ctx = annotation.context()
if ctx.build.platform != "linux" { panic($"Function '{ctx.target.name}' is only supported on Linux! Current OS: {ctx.build.platform}") }}
@LinuxOnlyfn initialize_epoll_driver() { print("Linux epoll driver initialized.")}4. Summary
Section titled “4. Summary”| Feature | Description |
|---|---|
annotation.context() |
Retrieves active AnnotationContext (restricted to annotation declarations). |
ctx.target.ref() |
Extracts a callable function reference without re-triggering annotations. |
ctx.target.transform() |
Wraps target functions with direct interceptor or factory closures. |
ctx.target.* |
Introspects target symbol name, kind, parameters, return_type, and annotations. |
ctx.compiler.* |
Accesses toolchain name and version. |
ctx.build.* |
Inspects target architecture, OS platform (linux, darwin, windows), and build mode. |
