✓
Passing This code compiles and runs correctly.
Code
// DRAIN SWEEP — a rule whose entire `! row` body is `take(s[e])` with a
// discarded `| item` payload removes every row the invoked sweep visits.
// The per-row take reads every column into the item payload and swap-writes
// every column of the last row into the freed slot — work that exists for
// the payload's sake and to keep survivors live. A drain has neither, so
// the invoked sweep lowers to the clear unit's canonical reset: a
// generation bump over every issued slot (`0..hslot_next`), then len,
// freelist and the fresh cursor drop to zero and `ident` re-arms — no
// column traffic. Refilled rows take slots in fresh order rather than
// sequential take's LIFO pop order — observable only in handle bit
// values; the slot SET reissued is identical.
//
// `pool` qualifies: bare take on the bound row, discard item arm, no
// guard, no owned columns, no `! removed` observer.
// `guarded` declines: a `when` clause makes the walk selective — it keeps
// the removal-tolerant `while` that re-checks the index swap-remove just
// refilled.
// `ipool` qualifies WITH an index: take reseats nothing in the bucket
// map (dead handles resolve to no live row), so a teardown leaves the
// index exactly as sequential take would — and the pin proves it by
// routing a lookup over the drained store and again after a refill.
//
// Inserts sit above the rule declarations so the reactive per-insert fire
// (`__site_line > rule line`) stays out of the picture — the sweeps run
// only when the named rules are invoked.
import std/io
import std/store
import std/indexes
std/store:new(pool, capacity: 64) { hp: i64 }
std/store:new(guarded, capacity: 64) { hp: i64 }
std/store:new(ipool, capacity: 64) { tag: i64, hp: i64 }
std/indexes:store(ipool, tag)
std/store:insert(pool) { hp: 5 }
| row _ |> _
| full |> _
std/store:insert(pool) { hp: 50 }
| row _ |> _
| full |> _
std/store:insert(pool) { hp: 8 }
| row _ |> _
| full |> _
std/store:insert(guarded) { hp: 5 }
| row _ |> _
| full |> _
std/store:insert(guarded) { hp: 50 }
| row _ |> _
| full |> _
std/store:insert(guarded) { hp: 8 }
| row _ |> _
| full |> _
std/store:insert(ipool) { tag: 1, hp: 5 }
| row _ |> _
| full |> _
std/store:insert(ipool) { tag: 2, hp: 50 }
| row _ |> _
| full |> _
tor drain-pool {}
drain-pool = std/store:rule(pool)
! row e |> std/store:take(pool[e])
| item _ |> _
tor sweep-guarded {}
sweep-guarded = std/store:rule(guarded)
! row e when e.hp <= 10 |> std/store:take(guarded[e])
| item _ |> _
tor drain-ipool {}
drain-ipool = std/store:rule(ipool)
! row e |> std/store:take(ipool[e])
| item _ |> _
drain-pool()
sweep-guarded()
drain-ipool()
std/io:print.ln("pool {{ pool.len:d }}")
std/io:print.ln("guarded {{ guarded.len:d }}")
std/io:print.ln("ipool {{ ipool.len:d }}")
// a routed lookup over the drained store answers none — the bucket's
// dead members skip, never resolve
std/store:query(ipool)
! first p when p.tag == 1 |> std/io:print.ln("stale {{ p.hp:d }}")
| none |> std/io:print.ln("ipool drained")
// a standing rule still stands: drain lowered the sweep, not the enters —
// this insert (site line past the rule's) fires the take body and the
// new row dies instantly, so the routed lookup still answers none
std/store:insert(ipool) { tag: 2, hp: 99 }
| row _ |> _
| full |> _
std/io:print.ln("after-refill {{ ipool.len:d }}")
std/store:query(ipool)
! first p when p.tag == 2 |> std/io:print.ln("stale {{ p.hp:d }}")
| none |> std/io:print.ln("rule still stands")
Actual
pool 0
guarded 1
ipool 0
ipool drained
after-refill 0
rule still stands
Expected output
✓ Zig✓ JavaScriptpool 0
guarded 1
ipool 0
ipool drained
after-refill 0
rule still stands
Flows
flow ~new click a branch to expand · @labels scroll to their anchor
new (pool, capacity: 64, source: hp: i64)
flow ~new click a branch to expand · @labels scroll to their anchor
new (guarded, capacity: 64, source: hp: i64)
flow ~new click a branch to expand · @labels scroll to their anchor
new (ipool, capacity: 64, source: tag: i64, hp: i64)
flow ~store click a branch to expand · @labels scroll to their anchor
store (expr: ipool, tag, source: <implicit_source>)
flow ~insert click a branch to expand · @labels scroll to their anchor
insert (pool, source: hp: 5)
flow ~insert click a branch to expand · @labels scroll to their anchor
insert (pool, source: hp: 50)
flow ~insert click a branch to expand · @labels scroll to their anchor
insert (pool, source: hp: 8)
flow ~insert click a branch to expand · @labels scroll to their anchor
insert (guarded, source: hp: 5)
flow ~insert click a branch to expand · @labels scroll to their anchor
insert (guarded, source: hp: 50)
flow ~insert click a branch to expand · @labels scroll to their anchor
insert (guarded, source: hp: 8)
flow ~insert click a branch to expand · @labels scroll to their anchor
insert (ipool, source: tag: 1, hp: 5)
flow ~insert click a branch to expand · @labels scroll to their anchor
insert (ipool, source: tag: 2, hp: 50)
subflow ~drain-pool click a branch to expand · @labels scroll to their anchor
rule (pool)
subflow ~sweep-guarded click a branch to expand · @labels scroll to their anchor
rule (guarded)
subflow ~drain-ipool click a branch to expand · @labels scroll to their anchor
rule (ipool)
flow ~drain-pool click a branch to expand · @labels scroll to their anchor
drain-pool
flow ~sweep-guarded click a branch to expand · @labels scroll to their anchor
sweep-guarded
flow ~drain-ipool click a branch to expand · @labels scroll to their anchor
drain-ipool
flow ~print.ln click a branch to expand · @labels scroll to their anchor
print.ln (expr: "pool {{ pool.len:d }}")
flow ~print.ln click a branch to expand · @labels scroll to their anchor
print.ln (expr: "guarded {{ guarded.len:d }}")
flow ~print.ln click a branch to expand · @labels scroll to their anchor
print.ln (expr: "ipool {{ ipool.len:d }}")
flow ~query click a branch to expand · @labels scroll to their anchor
query (ipool)
flow ~insert click a branch to expand · @labels scroll to their anchor
insert (ipool, source: tag: 2, hp: 99)
flow ~print.ln click a branch to expand · @labels scroll to their anchor
print.ln (expr: "after-refill {{ ipool.len:d }}")
flow ~query click a branch to expand · @labels scroll to their anchor
query (ipool)
Test Configuration
MUST_RUN LANGUAGES: zig js
Post-validation Script:
#!/bin/bash
# Emitted-shape oracle for the drain lowering. `pool`'s rule body is a
# bare `take(pool[e])` with a discard `| item`, so its invoked sweep is
# the clear unit's canonical reset: every issued slot's generation
# bumps once (`0..hslot_next` covers live rows and slots freed by
# earlier takes), then len, the freelist and the fresh cursor drop to
# zero and `ident` re-arms — no per-row resolve, no column reads, no
# freelist materialization. The observable difference vs a per-row
# take walk is refill pop order: reset reissues slots in fresh order,
# the same slot SET either way. `guarded` carries a `when` clause, so
# its sweep keeps the removal-tolerant `while` that re-checks the index
# swap-remove just refilled.
set -u
if [ ! -f output_emitted.zig ]; then
echo "FAIL: no output_emitted.zig"
exit 1
fi
# --- pool lowered to the drain reset ---
if ! grep -q 'const __koru_dn = __koru_store_pool\.len' output_emitted.zig; then
echo "FAIL: pool's sweep did not lower to the drain reset"
exit 1
fi
POOL_SWEEP=$(awk '/qsweep_pool/,/^ };$/' output_emitted.zig)
if ! printf '%s' "$POOL_SWEEP" | grep -q '__koru_hslot_gen\[__koru_i\] +%= 1'; then
echo "FAIL: drain lost the issued-slot generation bump"
exit 1
fi
if ! printf '%s' "$POOL_SWEEP" | grep -q '__koru_hslot_next = 0'; then
echo "FAIL: drain did not reset the fresh-slot cursor"
exit 1
fi
if ! printf '%s' "$POOL_SWEEP" | grep -q '__koru_hslot_free_len = 0'; then
echo "FAIL: drain did not drop the freelist"
exit 1
fi
if ! printf '%s' "$POOL_SWEEP" | grep -q '__koru_ident = true'; then
echo "FAIL: drain did not re-arm the identity map"
exit 1
fi
if printf '%s' "$POOL_SWEEP" | grep -q '__koru_store_pool\.hp\['; then
echo "FAIL: drain still moves column data — the payload it discards"
exit 1
fi
if printf '%s' "$POOL_SWEEP" | grep -q '__koru_len_before'; then
echo "FAIL: pool kept the per-row tolerant loop — drain did not fire"
exit 1
fi
# --- ipool lowered too: an index decl does not disqualify ---
IPOOL_SWEEP=$(awk '/qsweep_ipool/,/^ };$/' output_emitted.zig)
if ! printf '%s' "$IPOOL_SWEEP" | grep -q 'const __koru_dn = __koru_store_ipool\.len'; then
echo "FAIL: indexed store's take-only rule did not lower to the drain reset"
exit 1
fi
if printf '%s' "$IPOOL_SWEEP" | grep -q '__koru_store_ipool\.\(tag\|hp\)\['; then
echo "FAIL: indexed drain still moves column data"
exit 1
fi
# --- guarded declined: removal-tolerant while kept for it ---
GUARDED_SWEEP=$(awk '/qsweep_guarded/,/^ };$/' output_emitted.zig)
if ! printf '%s' "$GUARDED_SWEEP" | grep -q '__koru_len_before'; then
echo "FAIL: guarded sweep lost its removal-tolerant while"
exit 1
fi
# --- JS lane: same lowering, JS spelling ---
if [ -f output_emitted.js ]; then
if ! grep -q 'const __koru_dn = __koru_store_pool\.len' output_emitted.js; then
echo "FAIL: JS lane did not lower pool's sweep to the drain"
exit 1
fi
if ! grep -q '% 2097152' output_emitted.js; then
echo "FAIL: JS drain lost the 2^21-wrapping generation bump"
exit 1
fi
if ! grep -q '__koru_hslot_next = 0' output_emitted.js; then
echo "FAIL: JS drain did not reset the fresh-slot cursor"
exit 1
fi
fi
echo "PASS: take-only rule lowers to the reset drain; guarded rule keeps tolerant sweep"
exit 0