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.7.0 — 2026-08-21
One overload, and with it the debugger reaches the shape an embedded script actually has. The bytecode format stays 3.3 and the language gains nothing.
Added
LoadedProgram.Invoke(index, debugController, args). Since 2.3 the toolchain has had breakpoints, stepping, the call stack, locals and evaluate — offered at exactly one place,RunEntry, which starts a program at itsmain. A game has nomain: its entry points are the functions a host calls once per frame throughInvoke, so none of that machinery was reachable from a host. The budget got this shape in 2.4; the debugger gets it now.The call runs on the caller's thread and a breakpoint parks it, so the commands come from another one — the same arrangement
DebugController.Startmakes with the roles swapped. A controller survives across calls: its breakpoints hold for every invocation it is passed to, and a call into a function nothing breaks on returns without stopping. NoExitedevent arrives, because nothing ended — the host simply stopped calling — so the event stream stays open while the game runs.There is deliberately no overload taking a debugger and a budget together: a session parked at a breakpoint would spend a budget on standing still.
What it does not do is keep a window drawing: the parked thread is the game's own. Drawing through a breakpoint needs an interpreter that can return to its host mid-instruction and resume later, and this one keeps its frame stack on the CLR stack. Guide 21 says so rather than leaving it to be discovered.