Assume that the continuation is a copy of the stack, and that to invoke a continuation is to return to a copy of the stack state. In the context of conventional programming languages, with this assumption, there are problems with reinvoked continuations—they break otherwise valid program transformations. Consider the C code
void zz(void); void routine(){ int ar[8]; ar[3] = 2; zz(); ++ar[3]; printf("%d", ar[3]);}It is normally correct to transform this as follows:
void zz(void); void routine(){ int * ar = (int*)malloc(8*sizeof(int)); ar[3] = 2; zz(); ++ar[3]; printf("%d", ar[3]); free(ar);}If zz invokes its continuation twice (the continuation is the state of the stack as zz was called) then the 2nd execution of free() is fatal. Even in a GC context without free() the value in ar[3] is copied in the first case and not the second and the two programs print 3 and 4 respectively the 2nd time the print statement is executed.
The problem is the troulbesome question of depth of copy. I conclude that the semantics of multiple continuation invocation is tied up with language semantics. Compilers for languages with well defined continuation semantics can decide which code transformations are permissible. Scheme is one of those languages and C is not.
I think that for the most likely implementations of Scheme interpreters, stack copying will work. The concept of the stack must, however, not extend to those frames older than that created by main.
I don’t know other reifications of a continuation in a stack environment. Stacks whose frames were produced by code designed with stack copying in mind, may be copied to provide for reinvokable continuations.
The paper Representing Control in the Presence of One-Shot Continuations examines where it makes sense to limit a continuation to one-shot. It refers to other uses of multi shot continuations.
This seems relevant.