Types
Basic Types
The following basic types are available:
void: A zero sized type representing no valuenoreturn: Zero sized type representing a value that is never returnedtypeof(null): A zero sized type that can be converted to any pointer typebool: A 1-byte sized type that can only have the valuestrueorfalseubyte: An unsigned 8-bit integerbyte: A signed 8-bit integerushort: An unsigned 16-bit integershort: A signed 16-bit integeruint: An unsigned 32-bit integerint: A signed 32-bit integerulong: An unsigned 64-bit integerlong: A signed 64-bit integerucent: An unsigned 128-bit integercent: A signed 128-bit integerfloat: A 32-bit floating point numberdouble: A 64-bit floating point numberchar: An 8-bit value representing a UTF-8 code unit
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:
uint8=ubyteint8=byteuint16=ushortint16=shortuint32=uintint32=intuint64=ulongint64=longfloat32=floatfloat64=doublesize_t- platform dependent unsigned integer type representing a number of addressable values in memorysizediff_t- platform dependent signed integer type representing the distance of two addressable values in memorynull_t- Type of thenullconstantstring- The default string type - currently defined asimmutable(char)[], but subject to change
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
- Integer types are using two's complement semantics.
- Floating point types are represented according to the IEEE 754 standard.
- Basic types with a size larger than one byte are stored with the native endianness of the system.