✓
Passing This code compiles and runs correctly.
Code
// IMPLEMENTED — a same-typed transition CONTINUES its binding.
//
// `advance` consumes `h` (<!open|!active>) and re-mints <active!> on the same
// handle: `-> h` IS the transition written out. The entity is `h` throughout.
// Today the caller must spend `h` and re-bind the re-minted handle under a new
// name (`app/held:advance(h): h2 |> close(h2)`), which carries no information —
// the new symbol is the old pointer with a new state. The intended rule: the
// sole same-typed survivor advances `h` in place, so `close` just uses `h`.
//
// Green: the `desugarHandleContinuation` pass rewrites `advance(h)` into the
// explicit `: __cont0` bind and points `close` at it (see output_emitted.zig).
import app/held
import std/io
app/held:open()
| opened h |> app/held:advance(h) |> app/held:close(h) |> std/io:print.ln("advanced in place")
| err e |> std/io:print.ln("err: {{ e:s }}")
Supporting Files
// A held resource whose state ADVANCES on the same handle — the shape raylib's
// window uses (opened -> active), reduced to its minimum. `advance` consumes
// <!open|!active> and re-mints <active!> on the SAME pointer (`-> h` is the
// transition written out); nothing here needs a second symbol.
const std = @import("std");
pub const Handle = struct { _token: u8 };
~pub tor open { }
| opened *Handle<open!>
| err string
~proc open|zig {
const h = std.heap.page_allocator.create(Handle) catch unreachable;
h.* = Handle{ ._token = 0 };
return .{ .opened = h };
}
~pub tor advance { h: *Handle<!open|!active> } -> *Handle<active!>
~advance -> h
~pub tor close { h: *Handle<!active> }
~proc close|zig {
std.heap.page_allocator.destroy(h);
}
Actual
advanced in place
Expected output
advanced in place
Flows
flow ~open click a branch to expand · @labels scroll to their anchor
open
Test Configuration
MUST_RUN