Reflect

Types

Basic Types

The following basic types are available:

The Type Type

A type itself can be represented as a value of type type. Types can be treated as values, both at run time and at compile time. However, values or declarations can only be generated from a type at compile time, that is, the type value needs to be stored in a meta variable/constant or parameter.

⚠️ TODO: type operations

Arrays

Arrays represent a fixed number of elements of the same type.

Example

var arr: int[2];
arr[0] = 1;
arr[1] = 2;

⚠️ TODO: go more in depth

Array Slices

An array slice is a reference into an array of elements with a dynamic length.

Example

var arr: int[10];
var slice = arr[1 .. 3];
slice[0] = 1;
slice[1] = 2;
assert(arr[1] == 1);
assert(arr[2] == 2);

⚠️ TODO: go more in depth

Pointers

A pointer stores the in-memory address of a value of any type. Declaring a pointer type is done by appending an asterisk (*) to an existing type. Any operation with a pointer value is considered memory unsafe and must be marked with @unsafe.

Example

var i: int;
var iptr: int*;
iptr = &i;
@unsafe *iptr = 2;
assert(i == 2);

Structs

Structs aggregate a number of fields into a combined value, also known as a product type. Each struct declaration forms its own distinct type.

See the Structs chapter for more details.

Enums

Enums encapsulate a value with a limited set of predefined values. They come in two variants, one containing a finite number of values of the same type and one containing arbitrary values of a finite number of types.

See the Enums chapter for more details.

Functions

Functions come in various forms, simple named functions, methods, operators, constructors, inline functions, lambda expressions etc.

See the Functions chapter for more details.

Additional Type Aliases

The following type aliases are defined in core.types and are part of the language, but are no keywords:

Type Qualifiers

⚠️ TODO

Escaping Data

By default, references cannot escape the scope in which they are declared. In order to allow a reference to escape its scope, the referenced data needs to be qualified with escape.

The escape qualifier is recursively applied to all contained types.

Isolated Data

The counterpart to escape is the isolated qualifier. Data qualified with isolated is guaranteed to only be referenced by a single reference. This guarantee enables references to isolated data to be safely converted to references to equivalent types with any other combination of qualifiers.

Additionally, isolated references can be safely moved between threads.

The conversion from isolated to an equivalent type with the default scoped qualification is implicit, whereas the conversion to an escape reference can only be done by moving the reference.

Both, escape and isolated, apply recursively to all contained types.

Mutability

By default, all reference types are mutable. Conversely, data qualified with immutable is guaranteed to never change during its lifetime. In order to accept both, mutable and immutable data, a type can be qualified with const.

immutable and const do not apply recursively to contained types.

Synchronization

By default, non-immutable data is guaranteed to be thread-local. The shared qualifier can be used to enable access from multiple threads. Shared data can only be accessed using an appropriate synchronization mechanism, such as atomic operations or monitor references.

In order to accept both, shared and thread-local data, the synchronized qualifier can be used. Such data needs to be accessed using the same synchronization mechanisms as shared data.

immutable types implicitly cast to shared and synchronized and can also be safely passed between threads without synchronization.

Implicit Type Conversions

⚠️ TODO

Binary Representation