Master the fundamental concepts of build a bytecode vm through this focused micro-challenge.
Coroutines suspend mid-function and resume later with local state intact. Unlike threads, they yield explicitly. Lua's \`coroutine.yield\`, Python generators, and \`asyncio\` all build on this save-restore pattern.
A coroutine object stores its own \`pc\`, operand stack, and frames:
The producer-consumer pattern is the classic demo: a coroutine generates values, yielding each one; the driver resumes it to pull the next.
For example, a coroutine yielding 1, 2, 3 prints those values across three resume calls without threads or preemption.
States to track: \`CREATED\`, \`RUNNING\`, \`SUSPENDED\`, \`DEAD\`.
Only one coroutine runs at a time in this model, so you avoid locks entirely. That cooperative guarantee is why Lua coroutines and Python generators can mutate VM state without the synchronization threads demand.
This exercise asks you to add coroutine objects with independent execution state. You will implement \`YIELD\`, \`RESUME\`, and a producer coroutine that the main program drives in a loop.
You will use the same mental model here when reading production interpreter source later in the track. Sketch one concrete input on paper, predict the outcome, then confirm with code. That discipline catches logic errors early and makes debugging far faster when you extend the implementation in follow-on tasks.
Add coroutine support to your VM in C.
Requirements:
Test:
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
All starter code and reference implementations are available for your local setup.
View on Github