<h2>Motivation</h2>
<p>I have seen many places saying that CPST (continuation-passing style transformation) can express all control flows, but the examples they give are relatively simple and do not involve any loops.</p>
<p>It may be because most of the languages that adopt CPS transform  are functional languages, and there are no loops.</p>
<p>I wonder if this technique can be used for modern control flow, such as <code>break</code>, <code>yield</code>, <code>await</code>.</p>
<h2>Attempt</h2>
<p>I try to do CPS transform for the following for loop:</p>
<pre class="lang-js prettyprint-override"><code>function iter(list: List&lt;Integer&gt;): Integer {
    for n in list {
        if n &lt; 0 {
            continue
        } else if n == 0 {
            break
        } else {
           return n
        }
    }
    return -1
}
</code></pre>
<p>After trying, I found that adding a continuation parameter of break is enough.</p>
<ul>
<li><code>continue</code> is equivalent to the recursive call itself</li>
<li><code>break</code> is equivalent to passing the continuation of the loop itself, that is, the statement after the loop end.</li>
<li><code>return</code> is equivalent to passing the continuation of the environment function.</li>
</ul>
<p><em>This is my personal understanding, I don't know if it is correct.</em></p>
<pre class="lang-js prettyprint-override"><code>function cps_iter(list: List&lt;Integer&gt;, ret: Continuation&lt;Integer&gt;) {
    let cps_for = (index: Integer, br: Continuation) =&gt; {
        if (index &gt;= list.length) {
            br()
        } else {
            let n = list[index]
            if (n &lt; 0) {
                cps_for(index + 1) 
            } else if n == 0 {
                br()
            } else {
                ret(n)
            }
        }
    }
    loop(0, () =&gt; { ret(-1) })
}
</code></pre>
<h2>Problem</h2>
<p>But for the generator (function with yield), I can't figure out how to compile it, who is the continuation of <code>yield</code>?</p>
<pre class="lang-js prettyprint-override"><code>function* iter(list: List&lt;Integer&gt;): Iterator&lt;Integer&gt; {
    for n in list {
        if n &lt; 0 {
            continue
        } else if n == 0 {
            break
        } else {
            yield n
        }
    }
    return -1
}
</code></pre>
<ol>
<li>I'm wondering if my CPS form of the for loop is correct?</li>
<li>How to compiles generators with <code>yield</code> and coroutines with <code>yield*</code>/<code>await</code> to CPS?</li>
</ol>

<generators><coroutines><continuation-passing-style>
How continuations compiles generators and coroutines?
CC BY-SA 4.0
2023-07-04T12:07:48.217Z
There is no such word as "Attemption" it sounds like an attempt to grab attention!
Bruce Adams
<p>On a yield you need to do 2 things, execute the continuation that will handle the yielded value and make sure that continuation can in turn continue the loop.</p>
<p>So to solve that you pass the continuation of the continued loop itself.</p>
<p>This is a bit more involved because you also need to pass state through that makes the loop continue correctly.</p>
<p>This is equivalent to first transforming from a coroutine into a statemachine and on yield set the current state in a struct which gets passed to the caller and on resume check the state struct to jump to the correct place in the coroutine.</p>

CC BY-SA 4.0
2023-07-04T12:04:38.873Z
2023-07-04T12:04:38.873Z
ratchet freak
CC BY-SA 4.0
2023-07-06T06:01:54.050Z
The state machine should not be necessary. I have heard in HN that the generator can be directly implemented with `make-generator` in the scheme without additional syntax changes.
Aster
# How continuations compiles generators and coroutines?
Posted by: username_0 on 2023-07-04
Motivation
I have seen many places saying that CPST (continuation-passing style transformation) can express all control flows, but the examples they give are relatively simple and do not involve any loops.
It may be because most of the languages that adopt CPS transform  are functional languages, and there are no loops.
I wonder if this technique can be used for modern control flow, such as break, yield, await.
Attempt
I try to do CPS transform for the following for loop:
function iter(list: List): Integer {
    for n in list {
        if n < 0 {
            continue
        } else if n == 0 {
            break
        } else {
           return n
        }
    }
    return -1
}

After trying, I found that adding a continuation parameter of break is enough.

continue is equivalent to the recursive call itself
break is equivalent to passing the continuation of the loop itself, that is, the statement after the loop end.
return is equivalent to passing the continuation of the environment function.

This is my personal understanding, I don't know if it is correct.
function cps_iter(list: List, ret: Continuation) {
    let cps_for = (index: Integer, br: Continuation) => {
        if (index >= list.length) {
            br()
        } else {
            let n = list[index]
            if (n < 0) {
                cps_for(index + 1) 
            } else if n == 0 {
                br()
            } else {
                ret(n)
            }
        }
    }
    loop(0, () => { ret(-1) })
}

Problem
But for the generator (function with yield), I can't figure out how to compile it, who is the continuation of yield?
function* iter(list: List): Iterator {
    for n in list {
        if n < 0 {
            continue
        } else if n == 0 {
            break
        } else {
            yield n
        }
    }
    return -1
}


I'm wondering if my CPS form of the for loop is correct?
How to compiles generators with yield and coroutines with yield*/await to CPS?
**Tags:** generators coroutines continuation-passing-style
> **Comments:**
> **username_1**: There is no such word as "Attemption" it sounds like an attempt to grab attention!  
---
## 1 answers
### Answer by username_2 on 2023-07-04. Score: 3
On a yield you need to do 2 things, execute the continuation that will handle the yielded value and make sure that continuation can in turn continue the loop.

So to solve that you pass the continuation of the continued loop itself.

This is a bit more involved because you also need to pass state through that makes the loop continue correctly.

This is equivalent to first transforming from a coroutine into a statemachine and on yield set the current state in a struct which gets passed to the caller and on resume check the state struct to jump to the correct place in the coroutine.
> **Comments:**
> **username_0** (2023-07-06): The state machine should not be necessary. I have heard in HN that the generator can be directly implemented with `make-generator` in the scheme without additional syntax changes.  
---
