Types
The types Antril has built in - integers and floating-point numbers of 8 to 256 bits, bool, characters, str and String<T>, any, arrays, nullable types, tuples, function types, pointers and references.
On this page
Every value in Antril has a type known when the program compiles. This page describes the types the language has built in. Types a program declares (classes, values, records, interfaces, enums) are in Declarations; generic types in Generics.
| Type | Kind |
|---|---|
bool, the integers, the floats |
Primitive values |
str, String<T> |
Text: a class |
any |
The root of every class |
void |
No value |
T[], T[,], T[N] |
Arrays |
T? |
Nullable types |
(T1, T2, …) |
Tuples |
func<…> : R, func*<…> : R |
Function types |
T*, void* |
Pointers (unsafe code) |
&T, &mut T |
References |
Value types and reference types
A value type holds its value directly: assigning it or passing it copies it. The primitives, enums, tuples and the value and record value types a program declares are value types.
A reference type lives on the heap, and variables hold a reference to it: assigning a variable makes both refer to the same object. Classes, str, arrays and any are reference types.
A variable of a value type that is not assigned starts at zero. A variable of a reference type must be assigned before it is used, unless its type is nullable.
Primitive types
| Type | Size | Values | Library type |
|---|---|---|---|
bool |
1 byte | true, false |
System.Boolean |
i8 |
1 byte | −128 … 127 | System.Int8 |
i16 |
2 bytes | −32 768 … 32 767 | System.Int16 |
i32 |
4 bytes | −2³¹ … 2³¹−1 | System.Int32 |
i64 |
8 bytes | −2⁶³ … 2⁶³−1 | System.Int64 |
i128 |
16 bytes | −2¹²⁷ … 2¹²⁷−1 | System.Int128 |
i256 |
32 bytes | −2²⁵⁵ … 2²⁵⁵−1 | System.Int256 |
u8 |
1 byte | 0 … 255 | System.UInt8 |
u16 |
2 bytes | 0 … 65 535 | System.UInt16 |
u32 |
4 bytes | 0 … 2³²−1 | System.UInt32 |
u64 |
8 bytes | 0 … 2⁶⁴−1 | System.UInt64 |
u128 |
16 bytes | 0 … 2¹²⁸−1 | System.UInt128 |
u256 |
32 bytes | 0 … 2²⁵⁶−1 | System.UInt256 |
iptr, uptr |
a pointer (8 bytes on 64-bit targets) | signed, unsigned | (none: they have no library members) |
f16 |
2 bytes | IEEE half precision | System.Float16 |
f32 |
4 bytes | IEEE single precision | System.Float32 |
f64 |
8 bytes | IEEE double precision | System.Float64 |
f128 |
16 bytes | IEEE quadruple precision (34 digits) | System.Float128 |
f256 |
32 bytes | IEEE octuple precision (72 digits) | System.Float256 |
Each primitive keyword names a value of the standard library, so the members of that type can be used through either name: Int32.MaxValue or i32.MaxValue, Int32.Parse("42"), x.ToString().
import System;
Main()
{
Console.WriteLine(i8.MinValue + " " + u16.MaxValue);
Console.WriteLine(i256.MaxValue);
f128 third = 1f128 / 3f128;
Console.WriteLine(third);
Console.WriteLine(Int32.Parse("41") + 1);
Console.WriteLine(sizeof(u256));
}
larva run
-128 65535
57896044618658097711785492504343953926634992332820282019728792003956564819967
0.3333333333333333333333333333333333
42
32
| Members | Of |
|---|---|
MinValue, MaxValue (constants) |
every number type |
Epsilon, NaN, PositiveInfinity, NegativeInfinity (constants) |
the floats |
Zero, One (and NegativeOne for signed types) |
every number type, as static properties |
Parse(text), ToString(), Hash(), Equals(other), CompareTo(other) |
every number type |
Integer arithmetic wraps around on overflow (i32.MaxValue + 1 is i32.MinValue) unless it is in a checked block or expression, which throws OverflowError (see Statements). Integer division by zero stops the program with larva panic: division by zero and exit code 101.
Characters
Antril has no character type. A character literal such as 'A' is the number of its Unicode code point, of the integer type expected where it goes (u16 when none is). System.Char has functions on code points: Char.IsDigit('7'), Char.IsLetter(c), Char.ToUpper(c). See Lexical structure.
Text: str and String
str is System.String<u8>: immutable text in UTF-8. A string literal is a str.
String<T> is generic over the size of its code units, T : [u8, u16, u32]: String<u8> (UTF-8, which is str), String<u16> (UTF-16) and String<u32> (UTF-32). ToUtf16() gives the UTF-16 form of a str; String<u16> is how text crosses to C functions that take wide strings (see Interop).
A string's Length and indexes count code units, not characters. A loop over a string gives its units:
import System;
Main()
{
str word = "año";
Console.WriteLine(word.Length);
loop (u8 unit in word)
Console.Write(unit + " ");
Console.WriteLine();
Console.WriteLine(word.ToUtf16().Length);
}
larva run
4
97 195 177 111
3
== compares strings by content, and + joins a string with another string, a number or any object (shown with its ToString()). The members of str (Substring, IndexOf, Split, Replace, Trim, ToUpper…) are listed in the standard library.
Warning
Not yet available: Console.WriteLine of a String<u16> does not print its text correctly. Convert it to str first.
any
any is System.Any, the root of every class: every object is an any, and any has ToString(), Equals(other), Hash() and GetType().
A value of a value type, a function or a pointer stored in an any is boxed: copied into an object. A cast gets it back, and is tests what it holds:
any boxed = 5;
i32 back = (i32)boxed;
if (boxed is i32 n)
Console.WriteLine(n * 2);
void
void is the type of "no value". A function with no result type returns void; it cannot be the type of a variable, a field or a parameter. void* is an untyped pointer.
Arrays
| Type | What it is |
|---|---|
T[] |
An array: a fixed number of elements, on the heap. |
T[,], T[,,] … |
A rectangular array of 2 to 8 dimensions. |
T[][] |
An array of arrays (each row its own length). |
T[N] |
An inline array of N elements kept inside a value or class, as a fixed field (see Memory). |
import System;
Main()
{
i32[] zeros = new i32[4];
str?[] names = new str?[2];
i32[] some = [1, 2, 3];
i32[,] grid = new i32[2, 3];
grid[1, 2] = 7;
i32[][] rows = [[1, 2], [3]];
Console.WriteLine(zeros.Length + " " + names.Length + " " + some[2]);
Console.WriteLine(grid.Length + " " + grid.Rank + " " + grid.GetLength(1) + " " + grid[1, 2]);
Console.WriteLine(rows[1].Length);
}
larva run
4 2 3
6 2 3 7
1
Lengthis the number of elements;Rankthe number of dimensions andGetLength(d)the length of one (from 0).- A new array starts zeroed, so its element type needs a zero value: numbers,
bool, enums, values, or a nullable type.new str[3]is error AN2022; writenew str?[3]or use a literal. - An array literal
[a, b, c]takes its type from where it goes; a nested literal fills a rectangular array (i32[,] m = [[1, 2], [3, 4]];). - Indexes are checked: an index out of range stops the program with
larva panic: index 3 out of bounds for length 1and exit code 101. - Type suffixes read from left to right:
i32[,][]is an array of rectangular arrays,i32[]?a nullable array. - An array is a reference type: assigning it shares it (see Memory).
Warning
Not yet available: a filler value for a new array, new str[3](""). Fill it with a loop, or use a List<T>.
Nullable types
A type without ? never holds null. T? can hold a T or null, for any type: str?, Person?, i32?, i32[]?.
import System;
Main()
{
str? name = null;
Console.WriteLine(name ?? "nobody");
Console.WriteLine(name?.Length ?? -1);
i32? count = null;
Console.WriteLine(count.HasValue);
count = 7;
Console.WriteLine(count.Value + 1);
if (count is i32 n)
Console.WriteLine(n * 2);
}
larva run
nobody
-1
false
8
14
- A member of a nullable value cannot be used until it is checked:
name.Lengthis error AN2040. Test it withis,?.,??or a comparison withnull. - A nullable value type has
HasValueandValue; readingValuewhen there is none stops the program. - Operators of the underlying type do not apply to the nullable one:
count + 1withi32? countis error AN2078. Usecount.Valueorcount ?? 0. - A
Tconverts toT?by itself. The other way needs a check:x is T y,x ?? fallback, orx.Value.
Tuples
(T1, T2, …) is a tuple type of two or more elements: System.ValueTuple<T1, T2, …>. (a, b, …) makes one, and its elements are Item1, Item2…
(i32, str) pair = (1, "one");
pair.Item1 = 2; // the elements can change
(i64, f64) wide = (3, 4); // each element takes the type it goes to
(str?, i32) maybe = (null, 1); // null needs a type to go to
Tuples are records: == compares them element by element, they print as (1, one), and they work as dictionary keys. ToTuple() gives a System.Tuple<…>, a class whose elements cannot change. One to sixteen elements are declared in System.Core; larger tuples are made from a variadic template.
A tuple that holds objects, such as (i32, str), cannot be the type argument of a generic type (List<(i32, str)>). Tuples of numbers and plain values can: Dictionary<(i32, i32), str>.
Function types
func<A, B> : R is the type of a function value that takes an A and a B and returns an R. func : R takes nothing; without : R it returns nothing (func<str>, func). Lambdas, free functions, static methods and object.Method are function values. See Functions.
func*<A> : R is the address of a function with the C calling convention, for interop. Its parameters and result are numbers, bool, pointers and other func* (AN1057). See Interop.
Pointers
In unsafe code, T* is the address of a T: a number, an enum, a value without objects, or another pointer. void* is an address of anything. See Memory.
References
&T is a shared reference to a T and &mut T an exclusive one. They need the borrow checker (borrowcheck: warn or enforce). See Memory.
Static classes
A static class has no values: it cannot be the type of a variable, a field, a parameter, a result, an element, a type argument, a default(T) or a cast (AN1105). Use its members through its name: Console.WriteLine(…).
Edit this page on GitHub Report an issue