Predict the output of numeric operations and lookups, then fix an array access that stops execution. The examples show what happens after a program passes checking.
Install Topaz through First Program. Save the two examples as separate files and run each from its folder.
Observe ordinary values
Save this as runtime-behavior.tpz.
let values = [10, 20]
print("int: {7 / 2} {-7 % 3}")
print("float: {1.5 + 1.5}")
print("safe: {values.get(9)}")Run topaz run runtime-behavior.tpz.
int: 3 -1
float: 3.0
safe: None7 / 2 gives 3 because integer division discards the fractional part toward zero. -7 % 3 gives -1 because the remainder follows the dividend's sign. 1.5 + 1.5 prints as 3.0.
values.get(9) returns None because the array has no element at index 9. get represents absence as a value, so the program keeps running.
print takes a string and adds a newline. Interpolation converts the numbers and Option to text before the call. Use print for line output. There is no free println function.
Observe an invalid array index
Save this second example as intentional-fault.tpz.
let tasks = ["Run first program", "Build application"]
print(tasks[2])Run topaz run intentional-fault.tpz. It exits with a nonzero status and points to the failed access.
error[TPZ4001]: index 2 is out of bounds for an array of length 2
--> intentional-fault.tpz:2:7
|
2 | print(tasks[2])
| ^^^^^^^^
The array has two elements, at indices 0 and 1. Change tasks[2] to tasks[1] and run again to print Build application. If a missing index is expected, use tasks.get(2) and handle None.
A runtime error, or fault, stops execution. It cannot be caught by postfix ?, optional operators, or concurrent. None and Err are values that a program can handle.
Choose the observable failure model
| Situation | Result |
|---|---|
| A value is absent | Option, such as None from get |
| An operation returns an error reason | Result containing Ok or Err |
| An invalid operation is reached during execution | A fault and nonzero process exit |
| Source is invalid before execution | A diagnostic from topaz check |
An int is a signed 64-bit integer. Overflow stops execution with a fault. A float uses IEEE-754 binary64 arithmetic, so decimal fractions can require rounding.
These conditions cause faults when reached at runtime.
| Operation | Invalid condition |
|---|---|
| Direct array indexing | Index outside the array |
| Integer division or remainder | Divisor is zero |
| Integer arithmetic | Result exceeds the integer range |
| Range iteration | Step is zero |
| Integer exponentiation | Exponent is negative |
match | No case matches the value |
The checker can reject constant invalid arithmetic before execution. For values computed at runtime, validate the input before the operation.
Call depth is capped at 1000 frames, meaning 1000 active nested calls, across execution routes. A deeper call reports TPZ5009 at the call site. There is no command-line option to raise this limit.
What remains stable
String comparison uses exact Unicode scalar sequences. A scalar is one Unicode code point outside the surrogate range. Topaz does not automatically normalize different sequences into one spelling. For example, precomposed "é" and "é" compare unequal even when they look alike.
Arrays keep element order. Map key snapshots keep insertion order. Other collection operations and callbacks follow the order specified for that operation.
Printed record, enum, and newtype values retain their type's constructor name. The output forms include Name { field: value }, Name.Variant, and Name(value). Targets may store values differently while preserving the language's output and execution rules.
Continue with Null, Option, Result & Faults for handling values, Concurrency for timeouts, or Core Library for conversion helpers. Strings & Templates explains scalar positions.