Skip to content

Instantly share code, notes, and snippets.

@jlongster
Last active December 2, 2019 11:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jlongster/8f6fed214ef8ea8d1851f318a135aa6a to your computer and use it in GitHub Desktop.
Save jlongster/8f6fed214ef8ea8d1851f318a135aa6a to your computer and use it in GitHub Desktop.
// Example code, see below for run/yield implementation. Note how we
// can even do yields across the stack, so this implements something
// more like coroutines than generators.
function foo() {
var x = Yield();
return x + 1;
}
var process = Run(function() {
console.log(Yield());
console.log(foo());
});
process.send("hello");
process.send(5);
// Output:
// hello
// 6
// run/yield implementation
var yieldStack = [];
function currentContinuation() {
return callCC(function(cont) {
cont(cont);
});
}
function Run(fn) {
let c = currentContinuation();
let y;
if(c) {
y = {
suspend: c,
send: function(val) {
let c = currentContinuation();
if(c) {
y.suspend = c;
y.resume(val);
}
}
};
yieldStack.push(y);
fn();
yieldStack.pop(y);
// A final suspend will jump back to the last place where we
// should be (either the last thing that sent a value or, if
// nothing was ever sent, ourselves)
y.suspend();
}
return y;
}
function Yield() {
if(yieldStack.length > 0) {
var c = currentContinuation();
var y = yieldStack[yieldStack.length - 1];
if(typeof c === 'function') {
y.resume = c;
y.suspend();
}
else {
y.resume = null;
return c;
}
}
throw new Error("Yield outside of Run");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment