Memory and errors
Classes, strings, and arrays use managed references. The runtime traces reachable objects and reclaims unreachable allocations. Ordinary Cloth programs do not manually free memory, maintain reference counts, or annotate ownership.
The current collector is a precise, non-moving mark-and-sweep collector. The compiler supplies reference information, including references contained inside struct fields and array elements. Cyclic object graphs can be reclaimed when unreachable.
Values and sharing
Class and array assignment shares a reference. String references share immutable text. Struct assignment copies inline fields recursively while sharing managed references stored inside those fields.
final prevents rebinding; it does not recursively freeze referenced objects.
See structs for inline read-only behavior.
Collection timing is not deterministic destruction. No destructor or finalizer contract is exposed by the current language. Collector diagnostics are runtime facilities for testing and embedding, not source-language functions.
Typed errors
An error file defines a managed error type. It derives from the
compiler-provided Error root unless another error base is named.
// InvalidUser.co
error {
InvalidUser(string message): Error(message) {}
}Error is abstract and supplies the public final string Message field.
Errors otherwise follow class rules: they may contain fields and functions,
implement interfaces, derive from one error, and use capitalization for
visibility. Construct an error with its file type name; Cloth does not use
new.
The standard-library prelude provides four general and operation-specific errors:
ArgumentErrorreports a value a caller is not permitted to supply.StateErrorreports an operation that is invalid for the receiver’s current state.IoErrorreports a failure in a portable I/O operation.ParseErrorreports malformed or unrepresentable primitive text.
Their canonical package is cloth.lang.errors; recursive prelude lookup keeps
the short names available without an import.
All four provide () and (string message) constructors and may be extended by
more specific application errors. They require no import:
func SetLimit(int32 limit) throws ArgumentError {
if (limit < 0) {
throw ArgumentError("limit must be non-negative");
}
}Use a specific error when the API has a more precise failure contract. These
types do not replace compiler-owned Error, DivisionByZero, or runtime traps.
Use throw to complete the current callable with a non-null error. A callable
that can expose an error declares its set after the return type:
func Load(): object throws IoError, ParseError {
return ReadSource();
}
User(string name) throws InvalidUser: Human(name) {
Name = Validate(name) ?? throw InvalidUser(name);
}Calls use ordinary syntax. When a called function succeeds, evaluation
continues with its result. When it throws, Cloth automatically propagates the
error; no later argument, assignment, or statement on that path executes.
Public functions and constructors must state every exposed error. Private
callables may omit throws; the compiler infers their transitive set.
The compiler-provided sealed DivisionByZero error is produced when executed
integer /, %, /=, or %= uses a zero divisor. A required constant with a
zero divisor remains a compile-time error. Floating division keeps IEEE
behavior.
Null still represents expected absence. ?? throw promotes absence to an
error without a separate conditional:
User user = FindUser(id) ?? throw InvalidUser("unknown user");Cloth currently has no local try, catch, or recover construct. A thrown
error continues to the caller until it reaches a declared throwing Main.
Terminal runtime failures
Some invalid operations are compile-time errors. Others depend on runtime values and terminate through a runtime trap:
- Out-of-bounds array access.
- A failed non-null assertion.
- An out-of-range checked numeric conversion.
- An invalid dynamic shift count.
- An integer byte operation whose complete range does not fit the array.
A failed safe reference cast is different: value as T? returns null. Use
nullability to handle that result.
Program termination
A void Main finishes with status zero. An int32 Main supplies its
returned process status. Main may declare throws; an escaping error is
written to standard error as cloth error: Type with : Message appended when
the message is non-empty, and the process returns a nonzero status. Runtime
traps terminate execution instead of returning a successful result.