Declarations and Scope
This page defines common declaration and lookup rules. See Language Basics for normal usage.
Variables
A variable declaration starts with var and normally includes an explicit
type. Restricted declaration type inference is available with ? when the
initializer has an independently determined typed-pointer, structure, or object
reference type.
var count : int = 0
var ready : bool
var registers : ? = ^SRegisters(address)
var values : [?]int = [1, 2, 3]
An omitted initializer default-initializes the value according to its type.
An inferred declaration requires an initializer. Integer, floating-point, null,
raw-pointer, and all other unlisted types are not eligible. [?]T remains the
separate syntax for inferring a fixed array's length.
Object fixed-storage declarations use <- and are described in
Objects and Properties.
References
A local alias is declared with ref and must bind to compatible storage.
Assignment through the alias writes the referenced value.
var value : int = 10
ref alias = value
alias = 20
A reference is not a nullable pointer value. Function parameter reference modes are defined in Functions.
Constants
Constants use const, have a declared type, and require a compile-time constant
initializer.
const BUFFER_SIZE : int = 4096
const REGISTERS : ? = ^SRegisters(0x40000000)
? follows the same restricted inference rules as variables. Inference does
not relax the requirement for a valid constant expression and is not supported
in a grouped const(type): ... endconst header.
Related constants of the same type can share a declaration block. The block does not introduce a scope, and later members can reference earlier members.
const(uint32):
FLASH_BASE = 0x08000000
FLASH_BANK1_END = FLASH_BASE + 0x7FFF
SRAM_BASE = 0x20000000
endconst
Type Declarations
type introduces a type alias. struct, enum, and object introduce compound
types with their own declaration rules.
type TSize = uint
type FTransform = function(value : int) -> int
Aliases do not create a distinct runtime type. Enumerations do.
Visibility and Declaration Order
Module declarations before implementation form the public interface. Later
declarations are private implementation details unless they implement a public
declaration. Object declarations use public and private member groups.
Names must be declared before uses that require their complete meaning, except where the language explicitly permits a public declaration followed by an implementation.
Name Lookup
Unqualified lookup starts in the innermost active scope and proceeds outward.
Imported symbols may participate when a use merges them into the scope.
Namespace qualification uses @name.Symbol; @. selects the current module's
global scope.
Object methods intentionally prioritize object members and restrict implicit
access to outside value symbols. Use @.Name, an imported namespace, or an
allowed method-local use to select module-scope values explicitly. Type names
remain available for declarations and casts.
Detailed import, conflict, and reexport behavior is defined in Modules and Packages.
Initialization
Primitive and aggregate values can be initialized with type-appropriate
expressions. {} performs zero/default initialization for supported aggregate
types. Assignment is a statement and does not itself produce a value.