Type system
Programmer can define types of the following kinds:
- object
- structure
- union
- class
- named tuple
- symbol
- sum
- flags
Object
type Buffer =
val type : BufferType
var object : VkBuffer
var size : u32
val offset : u64
val usage : BufferUsageFlags
The Buffer
type has five fields, which are also constructor parameters.
type StorageBuffer =
inherit Buffer type = BufferType/Storage
offset = 0
let device : VkDevice
let memory : VkMemory
def discard =
vk/destroy_buffer device object null
vk/free_memory device memory null
When inheriting, we passed in values for the type
and offset
fields, the three remaining fields become constructor parameters for StorageBuffer
, joined by device
and memory
.
Bindings and functions with let
are private to a file.
type AttachmentFormat @data =
val format : VkFormat
val samples : SampleCountFlags
val usage : ImageUsageFlags
Equality and hash of objects with @data
attribute are derived from fields.
import collection/List@mrc
let list @owner = List.new
Modifier @mrc
stands for manual reference counting. The @owner
attribute guarantees that memory is freed before the containing function returns, also available for object fields.
The new
keyword is used only for types without constructor parameters.
type Stack =
var align_h @mut = AlignH/Stretch
val items @mut = List<Control>.new
The List
type has a mutable version mut List
. Readonly type cannot be casted back to mutable.
When the file ends, var
bindings become readonly and val
bindings of mutable types get the readonly version of the type. @mut
attribute serves to prevent this.
type App @move =
let name : String
let app = App "Editor"
let app_ref = app
let app_copy = app@copy
The app
binding of type mov App
contains object's memory. Accessing app
returns a reference of type App
. Copying requires the @copy
modifier.
type Slice<T> @byval =
val ptr : Ptr<T>
val size : u32
Objects with @byval
attribute are passed by value.
Multiple inheritance is supported, but each type can be inherited only once.
Structure
type ClearDepthStencilValue = struct
depth : f32
stencil : u32
Can inherit other structures.
Union
type ClearValue = union
color : ClearColorValue
depth_stencil : ClearDepthStencilValue
All fields point to the same memory address. Value of one field needs to be provided on initialization.
Class
type Compare = class
def compare (other : Self) : Ordering
def (>) (rhs : Self) =
let result = compare rhs
result == Ordering/Greater
...
type TextPos = struct
line : u32
char : u32
def compare (other : TextPos) = when
line < other.line -> Ordering/Less
line > other.line -> Ordering/Greater
char < other.char -> Ordering/Less
char > other.char -> Ordering/Greater
else -> Ordering/Equal
is Compare
Type can be declared as belonging to a class if it corresponds to all of the class's requirements.
Named tuple
type CString = ptr CChar
Most of the time has only one element, as otherwise a structure might be a better choice.
Symbol
Also known as a unit type. In essence, it is a named tuple with zero elements.
type None = symbol
Is used in sum types.
Sum
Differs from union by containing information about an active field.
type BufferType =
| Vertex
| Index
| Storage
| Image
| Uniform
Enumeration is a sum of unit types.
type Target =
| Buffer VkBuffer
| Image image : VkImage
width : u32
height : u32
Target/Buffer
is a named tuple, Target/Image
is a structure.
type Option<T> =
| None
| Some T
type Result<T, E> =
| Ok T
| Error E
Option
allows for representing an absence of a value. Function returns Result
to pass an error message in case of a failure.
type Metal @open = enum
Iron | Copper | Nickel
type Metal
Silver | Gold
type Platinum = symbol
inherit Metal
Fields can be added to open sum types at any moment. Modifier enum
restricts types of fields to symbols.
Flags
type QueueFlags = flags
| Graphics
| Compute
| Transfer
| SparseBinding
| Protected
let queue_flags = QueueFlags/Graphics | QueueFlags/Transfer
assert queue_flags.contains QueueFlags/Graphics