Documentation channel: current development main at compiler checkpoint 1d7e15e. The latest tagged release is v0.0.3; pages identify APIs that are not yet released.

Types

Strut uses lowercase built-in type names and lets aliases provide ergonomic defaults. Explicit-width names remain available whenever layout or interoperability matters.

Built-in and core types

TypeMeaningExample
boolBoolean value.ready := true;
intAlias of int_32.count := 12;
uintAlias of uint_32.uint mask := 7;
int_8/16/32/64Signed fixed-width integers.int_64 id := 42;
uint_8/16/32/64Unsigned fixed-width integers.uint_8 byte := 255;
doubleAlias of double_32.ratio := 1.5;
double_32/64Floating-point values.double_64 precise := 1.25;
stringOwned UTF-8 byte string.name := "Strut";
jsonBuilt-in JSON value.json data := {...};
T[] / vector<T>Core dynamic contiguous array; no include required. vector<T> is the compatibility spelling.int[] ids := [1, 2];
T[n]Fixed-size array.int[3] rgb := [1, 2, 3];
map<K,V>Hash map; requires <map>.map<string,int>
set<T>Hash set; requires <set>.set<string>
ordered_map<K,V>Sorted tree map.ordered_map<string,int>
ordered_set<T>Sorted tree set.ordered_set<string>
tuple<T...>Fixed heterogeneous tuple.tuple<double,int>
T?Nullable value.User? user := null;
T*Safe reference-counted owning pointer.User* user := new(...);
T**Recursive safe owning pointer layers.User** users := new(user);
T*&Non-owning reference to a pointer binding.User*& alias := ref(user);
T&Safe non-owning, non-null reference.User& user := existing;
weak_ptr<T>Non-owning weak pointer.weak_ptr<User>
raw_ptr<T>Unsafe unmanaged raw pointer; restricted to unsafe.raw_ptr<User>

Aliases

int, uint, and double are ordinary aliases, not special compiler-only spellings. User aliases use the same mechanism.

type int := int_32;
type uint := uint_32;
type double := double_32;
type user_id := uint_64;

Dynamic arrays

function main() -> int {
    int[] values := [1, 2, 3];
    print(values.reduce((total, value) => total + value));
    return 0;
}

Pointer and reference types compose inside generic containers.

User*[] owners;
owners.push(new(User { id: 1, name: "Ada" }));

User&[] views;
views.push(ref(*owners[0]));

Fixed arrays

double[3] point := [1.0, 2.0, 3.0];

Maps

Plain map is hash-based for fast general-purpose lookup; use ordered_map when sorted iteration is required. Maps use keyed square-bracket literals so braces can unambiguously mean JSON objects.

include <map>;

map<string, int> scores := [
    "alice": 10,
    "bob": 20
];

scores.insert("carol", 30);

JSON

payload := {
    "name": "Strut",
    "active": true,
    "ports": [8080, 8081]
};

Nullable values

User? user := find_user(id);
name := user?.name ?? "anonymous";

Type inference

:= infers a stable type from the initializer. Later assignment must remain compatible with that type.

count := 1;       // int / int_32
ratio := 1.25;    // double / double_32
name := "Strut"; // string

Tuples

include <tuple>;

tuple<double, int> t := (2.0, 1);
tuple<int> single := (7,);
print(t[0]);

A trailing comma distinguishes a one-element tuple from an ordinary parenthesized expression.