✓
Passing This code compiles and runs correctly.
Code
// PINS: a subflow chaining VOID steps runs every one of them, in order — and
// the COUNT of them is the assertion.
//
// `run-one` chains four void steps off one binding, two of which are `work`,
// and `~for` drives it ten times: exactly twenty `Work` lines. The count is
// what this test holds, because a chain that silently dropped a step would
// still compile, still run, and still exit 0 — printing ten. Nothing else
// distinguishes the two outcomes.
//
// A void step has no result to switch on, so it cannot be lowered the way a
// branching step is: `switch (nested_result_0) { . => || { … } }` is not Zig,
// and a void type cannot be switched on at all. The sequential-call lowering
// that stands in its place is what the twenty lines guard.
//
// Sibling: 210_176, the same "every step runs" claim for a chain whose HEAD is
// a comptime transform rather than a handler call.
~import std/control
const std = @import("std");
const Resource = struct { id: usize };
~tor create {} -> *Resource<active!>
~proc create|zig {
const r = std.heap.page_allocator.create(Resource) catch unreachable;
r.* = Resource{ .id = 42 };
return r;
}
~tor work { r: *Resource<active> }
~proc work|zig {
std.debug.print("Work\n", .{});
}
~tor destroy { r: *Resource<!active> }
~proc destroy|zig {
std.heap.page_allocator.destroy(r);
}
~tor run-one {}
~run-one = create(): r |> work(r) |> work(r) |> destroy(r)
~for(0..10)
! each _ |> run-one()
| done |> _
Actual
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Expected output
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Work
Flows
subflow ~run-one click a branch to expand · @labels scroll to their anchor
create
flow ~for click a branch to expand · @labels scroll to their anchor
for (0..10)
Test Configuration
MUST_RUN