Annotations
Defining annotations, annotation parameter schemas, construct allowlists, execution annotations, and FFI annotation families.
Annotations are one of Kira's defining language mechanisms.
Defining Annotations
Kira annotations are first-class declarations. An annotation declaration gives the annotation a source-level identity and, optionally, a parameter schema:
annotation State {
}
annotation Attribute {
parameters {
index: Int
}
}
annotation InputMapping {
parameters {
priority: Int = 0
blocksLowerPriorityMappings: Bool = false
}
}This keeps annotations lightweight. The declaration says what parameters an annotation accepts; it does not say where the annotation is globally valid or what semantic behavior it performs.
Parameter Blocks
The first version supports one declaration subblock:
parameters {
name: Type
otherName: Type = defaultValue
}Supported parameter types are Bool, Int, Float, and String. A parameter without a default is required. A parameter with a default is filled by semantics when the annotation is applied.
Documentation is not modeled as an annotation. Use /// comments immediately above the declaration or member they describe:
/// Horizontal position in points.
var x: Float = 0.0The compiler validates that applied annotations exist, that required parameters are present, that unknown parameter names are rejected, and that argument values match the declared parameter types.
Applying Annotations
The current frontend understands these annotation use styles:
| Style | Example |
|---|---|
| Bare | @Main |
| Namespaced | @FFI.Pointer |
| Argument form | @InputMapping(10) |
| Named argument form | @InputMapping(priority: 10) |
| FFI metadata block | @FFI.Callback { abi: c; params: [I64, RawPtr]; result: I64; } |
User-defined annotation parameters are supplied with parentheses. The FFI metadata block form is the existing compiler interop path and is separate from first-version annotation parameter declarations.
These fail when the declarations above are in scope:
@Attribute
var position: Float = 0.0
@Attribute("zero")
var position: Float = 0.0
@State(1)
var isPressed: Bool = false@Attribute requires index: Int, "zero" is a String, and @State declares no parameters.
Execution Annotations
Three annotations have direct compiler meaning for execution:
@Main@Runtime@Native
They choose entrypoints and execution placement, and the semantics layer rejects duplicates or conflicting combinations.
Printable
Foundation defines Printable as a compiler-known construct for custom print rendering:
import Foundation
@Printable
struct UserName {
let value: String
function onPrint() -> String {
return value
}
}When print(value) receives a named class or struct annotated with @Printable, lowering dispatches through that type's onPrint() -> String method. Primitive values keep the ordinary builtin print path.
If a @Printable type does not provide onPrint() -> String, semantics raises KSEM102.
Documentation Comments
Kira documentation uses consecutive /// comments:
/// Horizontal position in points.
var x: Float = 0.0Documentation comments are part of the lexical surface, while annotations remain source-level metadata for behavior and validation.
FFI Annotation Families
The current compiler also gives semantic meaning to these interop annotations:
@FFI.Extern@FFI.Callback@FFI.Pointer@FFI.Struct@FFI.Alias@FFI.Array
Those annotations are covered in more detail in Interop and FFI.
Construct-Declared Annotation Use
Construct definitions declare which already-declared annotations are valid in construct forms:
annotation State {
}
annotation Binding {
}
construct Widget {
annotations {
@State;
@Binding;
@Env;
}
}That split is intentional:
annotationdeclares the annotation identity and parameter schemaconstructdeclares which annotations are meaningful in a construct domain- construct semantics remain the source of behavior
Annotations can declare direct target restrictions with readable targets: ... entries, and reusable generated behavior is composed through capabilities:
capability Labeling {
generated {
overridable function label() -> String {
return "item"
}
}
}
annotation GameItem {
targets: class
uses Labeling
}Generated members are explicit through generated { ... }, and class-side replacements use normal override function ... syntax when the generated member is marked overridable.