Numeric Overflow
Oftentimes, programming languages assign sizes to certain numeric types: in C,
the 8-bit unsigned integer is called uint8_t
, and can represent values
between 0 and 255. If something larger than 255 is assigned to a variable of
this type, it rolls over, the result being the modulus. So if we assigned 260
to a uint8_t
, we would actually get 5 instead. If we were to do this to an
int8_t
(the 8-bit signed integer that represents values from -127 to 127),
the results are undefined; a C compiler has license to do whatever it likes.
This has a couple of unfortunate effects. The first is you constantly need to
estimate what values may be stored in your variables, which generally causes
most programmers to use int
everywhere. The second is when numbers behave
unexpectedly (roll over or explode), they can cause program misbehavior, which
often leads to a crash or a security issue.
Ki has two number types that are not like this: int
and uint
. They are
intended to be the default integer types. Instead of overflowing, they just
keep growing (either positively or negatively). The downside is that they
become about half as fast as a regular integer once they exceed the bit-width
of the host machine.
The other integer types (s8
, s16
, s32
, s64
, u8
, u16
, u32
and
u64
) don't do this, rather they overflow by default. Signed overflow is
well-defined in Ki; it doesn't share that problem with C.
You can change the overflow behavior of both int
and the sized integer types
at a program level or an expression level. Here are your options:
@overflow.
: calls the functionx
with the pre-overflow value@overflowfn
: used to define an overflow handling function instead offn
.@set_overflow_handler
: sets the default overflow handler to the functionx
.@overflow.wrap
: wraparound@overflow.limit
: floor/ceiling@overflow.bignum
: convert to bignum (probably default policy)@overflow.error
: runtime error@overflow(
: custom function, )