Guide
Tasks and scopes
Asynchronous behaviour with an owner, on three clocks that are not interchangeable.
Asynchronous behaviour here is a task with an owner rather than a promise nobody holds. What that buys over a promise is cancellation, an owner, a chosen clock, and a scheduler the host can change later without changing every script.
A scope cancels what it owns
Leaving a scope cancels whatever has not finished, so detached work cannot outlive the thing that started it. A scope opened inside a plain function is refused: it would be left on the same tick it was opened, cancelling everything spawned into it.
// A task is asynchronous behaviour with an owner.
//
// `spawn` starts one inside a `scope`, and leaving the scope cancels whatever has not finished.
// That is the rule that stops detached work outliving the thing that created it, and it is
// structural here rather than something every author has to remember.
//
// `begin` is a task rather than a function, and the compiler insists: a scope opened in a function
// would be left on the same tick it was opened, cancelling everything spawned into it.
data Signal {
fired: bool = false
count: u32 = 0
}
task pulse(signal: mut Signal) {
await fixedTime(250ms)
signal.count = signal.count +| 1
signal.fired = true
}
task begin(signal: mut Signal) {
scope effect {
spawn pulse(signal)
await fixedTime(1s)
}
}
Three clocks, and they are not interchangeable
fixedTime is the simulation step and the only clock a deterministic task may await. frameTime is the clamped frame delta and is the one to animate against, so a stall cannot advance two seconds of animation in a single frame. wallTime is the same gap untouched, and is for diagnostics.
Awaiting a clock and reading one are different rules
Inside a deterministic function, awaiting the fixed step is accepted: a resume point counted in whole ticks is a function of the tick count and replays identically. Reading a delta is refused, because a simulation is given its delta as a parameter, and one that reached out for it has stopped being a function of its inputs.