Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

Coroutines

Coroutines allow a function to suspend and yield a result in the middle of the function. This can be used for lazy generation of results.

Coroutines are hence similar to streams, where the state of the stream contains the position of the yield of the last value.

Applications of Coroutines

TBW: It is unclear to me what the main application of coroutines is, where do they provide a real benefit over streams?

Implementation of Coroutines

Any non-recursive coroutine can be mapped to a stream by performing these steps:

  • turn all local fields of the coroutine into fields of the stream such that they keep there values for later calls.
  • number all yield instructions
  • add fields last_yield and last_result to the stream, originally initialize last_yield to -1.
  • implement a yield v as

    if last_yield = n
      last_yield := -1
    else
      last_yield := n; result := v
        

    where n is the number of the yield instruction.

  • For all code dominated by a yield, put that code into a condition if last_yield < 0 such that we drop out of the current function directly as soon as last_yield was set to a non-negative value.
  • For all code on the shortest path from the function entry to a yield instruction, put that code into a condition if last_yield < 0. For all conditionals on the path, add last_yield = n || before the condition if the if-branch leads to the yield, otherwise add last_yield != n && if the else-branch leads to the yield. Then, any call to that function will directly fall through to the code of the yield instruction and continue execution there.
  • The last two steps could be simplified if the implementation could perform a goto from the yield instruction to the functions end and from function entry to the yield instruction.

TBD: Do recursive co-routines make any sense?

last changed: 2024-06-28