kota's memex
use fmt;

export fn main() void = {
	// Casting between numeric types allows for lossy conversions:
	fmt::println(13.37f32: int)!;

	// Type assertions let you examine the type of a tagged union:
	let x: (int | uint) = 42i;
	assert(x is int);
	fmt::println(x as int)!;

	let y: nullable *(int | uint) = &x;
	assert(!(y is null)); // And nullable pointers

	// You can even use casts for pointer arithmetic, ill-advised as that may
	// be:
	fmt::println("{:x} {:x}", y, y: uintptr + 10)!;

	// Casts can also be used to change pointer types, ill-advised as that may
	// be:
	let z = (y: uintptr + size(int): uintptr): *int;
	assert(*z == 42);
};

casting

Casting from a float to an int is a lossy operation, but can be done explicitely: 13.37f32: int

Converting between signed and unsigned types must also be explicit.

type tests

The is expression returns true if the tagged union is set to a value of the given member type.

type assertions

The as keyword is useful when you know a tagged union has a particular type (previously tested with is) and want to treat it as such. This "assertion" is tested at runtime and will abort your program if it fails.