That's a really long post, and I dimly recall reading it a while back, but after you scrape off it saying the same thing over and over again, I think it reduces down to an uncompelling argument.
It's basically, "I want context switches syntactically explicit in my code. If they aren't, reasoning about it is exponentially harder."
And I think that's pretty clearly a strawman. Everything the author claims about threaded code is true of any re-entrant code, multi-threaded or not. If your function inadvertently calls a function which calls the original function recursively, you have the exact same problem.
But, guess what, that just doesn't happen that often. Most code isn't re-entrant. Most state isn't shared.
For code that is concurrent and does interact in interesting ways, you are going to have to reason about it carefully. Smearing "yield from" all over your code doesn't solve.
In practice, you'll end up with so many "yield from" lines in your code that you're right back to "well, I guess I could context switch just about anywhere", which is the problem you were trying to avoid in the first place.
I don't think you read the article very carefully. Specifically, what I am claiming about (shared-state) threaded code which is not true of "any re-entrant code" is the fact that you cannot tell whether threaded code is re-entrant or not without a comprehensive, combinatorial whole-program analysis. It's not feasible to know what you might be re-entrant with, because you might be re-entrant with anything. With preemptive threads you really just can't do it at all, but with green threads you have to follow every call stack all the way to the bottom, because nothing else about it the bottom of the stack tells you whether you're going to context switch or not. When you get back a Deferred (or a Promise or a Future or a thunk or whatever), then the stack-inspection can be shallow; O(1) on the depth of your stack instead of O((stack_depth) * (function_length)).
It's basically, "I want context switches syntactically explicit in my code. If they aren't, reasoning about it is exponentially harder."
And I think that's pretty clearly a strawman. Everything the author claims about threaded code is true of any re-entrant code, multi-threaded or not. If your function inadvertently calls a function which calls the original function recursively, you have the exact same problem.
But, guess what, that just doesn't happen that often. Most code isn't re-entrant. Most state isn't shared.
For code that is concurrent and does interact in interesting ways, you are going to have to reason about it carefully. Smearing "yield from" all over your code doesn't solve.
In practice, you'll end up with so many "yield from" lines in your code that you're right back to "well, I guess I could context switch just about anywhere", which is the problem you were trying to avoid in the first place.