diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-03-19 01:11:12 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-03-19 01:11:12 +0000 |
commit | 976becf7eb18aa1592c703ac4d86a2cf9dfa701e (patch) | |
tree | ea2cf60b1ebf58b756e896484440036f5f3ba2cd /vm.c | |
parent | a9d575e507e1ce181ed71b9a7d4c3ad4f2f23e59 (diff) |
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
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 27 |
1 files changed, 21 insertions, 6 deletions
@@ -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 |