with
Symbol: compile/with
Syntax: (with [name? expr] body ...)
Optional name binds the context manager’s enter result for the body. If
omitted, only expr and body ... are given (no binding).
Use-case: Single-shot context manager: evaluate expr to get a manager,
call enter (auto-await if needed), run body in a fresh operand stack block,
then call exit on normal or exception exit. A continuation transfer out of
the body runs the manager’s exit as an exception would, and the instance is
finished: single-shot means each with instance enters once and exits once,
and a transfer back into a captured body does not enter it again. Use
dyn-with for a manager that should wind and unwind on every
transfer.
Behaviour: Compiles expr, emits PUSH_WITH with optional name (constant
pool index or no-binding sentinel), compiles body with helper_begin, emits
POP_WITH. PUSH_WITH looks up the WITH extent at its PC and stores
resume_pc = pop_pc + 1 on the node for use when exit swallows an exception.
The expression value is the body’s value; when the exit swallows an exception
the value is None. The exit’s own return decides only whether the exception
is swallowed and is never the value. Both sync and async context managers
are supported (VM auto-awaits enter/exit when they return awaitables). See
dyn-with for the multi-shot variant and
PUSH_WITH / POP_WITH in the VM reference.
Examples:
;; With binding
(with [f (open-file path)]
(read-all f))
;; Without binding
(with [(make-lock)]
(do-work))