Landin library reference source

core/spill

Shared: available on every enabled target.

A list that keeps an inline prefix and spills into allocated storage when it fills.

Queries use a pointer to avoid copying the inline array. Popping from spilled storage retains that allocation; release returns to an empty inline representation. Items need no zero image: pointers and atom-bearing records are stored like any other.

Items

Executable example

This complete program is maintained in the repository runtime tests. View source.

import core/mem
import core/spill

exercise: () -> (ok: bool) ! mem.out_of_memory | mem.empty | mem.out_of_bounds =
    ok = false
    mut backing: [32]u8 = zeroed
    mut state := mem.arena_over_unchecked(addr backing[0], 32)
    mut values := spill.new(item: i32, inline_slots: 1)
    try spill.push(values, state, i32(41))
    return when spill.length(addr values) <> 1 or mem.arena_used(state) <> 0
    slot: ptr mut i32 = try spill.at(values, usize(0))
    slot.val = 42
    value := try spill.pop(values)
    return when value <> 42
    _ = spill.pop(values) else (problem)
        ok = problem == mem.empty and spill.length(addr values) == 0
        return
    end
end exercise

public main: () -> (code: i32) =
    code = 1
    ok := exercise() else false
    if ok then
        code = 42
    end if
end main

list type

public list: type (item: type, fixed inline_slots: usize) = struct
    storage: spill_value(item, inline_slots)
end list

core/spill/spill.ldn:18

Vector with an inline prefix of inline_slots items that spills into allocator-backed storage when it fills. Only initialized slots are readable; no item needs a zero image.

at function

public at: (item: type, fixed inline_slots: usize,
            inout value: list(item, inline_slots), index: usize)
           -> (slot: ptr mut item from value) ! mem.out_of_bounds

core/spill/spill.ldn:127

Lend a writable item pointer, with the same binding lock as vec.at [0800]. Reports mem.out_of_bounds before forming an invalid pointer; end the pointer before a push or release.

capacity function

public capacity: (item: type, fixed inline_slots: usize,
                  value: ptr list(item, inline_slots)) -> (count: usize)

core/spill/spill.ldn:40

Return the inline capacity before spilling, or the backing vector capacity afterwards.

get function

public get: (item: type, fixed inline_slots: usize,
             value: ptr list(item, inline_slots), index: usize)
            -> (result: item from value) ! mem.out_of_bounds

core/spill/spill.ldn:113

Copy the indexed item without copying the container. Reports mem.out_of_bounds outside its initialized prefix.

length function

public length: (item: type, fixed inline_slots: usize,
                value: ptr list(item, inline_slots)) -> (count: usize)

core/spill/spill.ldn:33

Return the initialized item count. A read-only pointer accepts addresses of mutable and immutable containers without copying their inline storage.

new function

public new: (item: type, fixed inline_slots: usize)
            -> (value: list(item, inline_slots))

core/spill/spill.ldn:24

Create an empty inline vector without allocating. Unused inline slots have no readable item value.

pop function

public pop: (item: type, fixed inline_slots: usize,
             inout value: list(item, inline_slots))
            -> (removed: item from value) ! mem.empty

core/spill/spill.ldn:137

Remove and return the last item, retaining spill capacity. Reports mem.empty when empty; popping does not switch back to inline storage.

push function

public push: (item: type, fixed inline_slots: usize,
              provider: type is mem.allocator,
              escaping inout value: list(item, inline_slots),
              inout state: provider, escaping added: item)
             -> none ! mem.out_of_memory

core/spill/spill.ldn:64

Append inline while room remains, then spill to allocated storage. Allocation failure leaves the vector unchanged. Growth or the first spill invalidates old item views.

release function

public release: (item: type, fixed inline_slots: usize,
                 provider: type is mem.allocator,
                 inout value: list(item, inline_slots),
                 inout state: provider) -> none

core/spill/spill.ldn:152

Free any spill allocation through its original provider and reset to an empty inline vector. Does not clean up resources referenced by items.

used function

public used: (item: type, fixed inline_slots: usize,
              inout value: list(item, inline_slots))
             -> (view: []mut item from value)

core/spill/spill.ldn:101

Lend the initialized mutable prefix from inline or spill storage. The container and its backing must remain valid for the view's lifetime.