1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-16 16:50:21 +02:00

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.
This commit is contained in:
Andy Wingo 2010-02-08 22:59:25 +01:00
parent 269479e31f
commit d8873dfe47
6 changed files with 142 additions and 107 deletions

View file

@ -982,7 +982,13 @@ VM_DEFINE_INSTRUCTION (89, continuation_call, "continuation-call", 0, -1, 0)
{
SCM contregs;
POP (contregs);
scm_i_continuation_call (contregs, sp - (fp - 1), fp);
scm_i_check_continuation (contregs);
vm_return_to_continuation (scm_i_contregs_vm (contregs),
scm_i_contregs_vm_cont (contregs),
sp - (fp - 1), fp);
scm_i_reinstate_continuation (contregs);
/* no NEXT */
abort ();
}
@ -1090,10 +1096,11 @@ VM_DEFINE_INSTRUCTION (63, tail_apply, "tail-apply", 1, -1, 1)
VM_DEFINE_INSTRUCTION (64, call_cc, "call/cc", 0, 1, 1)
{
int first;
SCM proc, cont;
SCM proc, vm_cont, cont;
POP (proc);
SYNC_ALL ();
cont = scm_i_make_continuation (&first, vm, capture_vm_cont (vp));
vm_cont = vm_capture_continuation (vp->stack_base, fp, sp, ip, NULL);
cont = scm_i_make_continuation (&first, vm, vm_cont);
if (first)
{
PUSH ((SCM)fp); /* dynamic link */
@ -1104,22 +1111,14 @@ VM_DEFINE_INSTRUCTION (64, call_cc, "call/cc", 0, 1, 1)
nargs = 1;
goto vm_call;
}
ASSERT (sp == vp->sp);
ASSERT (fp == vp->fp);
else if (SCM_VALUESP (cont))
else
{
/* multiple values returned to continuation */
SCM values;
values = scm_struct_ref (cont, SCM_INUM0);
if (scm_is_null (values))
goto vm_error_no_values;
/* non-tail context does not accept multiple values? */
PUSH (SCM_CAR (values));
NEXT;
}
else
{
PUSH (cont);
/* otherwise, the vm continuation was reinstated, and
scm_i_vm_return_to_continuation pushed on one value. So pull our regs
back down from the vp, and march on to the next instruction. */
CACHE_REGISTER ();
program = SCM_FRAME_PROGRAM (fp);
CACHE_PROGRAM ();
NEXT;
}
}
@ -1127,12 +1126,17 @@ VM_DEFINE_INSTRUCTION (64, call_cc, "call/cc", 0, 1, 1)
VM_DEFINE_INSTRUCTION (65, tail_call_cc, "tail-call/cc", 0, 1, 1)
{
int first;
SCM proc, cont;
SCM proc, vm_cont, cont;
POP (proc);
SYNC_ALL ();
cont = scm_i_make_continuation (&first, vm, capture_vm_cont (vp));
ASSERT (sp == vp->sp);
ASSERT (fp == vp->fp);
/* In contrast to call/cc, tail-call/cc captures the continuation without the
stack frame. */
vm_cont = vm_capture_continuation (vp->stack_base,
SCM_FRAME_DYNAMIC_LINK (fp),
SCM_FRAME_LOWER_ADDRESS (fp) - 1,
SCM_FRAME_RETURN_ADDRESS (fp),
SCM_FRAME_MV_RETURN_ADDRESS (fp));
cont = scm_i_make_continuation (&first, vm, vm_cont);
if (first)
{
PUSH (proc);
@ -1140,19 +1144,14 @@ VM_DEFINE_INSTRUCTION (65, tail_call_cc, "tail-call/cc", 0, 1, 1)
nargs = 1;
goto vm_tail_call;
}
else if (SCM_VALUESP (cont))
{
/* multiple values returned to continuation */
SCM values;
values = scm_struct_ref (cont, SCM_INUM0);
nvalues = scm_ilength (values);
PUSH_LIST (values, scm_is_null);
goto vm_return_values;
}
else
{
PUSH (cont);
goto vm_return;
/* Otherwise, cache regs and NEXT, as above. Invoking the continuation
does a return from the frame, either to the RA or MVRA. */
CACHE_REGISTER ();
program = SCM_FRAME_PROGRAM (fp);
CACHE_PROGRAM ();
NEXT;
}
}