Most numberic types like
i64 have a limit range of possible
values they can hold. Some numeric operations such as addition or multiplication
can lead to an overflow. Fuzion's basic types provide a choice of means to deal
with overflows. These will be presented here.
Runtime Checks via Preconditions
The standard operations perform runtime checks to detect overflows at runtime:
If runtime checks are enabled, an error is produced and the application is stopped. Alternatively, runtime checks can be disabled:
Which then results in wrap-around numeric behaviour.
Explicit handling of Overflows
Alternatively, a set of operations
*? produce an optional result in case of an overflow:
match-statement can be used to distinguish the successful case
from the overflow.
A disadvantage of this approach is that one needs to check for an overflow after every operation that might overflow, otherwise we might see overflows in intermediate values:
? operator provides syntactic sugar that simplifies
these tests: When applied to a choice type like
? returns immediately from the current feature in case the
value does not match the first type in the choice. In this case, the value is
returned as the feature's result.
In some cases, it might be sufficient to record a large (or small) number in
case of a numeric overflow (or underflow). An example is counting some entity
while it does not matter to distinguish very large amounts. A set of saturating
*^ does this: After
an overflow (or underflow), the largest (or smallest) representable value is
Note that, unlike the operations
*? that return an option, the saturating operations return a
normal numeric value that can be used for further arithmetic:
The fact that an intermediate operation resulted in an overflow may no longer be obvious after additional operations.
In some applications, it might be desirable to have wrap-around semantics,
i.e., the value represented is always the lowest bits that fit in the respective
type. This is possible using a new set of operations
⮫ next: Fraction Types