diff options
author | Andy Wingo <wingo@pobox.com> | 2010-02-08 22:59:25 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2010-02-08 22:59:25 +0100 |
commit | d8873dfe4754daf031a6709738bd31afa8edb443 (patch) | |
tree | dbad856934bd9069258d0db8e010f9a9a556ef69 /libguile/continuations.c | |
parent | 269479e31f70d40a82b75be87c1b2a7363c85696 (diff) | |
download | guile-d8873dfe4754daf031a6709738bd31afa8edb443.tar.gz |
continuations return multiple values on the stack
* libguile/vm.h (struct scm_vm_cont): Instead of saving the "IP", save
"RA" and "MVRA". That is, save singly-valued and multiply-valued
return addresses, so that we can return multiple values on the stack.
(scm_i_vm_reinstate_continuation): Remove.
* libguile/vm.c (vm_capture_continuation): Rename from capture_vm_cont,
and change the prototype so we can capture the RA and MVRA, and so
that tail calls to call/cc can capture a continuation without the
call/cc application frame.
(vm_return_to_continuation): Rename from reinstate_vm_cont, and take
arguments to return to the continuation. Handles returning to single
or multiple-value RA.
(scm_i_vm_capture_continuation): Change to invoke
vm_capture_continuation. Kept around for the benefit of make-stack.
* libguile/vm-i-system.c (continuation-call): Handle reinstatement of
the VM stack, with arguments.
(call/cc, tail-call/cc): Adapt to new vm_capture_continuation
prototype. tail-call/cc captures tail continuations.
* libguile/stacks.c (scm_make_stack): Update for scm_vm_cont structure
change.
* libguile/continuations.h (struct scm_contregs): Remove throw_value
member, which was used to return a value to a continuation.
(scm_i_check_continuation): New internal function, checks that a
continuation may be reinstated.
(scm_i_reinstate_continuation): Replaces scm_i_continuation_call; just
reinstates the C stack.
(scm_i_contregs_vm, scm_i_contregs_vm_cont): New internal accessors.
* libguile/continuations.c (scm_i_make_continuation): Return
SCM_UNDEFINED if we are returning again.
(grow_stack, copy_stack_and_call, scm_dynthrow): Remove extra arg, as
vm opcodes handle value returns.
(copy_stack): No need to instate VM continuation.
(scm_i_reinstate_continuation): Adapt.
Diffstat (limited to 'libguile/continuations.c')
-rw-r--r-- | libguile/continuations.c | 61 |
1 files changed, 31 insertions, 30 deletions
diff --git a/libguile/continuations.c b/libguile/continuations.c index fc47d9b40..118c0b61d 100644 --- a/libguile/continuations.c +++ b/libguile/continuations.c @@ -34,7 +34,6 @@ #include "libguile/smob.h" #include "libguile/ports.h" #include "libguile/dynwind.h" -#include "libguile/values.h" #include "libguile/eval.h" #include "libguile/vm.h" #include "libguile/instructions.h" @@ -54,7 +53,6 @@ static scm_t_bits tc16_continuation; (SCM_CONTREGS (x)->num_stack_items = (n)) #define SCM_JMPBUF(x) ((SCM_CONTREGS (x))->jmpbuf) #define SCM_DYNENV(x) ((SCM_CONTREGS (x))->dynenv) -#define SCM_THROW_VALUE(x) ((SCM_CONTREGS (x))->throw_value) #define SCM_CONTINUATION_ROOT(x) ((SCM_CONTREGS (x))->root) #define SCM_DFRAME(x) ((SCM_CONTREGS (x))->dframe) @@ -187,8 +185,8 @@ continuation_print (SCM obj, SCM port, scm_print_state *state SCM_UNUSED) } /* this may return more than once: the first time with the escape - procedure, then subsequently with the value to be passed to the - continuation. */ + procedure, then subsequently with SCM_UNDEFINED (the vals already having been + placed on the VM stack). */ #define FUNC_NAME "scm_i_make_continuation" SCM scm_i_make_continuation (int *first, SCM vm, SCM vm_cont) @@ -206,7 +204,6 @@ scm_i_make_continuation (int *first, SCM vm, SCM vm_cont) "continuation"); continuation->num_stack_items = stack_size; continuation->dynenv = scm_i_dynwinds (); - continuation->throw_value = SCM_EOL; continuation->root = thread->continuation_root; src = thread->continuation_base; #if ! SCM_STACK_GROWS_UP @@ -238,11 +235,7 @@ scm_i_make_continuation (int *first, SCM vm, SCM vm_cont) return make_continuation_trampoline (cont); } else - { - SCM ret = continuation->throw_value; - continuation->throw_value = SCM_BOOL_F; - return ret; - } + return SCM_UNDEFINED; } #undef FUNC_NAME @@ -272,13 +265,25 @@ scm_i_continuation_to_frame (SCM continuation) return scm_c_make_frame (cont->vm_cont, data->fp + data->reloc, data->sp + data->reloc, - data->ip, + data->ra, data->reloc); } else return SCM_BOOL_F; } +SCM +scm_i_contregs_vm (SCM contregs) +{ + return SCM_CONTREGS (contregs)->vm; +} + +SCM +scm_i_contregs_vm_cont (SCM contregs) +{ + return SCM_CONTREGS (contregs)->vm_cont; +} + /* {Apply} */ @@ -295,7 +300,7 @@ scm_i_continuation_to_frame (SCM continuation) * with their correct stack. */ -static void scm_dynthrow (SCM, SCM); +static void scm_dynthrow (SCM); /* Grow the stack by a fixed amount to provide space to copy in the * continuation. Possibly this function has to be called several times @@ -307,12 +312,12 @@ static void scm_dynthrow (SCM, SCM); scm_t_bits scm_i_dummy; static void -grow_stack (SCM cont, SCM val) +grow_stack (SCM cont) { scm_t_bits growth[100]; scm_i_dummy = (scm_t_bits) growth; - scm_dynthrow (cont, val); + scm_dynthrow (cont); } @@ -332,15 +337,13 @@ copy_stack (void *data) copy_stack_data *d = (copy_stack_data *)data; memcpy (d->dst, d->continuation->stack, sizeof (SCM_STACKITEM) * d->continuation->num_stack_items); - scm_i_vm_reinstate_continuation (d->continuation->vm, - d->continuation->vm_cont); #ifdef __ia64__ SCM_I_CURRENT_THREAD->pending_rbs_continuation = d->continuation; #endif } static void -copy_stack_and_call (scm_t_contregs *continuation, SCM val, +copy_stack_and_call (scm_t_contregs *continuation, SCM_STACKITEM * dst) { long delta; @@ -351,7 +354,6 @@ copy_stack_and_call (scm_t_contregs *continuation, SCM val, data.dst = dst; scm_i_dowinds (continuation->dynenv, delta, copy_stack, &data); - continuation->throw_value = val; SCM_I_LONGJMP (continuation->jmpbuf, 1); } @@ -377,7 +379,7 @@ scm_ia64_longjmp (scm_i_jmp_buf *JB, int VAL) * actual copying and continuation calling. */ static void -scm_dynthrow (SCM cont, SCM val) +scm_dynthrow (SCM cont) { scm_i_thread *thread = SCM_I_CURRENT_THREAD; scm_t_contregs *continuation = SCM_CONTREGS (cont); @@ -392,36 +394,35 @@ scm_dynthrow (SCM cont, SCM val) #if SCM_STACK_GROWS_UP if (dst + continuation->num_stack_items >= &stack_top_element) - grow_stack (cont, val); + grow_stack (cont); #else dst -= continuation->num_stack_items; if (dst <= &stack_top_element) - grow_stack (cont, val); + grow_stack (cont); #endif /* def SCM_STACK_GROWS_UP */ SCM_FLUSH_REGISTER_WINDOWS; - copy_stack_and_call (continuation, val, dst); + copy_stack_and_call (continuation, dst); } void -scm_i_continuation_call (SCM cont, size_t n, SCM *argv) +scm_i_check_continuation (SCM cont) { scm_i_thread *thread = SCM_I_CURRENT_THREAD; scm_t_contregs *continuation = SCM_CONTREGS (cont); - SCM args = SCM_EOL; - - /* FIXME: shuffle args on VM stack instead of heap-allocating */ - while (n--) - args = scm_cons (argv[n], args); if (continuation->root != thread->continuation_root) scm_misc_error ("%continuation-call", "invoking continuation would cross continuation barrier: ~A", scm_list_1 (cont)); - - scm_dynthrow (cont, scm_values (args)); +} + +void +scm_i_reinstate_continuation (SCM cont) +{ + scm_dynthrow (cont); } SCM |