chibi-scheme icon indicating copy to clipboard operation
chibi-scheme copied to clipboard

Continuation equality

Open mnieper opened this issue 4 years ago • 4 comments

How much work would it be to make sure that the primitive %call/cc produces the same procedure (in the sense of eq?) when called twice in the same continuation?

At the moment, a new procedure is created at every call: https://github.com/ashinn/chibi-scheme/blob/master/vm.c#L1206

The reason why I am asking is because I would like to implement continuation marks and delimited continuations on top of it, but for this it is important to be able to detect whether the code is in a continuation previously seen.

A related question is whether Chibi can store properties associated to procedures (that is closures).

mnieper avatar Jul 27 '21 13:07 mnieper

There are two parts to this: storing the continuation somewhere and determining when we are in the same continuation. I don't have a good idea for the former and am worried about overhead. The latter is a straightforward stack comparison but O(n).

I think it's better to go the other way: make delimited continuations the native construct and implement call/cc on top of that. This is a long-standing TODO that I haven't had time for.

ashinn avatar Jul 27 '21 22:07 ashinn

For implementing stable continuation procedures efficiently: When SEXP_OP_CALLCC is executed for the first time in a context, make the frame that is stored at the beginning of the cited source code lines special. In this frame, the created continuation procedure is stored. When SEXP_OP_CALLCC is executed the second time in the same context, it detects the special frame at the top of the stack and just reuses the continuation procedure stored there.

Even without delimited continuations, it would be very nice to have as it would, for example, allow one to test whether code is actually executed in tail position (which is guaranteed by many standard procedures), namely just by comparing two continuations.

mnieper avatar Jul 28 '21 05:07 mnieper

The most straightforward way to make the frame special is to include an extra offset in every frame, initially null, which contains the continuation. Unfortunately this adds (small) overhead to every non-tail-call.

Out-of-band approaches to storing the information get very complicated, e.g. a map of frame pointer to continuation stored in every stack object. call/cc would create the continuation and add it to the map, and push code onto the stack to remove the map entry.

ashinn avatar Jul 28 '21 12:07 ashinn

If reserving space in every frame is too costly, one could store the created continuation procedure on the stack before the actual frame is created. In that actual frame, the IP is a special one, pointing to bytecode that pops the continuation procedure from the stack and resumes execution by calling it. Comparing the stored IP with the special one gives the information whether we are in a frame that has already executed %call/cc.

mnieper avatar Jul 28 '21 13:07 mnieper