Skip to content

Standard Library

The standard library is currently in development, so frequent changes will occur. Note that all std::core modules and sub modules are implicitly imported.

All functions and macros in this library can be used without path qualifiers.

void panic(char* message, char *file, char *function, uint line)

Section titled “void panic(char* message, char *file, char *function, uint line)”

Default function called when the asserts fails.

Swap values in a and b.

int a = 3;
int b = 5;
@swap(a, b);
io::printfn("%d", a); // Prints 5

Optionally cast the value v to type $Type* on failure returns CastResult.TYPE_MISMATCH.

int b;
any a = &b;
float*? c = anycast(a, float); // Will return TYPE_MISMATCH
int*? d = anycast(a, int); // Works!

void unreachable($string = "Unreachable statement reached.")

Section titled “void unreachable($string = "Unreachable statement reached.")”

Mark a code path as unreachable.

switch (x)
{
case 0:
foo();
case 1:
bar();
default:
// Should never happen.
unreachable("x should have been 0 or 1");
}

On safe mode this will throw a runtime panic when reached. For release mode the compiler will assume this case never happens.

Do a bitcast of a value to $Type, requires that the types are of the same memory size.

float x = 1.0;
int y = bitcast(x, int); // y = 0x3f800000

Optionally returns the enum value with the given name. $Type must be an enum. Returns SearchResult.MISSING on failure.

enum Foo { ABC, CDE, EFG }
fn void? test()
{
Foo f = enum_by_name(Foo, "CDE")!;
// same as Foo f = Foo.CDE;
}

Scopes a variable:

int a = 3;
@scope(a)
{
a = 4;
a++;
};
// Prints a = 3
io::printfn("a = %d", a, b);

less, greater, less_eq, greater_eq, equals

Section titled “less, greater, less_eq, greater_eq, equals”

All macros take two values and compare them. Any type implementing Type.less or Type.compare_to may be compared (or if the type implements <). Types implementing Type.equals may use equals even if neither less nor compare_to are implemented.

  • IteratorResult returned when reaching the end of an iterator.
  • SearchResult used when a search fails.
  • CastResult when an anycast fails.
  • OS_TYPE the OS type compiled for.
  • COMPILER_OPT_LEVEL the optimization level used.
  • I128_SUPPORT true if int128 support is available.
  • COMPILER_SAFE_MODE true if compiled with safety checks.

Allocate the given number of bytes. malloc will panic on out of memory, whereas malloc_aligned returns an optional value. malloc_aligned adds an alignment, which must be a power of 2. Any pointer allocated using malloc_aligned must be freed using free_aligned rather the normal free or memory corruption may result.

char* data = malloc(8);
int[<16>]*? data2 = malloc_aligned(16 * int.sizeof), 128);

