Apologies if anyone has the opinion this is off topic. I am sharing some thoughts in case any one (perhaps myself) wanted to try to add continuations to Neko or any similar system.
I am undecided if continuations are worth the effort? Generators seem quite useful, but could be implemented more efficiently than generalized continuations. I noticed that Lua supports coroutines (a potential use of continuations), which they claim are useful for implementing multi-tasking on devices which do not supporting pre-emptive multi-threading, or for lower overhead multi-tasking: http://lua-users.org/lists/lua-l/2007-11/msg00248.html http://www.lua.org/manual/5.1/manual.html#5.2 Let's assume that even without the optimization below, that continuations save an entire copy of the stack, then this overhead (other than latency on initial save) will be insignificant for implementing coroutines when the running time of the coroutines is long compared to time to save stack, because the stacks will not be resaved each time the coroutines call each other (alternating execution, i.e. cooperative multitasking). Even with pre-emptive multi-threading, unless that is designed into the browser (e.g. Google's Chrome) and server to aware of blocking on slow resources (i.e. to pre-emptively multitask on such blocking), the continuations could greatly simplify web coding: http://en.wikipedia.org/w/index.php?title=Continuation&oldid=339611728#Continuations_in_Web_development I can remember some of my complex nested blocks of Javascript code to deal with asynchronous loading of code via XMLHttpRequest (or dynamically loading the <script> tag), where the nesting could I presume be eliminated with continuations. Perhaps this can be solved (I think I did) with closures and Continuation-passing style, or specialized shared state and dispatch on asynchronous events, or separate thread for loading each resource (again needing to maintain shared state negotiation), but it might be less general or more convoluted. I assume MMOG (massively multiplayer online games) may also have to deal with asynchronous network resources. > Am I correct that implementing continuations is similar to forming a > closure, in that a copy of the current stack is saved to capture the local > variables (execution context)? Also the resume location in the executable > statements is also saved. If the function capturing the continuation > contains a return statement (i.e. has any branch of execution that can > return instead of resuming a captured continuation), then the entire stack > history has to be saved also? The optimization of not saving entire stack would not be available to HLLs that support runtime evaluation of code statements, i.e. 'eval', in the case that 'return' means return from the function containing the 'eval' (as far as I know, there is no 'eval' that does that?). Or at least the entire stack would need to be saved by detecting at runtime the 'return' from the containing function. An orthogonal optimization is to save a pointer to captured location in the stack, then incrementally save the portion of stack on the exit of each stack block (e.g. function, either by 'return' or resume of a continuation higher in the stack). Then document that a continuation captures the state of the stack (local variables) at each hierarchal containing block exit, not at the statement for the capture. This optimization could avoid saving the entire stack in the cases where the captured continuation is garbage collected before the entire stack is unwound. I assume the captured continuation is assigned to a variable, so it can be resumed. BTW, this is another example of the problem of finalizers being called too late with garbage collection, and thus aforementioned superiority of reference counting combined with specialized Bacon's garbage collection (and maybe also weak references) for cleaning up cyclical references: http://lists.motion-twin.com/pipermail/neko/2010-January/002691.html Another design tradeoff may be whether the continuation captures an exclusive copy of the stack, or shared between all continuations in the same stack fork. I haven't really thought this out entirely, and it seems to me this sharing might not be very common any way. The algorithm would be on exit of each stack block, check for a capture continuation pointer deeper than current stack block, and if so save blocking being exited to shared stack copy. When a function call is made, then a new stack fork has been created. -- Neko : One VM to run them all (http://nekovm.org)
