🎓 A1Learner
🔍
0 of 49 lessons completed

Lua Coroutine State Machines

A coroutine state machine is a coroutine whose position between resumes is its state. Each resume runs the machine until its next yield, so each resume advances the machine by exactly one step.

A variable tracks the turnstile state

The turnstile starts locked. A coin unlocks it and a push locks it again.

local state = "locked"
local event = "coin"
if state == "locked" and event == "coin" then
  state = "unlocked"
end
print(state)
event = "push"
if state == "unlocked" and event == "push" then
  state = "locked"
end
print(state)

A coroutine yields one state per resume

The coroutine yields locked, then unlocked, then locked. Each resume delivers the next state.

local machine = coroutine.create(function()
  coroutine.yield("locked")
  coroutine.yield("unlocked")
  coroutine.yield("locked")
end)
local ok, state = coroutine.resume(machine)
print(state)
ok, state = coroutine.resume(machine)
print(state)
ok, state = coroutine.resume(machine)
print(state)

Events passed to resume drive transitions

The machine yields its state and waits. Each resume passes the next event, and the machine prints the state it moves to.

local machine = coroutine.create(function()
  local event = coroutine.yield("locked")
  if event == "coin" then
    event = coroutine.yield("unlocked")
  end
  if event == "push" then
    coroutine.yield("locked")
  end
end)
local ok, state = coroutine.resume(machine)
print(state)
ok, state = coroutine.resume(machine, "coin")
print(state)
ok, state = coroutine.resume(machine, "push")
print(state)

Example

local machine = coroutine.create(function()
  local state = "locked"
  while true do
    local event = coroutine.yield(state)
    if state == "locked" and event == "coin" then
      state = "unlocked"
    elseif state == "unlocked" and event == "push" then
      state = "locked"
    end
  end
end)
local events = {"coin", "push", "push", "coin", "push"}
local ok, state = coroutine.resume(machine)
print(state)
for _, event in ipairs(events) do
  ok, state = coroutine.resume(machine, event)
  print(state)
end

Key points

  • State: the situation the machine is in, such as locked or unlocked.
  • Event: an input passed to resume that tells the machine what just happened.
  • Transition: the move from one state to another in response to an event.
  • Yield point: the place where the machine pauses and waits for the next event.
  • Resume step: one resume advances the machine through exactly one transition.

In this example, the machine starts locked and yields its state before each event. A coin unlocks it and a push locks it again, while a push on a locked turnstile leaves it locked. The printed states follow the five events in order.

Note

the coroutine remembers its state for free, because its position in the code is the state.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

A turnstile machine is unlocked and receives a push event. What state is it in afterwards?