This library is in flux. APIs may change without notice. Generated from source with koruc 0.1.7 on 9/16/2026.
Pump
~import std/pumpKoru Standard Library: Pump — compile-time composition of participants.
pump.kz · 3 tors
Koru Standard Library: Pump — compile-time composition of participants. · 39 more lines
Koru Standard Library: Pump — compile-time composition of participants.
std/pump:create(main)
| drained |> std/io:print.ln("all participants retired")
std/pump(main)
! step |> tick-step()
! live |> tick-live()
! wait i |> tick-wait(i: i)
std/pump:run(main)
! idle |> std/time:sleep-ms(ms: 2)
A PARTICIPANT is anything that can answer up to three verbs:
step() -> i32 advance every live instance once; return how many made
progress this pass. Required.
live() -> i64 how many instances are live; 0 = retired. Absent = the
participant is immortal — it never drains the pump.
wait(i) -> { fd: i32, wait_ns: i128 } instance i's blocking interest:
fd = -1 for none, wait_ns a relative re-poll duration
(maxInt = never). Optional; unarmed participants
contribute nothing to the union wait.
The join site `std/pump(name)` carries the verbs as `!` arms — the same
reference form `std/store(name) ! field` uses for standing watches. Pass
order is join order (document order). Each arm's body is compiled into a
generated unit `__pump_<name>_{step,live,wait}_<idx>` — the verbs are
ordinary calls, so a participant is any author-written unit: a module's
singleton state, a hand-managed array, or a `! step` store (which exposes
exactly these verbs as `<store>-step` / `<store>-live` / `<store>-wait`).
The pump knows none of that — it calls names.
`run` drives passes until every participant's `live` answers 0 — a pump of
only immortals runs forever, which is honest: that pump IS the program's
event loop. When a pass progresses nothing, `run` fires `! idle` (an
effect, inside the loop); unarmed, it composes the wait itself — one
`poll()` over every joined `wait` interest, capped by the nearest
`wait_ns`, or a 1ms breath when nothing was declared.
~[keyword|comptime|transform] pub tor create {
expr: Expression,
invocation: *const Invocation,
item: std/compiler:*const Item,
program: std/compiler:*const Program,
reporter: std/compiler:*ErrorReporter,
allocator: std.mem.Allocator
} -> SiteResult// PUMP.DEFAULT — the bare `std/pump(name)` reference form: a participant JOIN.
//
// std/pump(main)
// ! step |> <call> — required, `-> i32` progress count
// ! live |> <call> — optional, `-> i64` live-instance count
// ! wait i |> <call(i)> — optional, `-> { fd, wait_ns }` interest
//
// Each arm compiles into `__pump_<name>_{step,live,wait}_<idx>`; run
// enumerates them. The verbs are ordinary calls — the pump never learns what
// implements them.
~[keyword|comptime|transform] pub tor default {
expr: Expression,
invocation: *const Invocation,
item: std/compiler:*const Item,
program: std/compiler:*const Program,
reporter: std/compiler:*ErrorReporter,
allocator: std.mem.Allocator
} -> SiteResult// PUMP.RUN — drive a declared pump until every participant drains.
//
// std/pump:run(main)
// ! idle |> ...
//
// Enumerates the joined `__pump_<name>_step_<i>` units and emits
// `__pump_run_<name>`: while any participant's `live` counts rows, step each
// in join order. A pass with zero progress fires `! idle` — armed, the arm
// runs in the loop; unarmed, the union wait collects every `wait` unit's
// interests and polls once, or breathes 1ms when nothing was declared.
~[keyword|comptime|transform] pub tor run {
expr: Expression,
invocation: *const Invocation,
item: std/compiler:*const Item,
program: std/compiler:*const Program,
reporter: std/compiler:*ErrorReporter,
allocator: std.mem.Allocator
} -> SiteResult