Capy-Bearer Documentation

struct

Capy

struct Name { field : type, ... }

A struct is a named, fixed layout of typed fields. The compiler checks its shape. A missing or misspelled field is a compile error.

Declare one at the top level of a unit, then construct it by passing the fields in order:

struct Point { x : s32, y : s32 }

function RENDER(request : dval) {
    var origin := Point(0, 0)
    print(origin.x, ",", origin.y, "\n")
}

Fields are mutable, the binding is shared

Reading and writing fields uses .:

struct Counter { total : s32 }

function bump(counter : Counter) {
    counter.total = counter.total + 1
}

function RENDER(request : dval) {
    var counter := Counter(0)
    bump(counter)
    bump(counter)
    print(counter.total, "\n")
}

A struct passed to a function shares identity with the caller's value. A function that writes a field changes what the caller sees. A dval crossing a unit boundary is copied instead.

Static type and field reflection

Struct values support three reflection expressions:

ExpressionStatic resultMeaning
value::type_namestringThe declared struct name after alias resolution.
value::sizes64The number of declared fields. This is not a byte size.
value::itemsdvalA map that describes the current field values.

value::items evaluates value once. It creates a snapshot and does not change the struct. Changes to the returned map do not change the struct.

The map uses each field name as a key. Each field entry has this shape:

{
    value: reflected_field_value,
    type_name: "resolved field type"
}

Use fields.name.value for a fixed field name. Use fields[key]["value"] when the field name comes from a value. Do not depend on map iteration to preserve declaration order.

Reflection converts fields as follows:

Struct fieldReflected value
Numeric scalar or boolA scalar dval. Use the field type constructor to recover the static type.
stringA string dval.
dvalA copied dynamic value.
StructA nested field map with the same entry shape.
Typed arrayA dval list. Each item uses the array item conversion.
Function valueA current-workspace callable with the exact function type.

Wide integers retain their exact value. The returned dval owns its callable references. A callable extracted into a typed local remains owned by that local. Serialization replaces callable values with none, as it does for other DValue callables.

The compiler rejects value::size and value::items when the receiver is not a struct. value::type_name works on all value types. The types guide defines its canonical names and explains parameter::type.

Choosing between a struct and a dval

Use a struct when the source defines the shape and the compiler must check it. Use a dval for request input, decoded data, database rows, and unit boundaries.

A single-field struct also acts as a constructor for its field type. For example, struct Meters { value : f64 } lets Meters accept an f64.

Exporting a struct

#exports publishes a struct's layout so another unit can name it after #import:

#exports Shape

struct Shape { value : s32 }

function RENDER(request : dval) {
    print(Shape(3).value, "\n")
}

Example

Capy

struct Job {
    id : u64
    state : string
}

function RENDER(request : dval) {
    var job := Job(u64(18446744073709551615), "queued")
    var fields := job::items
    print(u64(fields.id.value), " ", string(fields.state.value), "\n")
}