Lyric
A statically typed application language with a bytecode VM — standalone, and embeddable in a host with a capability-based sandbox.
What changed in v2.2.0 — 2026-08-20
The A8 wave: both coroutine edges Erato's register filed after building its cutscene driver,
plus one the fix uncovered. The bytecode format stays 3.2; a module that never calls
next() loads on every 2.x runtime. Four conformance cases activate with this release
(//! since: 2.2.0); the suite stands at 85.
Added
co.next()— the safe pull. It advances a coroutine exactly likeresumeand answers?T: the value, ornullonce the body has run to its end — andnullstays the answer on every further call, whereresumekeeps its promised panic. ACoroutine<void>answersbool(did it advance?), sowhile (p.next()) { }drives it out; aCoroutine<?T>refuses the form (LYR-SEM0080) becausenullwould mean two things there — drive it withresumeand a protocol of your own. The name and shape areIterator<T>.next()'s on purpose.A query that does NOT pull (
isDone) was probed and rejected: a pull-based coroutine cannot know whether another value comes without running the body, which is why no generator API in Python, JavaScript or C# has one. The pull with an end signal is the honest form.On the wire, exhaustion is read back through the compiler-bound native
std.core.coroutineIsDone; an older runtime rejects a module that usesnext()at load time with that name in the message — the format's designed forward path.
Fixed
Coroutine<T>works as a field type. A class or struct field, and a type argument (List<Coroutine<T>>), used to be refused withLYR-IR0001("type 'Coroutine' (not a class)") while the same type worked as a parameter and a local. A driver now holds its coroutines directly instead of hiding each behind a captured closure.- A bare
return;in the middle of a coroutine body works. It compiled to a valueless return from a value-yielding body — an internal compiler error in Debug, malformed bytecode in Release, and the coroutine was never marked exhausted. It is now exactly the run-through exit: the nextresumepanics, the nextnext()answersnull. (return;in tail position, the common form, was always fine.)