Structs
⚠️ TODO
Example
struct Vec2 {
var x: float;
var y: float;
method getLength() => sqrt(this.x ^^ 2 + this.y ^^ 2);
}
var v = Vec2(3.0f, 4.0f);
print(v.getLength()); // 5
Constructor and Destructor
⚠️ TODO
Example
struct S {
var coords: int[];
this(x: int, y: int)
{
coords = allocArray(int, 2);
coords[0] = x;
coords[1] = y;
}
~this()
{
freeArray(coords);
}
@disable operator[copy]();
}
Copy and Move Operators
The behavior of a struct value being copied or moved by the compiler can be
customizing by overloading the copied and moved operators.
The copied operator will be called whenever a value was copied to a new memory
location. It allows the struct to perform bookkeeping tasks, such as
incrementing a reference count.
The moved operator is called similarly after a value has been moved to a
different memory location.
Both operators can be marked with the @disable attribute do disallow copying
or moving values of the respective struct type.
Example
struct S {
operator[copy]() {
print("copied!");
}
operator[move]() {
print("moved");
}
}
struct T {
// disallows any value of type T to be moved
@disable operator[move];
}
Properties
Properties behave similar to regular fields, but are backed by getter and/or a setter methods. Depending on the existence and attributes of the defined accessors, a property can be read-only, read/write or write-only:
getonly: read-only propertyget refonly: read-write propertysetonly: write-only propertygetandset: read-write property
Declaring a property can be done using the regular syntax where get and set
are used within curly braces to define the corresponding methods, or using the
shortcut syntax where the lambda syntax => is used to define a single getter.
In the latter case, the => can be prefixed by a ref attribute to signal that
the value is returned by reference.
If the property has no explicit type, it will be inferred from the getter. A setter-only property must define an explicit type.
Example
struct Widget {
private {
var _width: int;
var _height: int;
var _caption: string;
}
// read-only
var width { get => _width; }
// shortcut syntax
var height => _height;
// read-write
var caption {
get => _caption;
set(v) { _caption = v; redraw(); }
}
function redraw() {
// ...
}
}
Operating on Properties
Using modifying operators, such as assignment or increment operators, on a property will automatically generate code that uses the property getter and setter to implement the operation equivalent to operating on a plain value of the same type.
Example
struct MyArray {
private {
var _length: size_t;
var _capacity: size_t;
var _ptr: void*;
}
var length {
get => _length;
set(v) {
if (v <= _capacity) {
_length = v;
} else {
_ptr = realloc(_ptr, v);
_length = _capacity = v;
}
}
}
}
var arr: MyArray;
// normal setter call
arr.length = 10;
// modifying operator
arr.length += 5;
// translated to:
// [ref arr] { var tmp = arr.length; tmp += 5; arr.length = tmp; return tmp; } ()
Passing Properties as Arguments
Similarly to how operators are handled, passing a property to a ref or out
parameter is translated to matching getter/setter calls internally.
Example
function foo(out num: size_t) { num = 42; }
function bar(ref num: size_t) { num++; }
var arr: MyArray;
// out parameter
bar(arr.length);
// translated to:
// var tmp: typeof(arr.length); bar(tmp); arr.length = tmp;
// ref parameter
foo(arr.length);
// translated to:
// var tmp = arr.length; foo(tmp); arr.length = tmp;