Variables
Declaration syntax
Section titled “Declaration syntax”A variable is declared as <type> <name> = <initializer>:
int age = 25float rate = 1.5bool active = truestring name = "Pluvial"auto count = 10 # inferred as intauto title = "Rain" # inferred as string- The initializer is required — there is no default initialization.
- With an explicit type, the initializer’s static type must match exactly.
int x = 1.5is a compile error (no implicit conversion).
The auto keyword
Section titled “The auto keyword”auto infers the variable’s type from the initializer and then fixes it permanently.
auto is not dynamic typing:
auto x = 10x = 20 # OKx = "hello" # compile error — the type is fixed as intauto a = null is a compile error: null alone does not determine an element type. Write
int? a = null instead.
Assignment and reassignment
Section titled “Assignment and reassignment”- Reassignment is allowed only when the type matches.
- Assignment is a statement, not an expression —
y = x = 1is invalid.
Scope and shadowing
Section titled “Scope and shadowing”- A block
{ }introduces a new lexical scope. Variables declared inside a block are not visible outside it. - Redeclaring a name in the same scope is an error.
- Shadowing is allowed in nested scopes: an inner block may declare a new variable with the same name as one in an outer scope. The inner one is a distinct new variable that covers the outer one; leaving the block restores the outer variable unchanged. Name resolution searches from the innermost scope outward (innermost-wins).
At runtime, top-level variables live in a globals array, while block-local variables live
on the value stack (frame-relative slots). The garbage collector marks the entire value
stack as a root, so locals are protected automatically.
Compound (augmented) assignment
Section titled “Compound (augmented) assignment”The operators += -= *= /= %= **= &= |= ^= <<= >>= are pure syntactic sugar: x op= e
lowers to x = x op e. The base operator’s type rules and error messages apply unchanged —
int += float is a compile error, string += int is an error, and bitwise forms are
int-only.
There are three legal left-hand sides:
- A variable —
x += 1. The readonly check is identical to plain=, sofor-loop variables,matchbindings, andselfcannot be assigned even with an augmented operator ("cannot assign to for-loop variable 'x'", and so on). - An array element —
a[i] += 1. The receiver and index are evaluated once, soa[get_idx()] += 100callsget_idx()exactly once. - A struct field —
obj.field += 1, including nested paths such aso.inner.v += 1.
Not currently supported (deferred):
- Augmented assignment on a
mapindex —m[k] op= e— because a map read returnsV?and needs narrowing. - Chained forms —
x += y += 1.