Skip to content

Instantly share code, notes, and snippets.

@yelouafi
Last active November 29, 2020 07:40
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 yelouafi/13ad4335f92e448f625930bb390da532 to your computer and use it in GitHub Desktop.
Save yelouafi/13ad4335f92e448f625930bb390da532 to your computer and use it in GitHub Desktop.
callcc with javascript generators
function*example() {
const x = 10
const y = yield callcc(function*(k) {
// ...
yield k(20)
throw "Unreachable code"
})
console.log(x + y)
}
stepGen(example())
function stepGen(gen, k = ()=>{}, arg) {
const {value, done} = gen.next(arg)
if(done) {
return k(value)
}
else if(typeof value.next === 'function') {
return stepGen(value, v => stepGen(gen, k, v))
}
else {
return value(x => stepGen(gen, k, x))
}
}
function callcc(gf) {
return k => {
const gen = gf(result => _ => k(result))
stepGen(gen, k)
}
}
let threads = []
function* exit() {
if(threads.length > 0) {
const nextK = threads.shift()
yield nextK()
}
}
function fork(fn, ...args) {
threads.push(() => k => stepGen(fn(...args), k))
return k => k()
}
const next = callcc(function*(k) {
threads.push(k)
const nextK = threads.shift()
yield nextK()
})
function* proc(id, n) {
for(let i = 0; i <= n; i++) {
console.log(`proc ${id}:`, i)
yield next
}
yield exit()
}
function* main() {
console.log('start main')
yield fork(proc, 1, 4)
yield fork(proc, 2, 4)
yield fork(proc, 3, 4)
yield next
console.log('end main')
yield exit()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment