From 976becf7eb18aa1592c703ac4d86a2cf9dfa701e Mon Sep 17 00:00:00 2001 From: nobu Date: Sun, 19 Mar 2017 01:11:12 +0000 Subject: vm_args.c: arity check of lambda * vm_eval.c (rb_yield_lambda): new function which yields an array to a proc and splat to a lambda. mainly for Enumerable only. * vm_args.c (setup_parameters_complex): remove special lambda splatting for [Bug #9605]. [ruby-core:77065] [Bug #12705] * vm_insnhelper.c (vm_callee_setup_block_arg): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58019 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- vm.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'vm.c') diff --git a/vm.c b/vm.c index afdc5be931..1eefee18a6 100644 --- a/vm.c +++ b/vm.c @@ -1019,14 +1019,16 @@ static inline VALUE invoke_block_from_c_splattable(rb_thread_t *th, VALUE block_handler, int argc, const VALUE *argv, VALUE passed_block_handler, const rb_cref_t *cref, - int is_lambda) + int splattable, int is_lambda) { again: switch (vm_block_handler_type(block_handler)) { case block_handler_type_iseq: { const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(block_handler); - return invoke_iseq_block_from_c(th, captured, captured->self, argc, argv, passed_block_handler, cref, TRUE, is_lambda); + return invoke_iseq_block_from_c(th, captured, captured->self, + argc, argv, passed_block_handler, + cref, splattable, is_lambda); } case block_handler_type_ifunc: return vm_yield_with_cfunc(th, VM_BH_TO_IFUNC_BLOCK(block_handler), VM_BH_TO_IFUNC_BLOCK(block_handler)->self, @@ -1034,7 +1036,8 @@ invoke_block_from_c_splattable(rb_thread_t *th, VALUE block_handler, case block_handler_type_symbol: return vm_yield_with_symbol(th, VM_BH_TO_SYMBOL(block_handler), argc, argv, passed_block_handler); case block_handler_type_proc: - is_lambda = block_proc_is_lambda(VM_BH_TO_PROC(block_handler)); + if (!splattable) + is_lambda = block_proc_is_lambda(VM_BH_TO_PROC(block_handler)); block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler)); goto again; } @@ -1057,19 +1060,31 @@ check_block_handler(rb_thread_t *th) static VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda) { - return invoke_block_from_c_splattable(th, check_block_handler(th), argc, argv, VM_BLOCK_HANDLER_NONE, cref, is_lambda); + return invoke_block_from_c_splattable(th, check_block_handler(th), + argc, argv, VM_BLOCK_HANDLER_NONE, + cref, FALSE, is_lambda); } static VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv) { - return invoke_block_from_c_splattable(th, check_block_handler(th), argc, argv, VM_BLOCK_HANDLER_NONE, NULL, FALSE); + return invoke_block_from_c_splattable(th, check_block_handler(th), + argc, argv, VM_BLOCK_HANDLER_NONE, + NULL, FALSE, FALSE); } static VALUE vm_yield_with_block(rb_thread_t *th, int argc, const VALUE *argv, VALUE block_handler) { - return invoke_block_from_c_splattable(th, check_block_handler(th), argc, argv, block_handler, NULL, FALSE); + return invoke_block_from_c_splattable(th, check_block_handler(th), + argc, argv, block_handler, + NULL, FALSE, FALSE); +} + +static VALUE +vm_yield_lambda_splattable(rb_thread_t *th, VALUE args) +{ + return invoke_block_from_c_splattable(th, check_block_handler(th), 1, &args, VM_BLOCK_HANDLER_NONE, NULL, TRUE, FALSE); } static inline VALUE -- cgit v1.2.3