:title
struct

:sig
struct Name { field : type, ... }

:content
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:

:content

```capy
struct Point
{
	x : s32,
	y : s32
}

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

:content

## Fields are mutable, the binding is shared

Reading and writing fields uses `.`:

:content

```capy
struct Counter
{
	total : s32
}

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

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

:content

A struct passed to a function is the caller's object. A function that writes a field changes what the caller sees. The same holds for a `dval`, including one passed to a component or an exported function.

## Static type and field reflection

Struct values support three reflection expressions:

| Expression | Static result | Meaning |
| --- | --- | --- |
| `value::type_name` | `string` | The declared struct name after alias resolution. |
| `value::size` | `s64` | The number of declared fields. This is not a byte size. |
| `value::items` | `dval` | A map that describes the current field values. |

`value::items` evaluates `value` once. It builds a new map 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:

```capy
{
	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 field | Reflected `value` |
| --- | --- |
| Numeric scalar or `bool` | A scalar `dval`. Use the field type constructor to recover the static type. |
| `string` | A string `dval`. |
| `dval` | A copied dynamic value. |
| Struct | A nested field map with the same entry shape. |
| Typed array | A `dval` list. Each item uses the array item conversion. |
| Function value | A function or closure of the current request 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`.

:example capy render
struct Job
{
	id : u64
	state : string
}

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

:content

## 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`:

:content

```capy
#exports Shape

struct Shape
{
	value : s32
}

function RENDER()
{
	print(Shape(3).value, "\n")
}
```

:see-group
constructors

:see
capy-03-values-and-types
capy-07-collections-and-records
capy-08-dynamic-values
type/dvalue
get_type_name
