diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c index a422d1ef2..6c1318fd3 100644 --- a/libguile/vm-engine.c +++ b/libguile/vm-engine.c @@ -1059,20 +1059,25 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_) NEXT (2); } - /* receive-values proc:24 _:8 nvalues:24 + /* receive-values proc:24 allow-extra?:1 _:7 nvalues:24 * * Receive a return of multiple values from a call whose procedure was * in PROC. If fewer than NVALUES values were returned, signal an - * error. After receive-values has run, the values can be copied down - * via `mov'. + * error. Unless ALLOW-EXTRA? is true, require that the number of + * return values equals NVALUES exactly. After receive-values has + * run, the values can be copied down via `mov'. */ - VM_DEFINE_OP (4, receive_values, "receive-values", OP2 (U8_U24, X8_U24)) + VM_DEFINE_OP (4, receive_values, "receive-values", OP2 (U8_U24, B1_X7_U24)) { scm_t_uint32 proc, nvalues; SCM_UNPACK_RTL_24 (op, proc); SCM_UNPACK_RTL_24 (ip[1], nvalues); - VM_ASSERT (FRAME_LOCALS_COUNT () > proc + nvalues, - vm_error_not_enough_values ()); + if (ip[1] & 0x1) + VM_ASSERT (FRAME_LOCALS_COUNT () > proc + nvalues, + vm_error_not_enough_values ()); + else + VM_ASSERT (FRAME_LOCALS_COUNT () == proc + nvalues, + vm_error_wrong_number_of_values (nvalues)); NEXT (2); } diff --git a/libguile/vm.c b/libguile/vm.c index 5f6a5a053..3a2795b7e 100644 --- a/libguile/vm.c +++ b/libguile/vm.c @@ -429,6 +429,7 @@ static void vm_error_not_a_bytevector (const char *subr, SCM x) SCM_NORETURN SCM static void vm_error_not_a_struct (const char *subr, SCM x) SCM_NORETURN SCM_NOINLINE; static void vm_error_no_values (void) SCM_NORETURN SCM_NOINLINE; static void vm_error_not_enough_values (void) SCM_NORETURN SCM_NOINLINE; +static void vm_error_wrong_number_of_values (scm_t_uint32 expected) SCM_NORETURN SCM_NOINLINE; static void vm_error_continuation_not_rewindable (SCM cont) SCM_NORETURN SCM_NOINLINE; static void vm_error_bad_wide_string_length (size_t len) SCM_NORETURN SCM_NOINLINE; @@ -577,6 +578,13 @@ vm_error_not_enough_values (void) vm_error ("Too few values returned to continuation", SCM_UNDEFINED); } +static void +vm_error_wrong_number_of_values (scm_t_uint32 expected) +{ + vm_error ("Wrong number of values returned to continuation (expected ~a)", + scm_from_uint32 (expected)); +} + static void vm_error_continuation_not_rewindable (SCM cont) { diff --git a/module/language/cps/compile-rtl.scm b/module/language/cps/compile-rtl.scm index 0fe321691..85e9fec20 100644 --- a/module/language/cps/compile-rtl.scm +++ b/module/language/cps/compile-rtl.scm @@ -273,7 +273,10 @@ (match args (() (emit-call asm proc-slot (+ nargs 1)) - (emit-receive-values asm proc-slot nreq) + ;; FIXME: Only allow more values if there is a rest arg. + ;; Express values truncation by the presence of an + ;; unused rest arg instead of implicitly. + (emit-receive-values asm proc-slot #t nreq) (when rest? (emit-bind-rest asm (+ proc-slot 1 nreq))) (for-each (match-lambda