Skip to Content
Cloth

Static members

static makes a member belong to its file type rather than to an instance.

// Counter.co static final int32 Initial = 0; static func Next(int32 value): int32 { return value + 1; }

Other files can use Counter.Initial and Counter.Next(1). Inside Counter.co, those names can be unqualified.

Static functions

A static function has no self. It may use parameters, locals, static members, imported types, and core operations. To access an instance member, it needs an explicit object.

Calling a static function through an object is invalid. Calling an instance function through a type is invalid.

Static constants

A static field must also be final and have an initializer. Supported values are booleans, characters, fixed-width integers, floating-point numbers, and enums. Scalar expressions and references to other constants are supported by checking, native builds, and package compilation.

static final bool Enabled = true; static final int32 Limit = 16; // With Status in scope: static final Status InitialStatus = Status.Pending;

Initializers may use scalar expressions and references to other constants:

static final int32 BufferSize = 4 * 1024; static final int32 LastIndex = BufferSize - 1; static final int8 Minimum = int8(-128); static final int8 Wrapped = int8::wrap(300); static final int8 Limited = int8::sat(300); static final bool Enabled = BufferSize > 0 && LastIndex < BufferSize; static final float32 Third = 1.0 / 3.0;

Values are computed at compile time and stored as constant data. They do not run initialization code at program startup. Integer and enum constants may also be used as named switch case labels; inline case expressions remain invalid.

Forward references are allowed within normal import and visibility rules. Dependencies must be acyclic, including references in skipped boolean operands. All constants are checked, even unused or private ones. A constant reference keeps its declared type; narrowing still requires an explicit checked conversion.

Arithmetic, comparisons, boolean operations, integer bitwise operations, checked numeric conversions, and integer wrap/sat conversions are allowed. Integer arithmetic overflow, evaluated division by zero, invalid shifts, and failed checked conversions are errors. Wrapping and saturating conversion modes do not fail for range. Floating operations round to binary32/binary64 with ties to even; evaluated results must be finite. Signed zero and subnormals are preserved. Arithmetic underflow may produce zero, but a nonzero literal that rounds to zero is out of range.

Each evaluated operation must be valid, not just the final result. For example, -(-(-2147483648)) is invalid as an int32 constant: the middle negation overflows even though cancelling the signs would produce a value that fits. -2147483648 itself is a valid signed-minimum literal.

Boolean evaluation short-circuits: false && (1 / 0 == 0) is valid. Skipped operands must still have eligible syntax and types, valid literals, and acyclic dependencies. Declared function calls and value-receiver meta operations are not constant expressions; integer target conversion modes are the explicit meta-operation exception.

Mutable static fields, reference-valued static fields, aggregate constants, local constant propagation, and dynamic initialization remain unsupported.

Constant initializers are limited to 65,536 expression nodes each, nesting depth 256, and 4,096 bytes per numeric literal. Each owning package may declare 65,536 static constants and contain 1,048,576 initializer nodes in total. Parentheses and skipped operands count toward these limits.

Static fields do not occupy instance storage and cannot be accessed through objects.

Program entry point

A native program needs exactly one eligible public static Main. It may take no parameters:

static func Main(): int32 { println("Done"); return 0; }

Or it may take one non-null string[] of non-null application arguments:

static func Main(string[] arguments) { for (string argument in arguments) { println(argument); } }

An omitted return annotation or explicit void produces status zero. An int32 return supplies the process status. The entry point runs without allocating an instance. The argument array excludes the executable name and preserves argument order, empty values, whitespace, dashes, and Unicode. The runtime owns the array and strings for the complete invocation.