Wednesday, April 07, 2010

Harmony first-class activations

This morning I've been blogging about single-function activations for Harmony, the history and design space of continuations, and informal models and design sketches for control operators. A few more thoughts here.

One-shot continuations

(I won't try to model this in the framework I sketched earlier, because it introduces mutation, and then we have to add a heap to the model, and it gets mucky enough not to be worth it here.)

You can limit the expressivity of continuations to only allow control to enter them at most once. This is totally compatible with most any design we pick along the other dimensions. For example, in the semantics I sketched earlier, if the callee throws an exception, we throw back into the activation, and it becomes marked as un-reusable. So if the callee saved the captured continuation, invoking it later would be an error. But if the callee calls the captured continuation before returning and then returns normally, the caller skips past the continuation and returns normally.

There's one very subtle aspect of multi-shot continuations that is probably their single biggest liability: finally. In ES, when you execute a try block with a finally block, the finally block is guaranteed to be executed exactly once (assuming the body of the try block completes without an infinite loop and the program isn't abruptly terminated). Now, even with one-shot continuations, it's possible that you'll suspend the continuation before the try block completes and never resume it. But if you do resume it and the try block completes, it'll still execute the finally block exactly once.

With multi-shot continuations, you can resume that code as many times as you like, and that finally block will get executed again and again. (This is analogous to Common Lisp's unwind-protect and Scheme's dynamic-wind.) This is pretty subtle, and makes it harder to write correct "clean-up" code.

Implementing JS1.7 generators

One-shot, single frame continuations should be expressive enough to implement JS1.7 generators pretty easily. I sent a draft implementation of generators via one-frame continuations to the es-discuss list. As soon as there's a prototype implementation of single-frame continuations somewhere, it should be possible to test that code (mutatis mutandis).

My current preference

So far I sort of prefer the semantics I described earlier today, with one-shot continuations. But I need to implement and experiment before I trust my opinion. There are certainly questions of API and syntax design that aren't addressed by my design sketches. For that I'd really prefer to look at real callback-heavy DOM code and see what would fit the most smoothly.


jto said...

I don't think finally is especially troublesome in this regard. Multiple return would trample unstated assumptions of just about any program written in a stateful language like ECMAScript.

Multiple return is goto for ninjas. I'll be surprised if anyone wants that in ECMAScript. It seems like it would make it awfully hard to write any kind of secure code in the language.

Dave Herman said...

Multiple return would trample unstated assumptions of just about any program written in a stateful language like ECMAScript.

I mostly agree, which is why I stated that my preference is leaning towards one-shot. However, keep in mind that with one-frame continuations, it's only the code within that same function body that can be returned to multiple times. So you can tell whether multiple returns are possible simply by checking the immediate function body.

(Again, I still agree that finally gets far more tricky to get right, esp. as you say in a highly stateful language, and that this is probably too high a cost.)