Skip to content

Nucleus Z80 Runtime and Backend Contract 0.103

← 2. Target and resource model · Contents · 4. Program storage and startup →

3. Runtime representation

3.1 Scalar values

u8 occupies one byte and ranges from 0 through 255. boolean occupies one byte and is exactly 0 or 1. u16 occupies two little-endian bytes and ranges from 0 through 65,535. A compiler or runtime helper must not depend on another Boolean representation.

Arithmetic width and wraparound follow the language specification. A value held temporarily in a Z80 register pair may use a wider carrier, but storage and observable results retain their declared widths. Checked narrowing tests the complete u16 value before producing a u8.

3.2 Records and arrays

Records are packed in field-declaration order with no padding. Field extents are:

  • one byte for u8 and boolean;
  • two little-endian bytes for u16; and
  • the complete inline extent for a record, fixed array, or bounded string.

A fixed array stores its elements consecutively. Its stride is the complete element extent. Neither a record nor an array stores a runtime type tag, field table, length word, or address.

Compiler metadata retains every complete aggregate extent, fixed-array length, fixed-array stride, and record-field offset as an unsigned 16-bit value. The same word-sized extent machinery applies to records, arrays, and bounded strings. This is compiler metadata only; it adds no header to an aggregate object.

3.3 Bounded strings

string[N] occupies N + 2 bytes. Byte zero is the current logical length L; bytes 1 through N are the content capacity; and byte N + 1 is always $00. The compiler writes that final byte while building the static image, and no runtime operation writes it again. Bytes L + 1 through N are also zero. The invariant is 0 <= L <= N, and the complete object extent is at most 255 bytes because the source capacity is at most 253. This string-specific limit does not constrain the complete extent of a containing record or array.

The address carrier + 1 is always zero-terminated within N + 1 bytes, so a terminator-consuming routine can never read past the end of the object. This does not make the payload a C string of exactly L bytes. Embedded zero bytes are ordinary Nucleus content, but a C consumer stops at the first one. The guarantee prevents a runaway read; it does not preserve counted length for a C consumer.

An aggregate carrier for a bounded string addresses its length byte. Reading .length checks the complete object and the length invariant. Indexing checks index < L and addresses byte 1 + index. Byte assignment changes one existing content byte and does not change the length.

3.4 Aggregate carriers

An aggregate parameter or result is carried as one 16-bit address. Its exact record type, array element type and length, or string capacity remains compiler metadata. The runtime address has no source type tag and is never a source integer. Only compiler-generated field selection, checked indexing, parameter transfer, result transfer, and copying may consume it.