new($Type, #initializer), new_aligned($Type, #initializer)

Section titled “new($Type, #initializer), new_aligned($Type, #initializer)”

This allocates a single element of $Type, returning the pointer. An optional initializer may be added, which immediately initializes the value to that of the initializer.

If no initializer is provided, it is zero initialized. new_aligned works the same but for overaligned types, such allocations must be freed using free_aligned

int* a = mem::new(int);
Foo* foo = mem::new(Foo, { 1, 2 });

Allocates a single element of $Type, same as new, but without initializing the data.

new_array($Type, usz elements), new_array_aligned($Type, usz elements)

Section titled “new_array($Type, usz elements), new_array_aligned($Type, usz elements)”

Allocates a slice of elements number of elements, returning a slice of the given length. Elements are zero initialized. new_array_aligned is used for types that exceed standard alignment.

int[] ints = mem::new_array(int, 100); // Allocated int[100] on the heap, zero initialized.

alloc_array($Type, usz elements), alloc_array_aligned($Type, usz elements)

Section titled “alloc_array($Type, usz elements), alloc_array_aligned($Type, usz elements)”

Same as new_array but without initialization.

Identical to the malloc variants, except the data is guaranteed to be zeroed out.

Resizes memory allocated using malloc or calloc. Any extra data is guaranteed to be zeroed out. realloc_aligned can only be used with pointers created using calloc_aligned or alloc_aligned.

Frees memory allocated using malloc or calloc. Any memory allocated using “_aligned” variants must be freed using free_aligned.

Swaps the current memory allocator for the duration of the call.

DynamicArenaAllocator dynamic_arena;
dynamic_arena.init(1024);
mem::@scoped(&dynamic_arena)
{
// This allocation uses the dynamic arena
Foo* f = malloc(Foo);
};
// Release any dynamic arena memory.
dynamic_arena.destroy();

Same as @scoped, but uses the temporary allocator rather than any arbitrary allocator.

void* tmalloc(usz size, usz alignment = 0)

Section titled “void* tmalloc(usz size, usz alignment = 0)”

Allocates memory using the temporary allocator. Panic on failure. It has type variants similar to malloc, so tmalloc(Type) would create a Type* using the temporary allocator.

void* tcalloc(usz size, usz alignment = 0)

Section titled “void* tcalloc(usz size, usz alignment = 0)”

Same as tmalloc but clears the memory.

void* trealloc(void* ptr, usz size, usz alignment = 0)

Section titled “void* trealloc(void* ptr, usz size, usz alignment = 0)”

realloc but on memory received using tcalloc or tmalloc.

tnew, temp_alloc, temp_array, talloc_array

Section titled “tnew, temp_alloc, temp_array, talloc_array”

Same as the new, alloc, new_array and alloc_array respectively.

Opens a temporary memory scope.

@pool()
{
// This allocation uses the dynamic arena
Foo* f = tmalloc(Foo);
};

Returns the value in x using a volatile load.

// Both loads will always happen:
int y = @volatile_load(my_global);
y = @volatile_load(my_global);

Store the value y in x using a volatile store.

// Both stores will always happen:
@volatile_store(y, 1);
@volatile_store(y, 1);

usz aligned_offset(usz offset, usz alignment)

Section titled “usz aligned_offset(usz offset, usz alignment)”

Returns an aligned size based on the current offset. The alignment must be a power of two. E.g. mem::aligned_offset(17, 8) would return 24

usz aligned_pointer(void* ptr, usz alignment)

Section titled “usz aligned_pointer(void* ptr, usz alignment)”

Returns a pointer aligned to the given alignment, using aligned_offset.

bool ptr_is_aligned(void* ptr, usz alignment)

Section titled “bool ptr_is_aligned(void* ptr, usz alignment)”

Return true if the pointer is aligned, false otherwise.

void copy(void* dst, void* src, usz len, usz $dst_align = 0, usz $src_align = 0, bool $is_volatile = false)

Section titled “void copy(void* dst, void* src, usz len, usz $dst_align = 0, usz $src_align = 0, bool $is_volatile = false)”

Copies bytes from one pointer to another. It may optionally be set as volatile, in which case the copy may not be optimized away. Furthermore the source and destination alignment may be used.

Foo* f = tmalloc(data_size);
mem::copy(f, slice.ptr, size);

void set(void* dst, char val, usz len, usz $dst_align = 0, bool $is_volatile = false)

Section titled “void set(void* dst, char val, usz len, usz $dst_align = 0, bool $is_volatile = false)”

Sets bytes to a value. This operation may be aligned and/or volatile. See the copy method.

void clear(void* dst, usz len, usz $dst_align = 0, bool $is_volatile = false)

Section titled “void clear(void* dst, usz len, usz $dst_align = 0, bool $is_volatile = false)”

Sets bytes to zero. This operation may be aligned and/or volatile. See the copy method.

Makes a shallow copy of a value using the regular allocator.

Foo f = ...
return @clone(f);

Same as @clone but uses the temporary allocator.

Return true if the type can be used with comparison operators.

Return true if the value can be compared using the equals macro.

Return true if the value can be compared using the comparison macros.

Returns an optional value of $Type if the any value losslessly may be converted into the given type. Returns a ConversionResult otherwise.

any* v = &&128;
short y = any_to_int(v, short)!!; // Works
ichar z = any_to_int(v, ichar)!!; // Panics VALUE_OUT_OF_RANGE

usz? char32_to_utf8(Char32 c, char* output, usz available)

Section titled “usz? char32_to_utf8(Char32 c, char* output, usz available)”

Convert a UTF32 codepoint to an UTF8 buffer. size has the number of writable bytes left. It returns the number of bytes used, or UnicodeResult.CONVERSION_FAILED if the buffer is too small.

void char32_to_utf16_unsafe(Char32 c, Char16** output)

Section titled “void char32_to_utf16_unsafe(Char32 c, Char16** output)”

Convert a UTF32 codepoint to an UTF16 buffer without bounds checking, moving the output pointer 1 or 2 steps.

String? readline(stream = io::stdin(), Allocator allocator = allocator::heap())

Section titled “String? readline(stream = io::stdin(), Allocator allocator = allocator::heap())”

Read a String? from a file stream, which is standard input (stdin) by default, reads to the next newline character \n or to the end of stream. Readline returns an Optional string.

import std::io;
fn void? hello_name()
{
String? name = io::readline();
if (catch excuse = name)
{
return excuse?;
}
io::printfn("Name was: %s.", name);
}

Read a String? from a file stream which is standard input (stdin) by default, Reads to the next newline character \n or to the end of stream. Treadline returns an Optional string. The temporary allocator is used by Treadline, in contrast the readline defaults to the heap allocator, but is configurable to other allocators.

import std::io;
fn void? hello_name()
{
String? name = io::treadline();
if (catch excuse = name) {
return excuse?;
}
io::printfn("Hello %s! Hope you have a great day", name);
}

Print a value to stdout works for the majority of types, including structs, which can be helpful for debugging. The printn variant appends a newline.

import std::io;
enum Heat
{
WARM,
WARMER,
REALLY_WARM,
}
fn void main()
{
int[<2>] vec = { 4, 2 };
Heat weather = WARM;
int[5] fib = { 0, 1, 1, 2, 3 };
String dialogue = "secret";
io::print("Hello"); // Hello
io::print(20); // 20
io::print(2.2); // 2.200000
io::print(vec); // [<4, 2>]
io::print(weather); // WARM
io::print(fib); // [0, 1, 1, 2, 3]
io::print(dialogue); // secret
}

Print any value to stderr. The eprintn variant appends a newline.

See print for usage.

usz? printf(String format, args...) @maydiscard

Section titled “usz? printf(String format, args...) @maydiscard”

Regular printf functionality: %s, %x, %d, %f and %p are supported. Will also print enums and vectors. Prints to stdout.

import std::io;
enum Heat
{
WARM,
WARMER,
REALLY_WARM,
}
fn void main()
{
int[<2>] vec = { 4, 2 };
Heat weather = REALLY_WARM;
String dialogue = "Hello";
io::printfn("%s", dialogue); // Hello
io::printfn("%d", 20); // 20
io::printfn("%f", 2.2); // 2.200000
io::printfn("%s", vec); // [<4, 2>]
io::printfn("%s", weather); // REALLY_WARM
}

Also available as printfn which appends a newline.

usz? eprintf(String format, args...) @maydiscard

Section titled “usz? eprintf(String format, args...) @maydiscard”

Regular printf functionality: %s, %x, %d, %f and %p are supported. Will also print enums and vectors. Prints to stderr.

Also available as eprintfn which appends a newline.

See printf for usage

char[]? bprintf(char[] buffer, String format, args...) @maydiscard

Section titled “char[]? bprintf(char[] buffer, String format, args...) @maydiscard”

Prints using a ‘printf’-style formatting string, to a string buffer.

Returns a slice of the buffer argument with the resulting length.

usz? fprint(out, x), usz? fprintn(out, x = "")

Section titled “usz? fprint(out, x), usz? fprintn(out, x = "")”

Print a value to a stream. out must implement OutStream. The fprintn variant appends a newline.

usz? fprintf(OutStream out, String format, args...)

Section titled “usz? fprintf(OutStream out, String format, args...)”

Prints to the specified OutStream using a ‘printf’-style formatting string.

Returns the number of characters printed.

fprintfn appends a newline.

Libc putchar, prints a single character to stdout.

usz? DString.appendf(DString* str, String format, args...) @maydiscard

Section titled “usz? DString.appendf(DString* str, String format, args...) @maydiscard”

Same as printf but on dynamic strings.

File* stdout(), File* stdin(), File* stderr()

Section titled “File* stdout(), File* stdin(), File* stderr()”

Return stdout, stdin and stderr respectively.

Open a file with the given file name with the given mode (r, w etc)

Open a file pointed to by a Path struct, with the given mode.

See whether the given path is a file.

Get the size of a file.

Delete a file.

void? File.reopen(&self, String filename, String mode)

Section titled “void? File.reopen(&self, String filename, String mode)”

Reopen a file with a new filename and mode.

usz? File.seek(&self, isz offset, Seek seek_mode = Seek.SET)

Section titled “usz? File.seek(&self, isz offset, Seek seek_mode = Seek.SET)”

Seek in a file. Based on the libc function.

void? File.write_byte(&self, char c) @dynamic

Section titled “void? File.write_byte(&self, char c) @dynamic”

Write a single byte to a file.

Close a file, based on the libc function.

True if EOF has been reached. Based on the libc function.

Read into a buffer, based on the libc function.

Write to a buffer, based on the libc function.

Read a single byte from a file.

char[]? load_buffer(String filename, char[] buffer)

Section titled “char[]? load_buffer(String filename, char[] buffer)”

Load up to buffer.len characters into the buffer.

Returns IoError.OVERFLOW if the file is longer than the buffer.

char[]? load_new(String filename, Allocator allocator = allocator::heap())

Section titled “char[]? load_new(String filename, Allocator allocator = allocator::heap())”

Load the entire file into a new buffer.

Load the entire file into a buffer allocated using the temporary allocator.

Flush a file, based on the libc function.

Generic list module, elements are of Type.

import std::collections::list;
alias MyIntList = List{ int };
...
MyIntList list;
list.init(mem); // heap allocated
list.push(123);
list.free();

List.push(List *list, Type element), append(...)

Section titled “List.push(List *list, Type element), append(...)”

Append a single value to the list.

Removes and returns the last entry in the list.

Removes the first entry in the list.

void List.remove_at(List *list, usz index)

Section titled “void List.remove_at(List *list, usz index)”

Removes the entry at index.

void List.insert_at(List *list, usz index, Type type)

Section titled “void List.insert_at(List *list, usz index, Type type)”

Inserts a value at index.

void List.push_front(List *list, Type type)

Section titled “void List.push_front(List *list, Type type)”

Inserts a value to the front of the list.

Remove the last value of the list.

Remove the first element in the list.

Return the first element in the list if available.

Return the last element in the list if available.

Return true if the list is empty.

Return the number of elements in the list.

Return the value at index.

Free all memory associated with this list.

Swap two elements in the list.