diff --git a/prism_compile.c b/prism_compile.c index df3a12ceb2..6ae9e094b2 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -932,10 +932,10 @@ pm_compile_call_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t } static void -pm_compile_index_write_nodes_add_send(bool popped, LINK_ANCHOR *const ret, rb_iseq_t *iseq, NODE dummy_line_node, VALUE argc, int flag, int block_offset) +pm_compile_index_write_nodes_add_send(bool popped, LINK_ANCHOR *const ret, rb_iseq_t *iseq, NODE dummy_line_node, VALUE argc, int flag, int block_offset, struct rb_callinfo_kwarg *keywords) { if (!popped) { - ADD_INSN1(ret, &dummy_line_node, setn, FIXNUM_INC(argc, 2 + block_offset)); + ADD_INSN1(ret, &dummy_line_node, setn, FIXNUM_INC(argc, 2 + block_offset + (keywords ? keywords->keyword_len : 0))); } if (flag & VM_CALL_ARGS_SPLAT) { @@ -952,6 +952,11 @@ pm_compile_index_write_nodes_add_send(bool popped, LINK_ANCHOR *const ret, rb_is } ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idASET, argc, INT2FIX(flag)); } + else if (keywords && keywords->keyword_len) { + ADD_INSN1(ret, &dummy_line_node, opt_reverse, INT2FIX(keywords->keyword_len + block_offset + 1)); + ADD_INSN1(ret, &dummy_line_node, opt_reverse, INT2FIX(keywords->keyword_len + block_offset + 0)); + ADD_SEND_R(ret, &dummy_line_node, idASET, FIXNUM_INC(argc, 1), NULL, INT2FIX(flag), keywords); + } else { if (block_offset > 0) { PM_SWAP; @@ -1241,9 +1246,10 @@ pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t int flag = 0; int argc_int = 0; + struct rb_callinfo_kwarg *keywords = NULL; if (arguments) { // Get any arguments, and set the appropriate values for flag - argc_int = pm_setup_args(arguments, &flag, NULL, iseq, ret, src, popped, scope_node, dummy_line_node, parser); + argc_int = pm_setup_args(arguments, &flag, &keywords, iseq, ret, src, popped, scope_node, dummy_line_node, parser); } VALUE argc = INT2FIX(argc_int); @@ -1255,9 +1261,9 @@ pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t block_offset = 1; } - ADD_INSN1(ret, &dummy_line_node, dupn, FIXNUM_INC(argc, 1 + block_offset)); + ADD_INSN1(ret, &dummy_line_node, dupn, FIXNUM_INC(argc, 1 + block_offset + (keywords ? keywords->keyword_len : 0))); - ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idAREF, argc, INT2FIX(flag)); + ADD_SEND_R(ret, &dummy_line_node, idAREF, argc, NULL, INT2FIX(flag), keywords); LABEL *label = NEW_LABEL(lineno); LABEL *lfin = NEW_LABEL(lineno); @@ -1276,7 +1282,7 @@ pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t PM_COMPILE_NOT_POPPED(value); - pm_compile_index_write_nodes_add_send(popped, ret, iseq, dummy_line_node, argc, flag, block_offset); + pm_compile_index_write_nodes_add_send(popped, ret, iseq, dummy_line_node, argc, flag, block_offset, keywords); ADD_INSNL(ret, &dummy_line_node, jump, lfin); ADD_LABEL(ret, label); @@ -5028,7 +5034,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ID method_id = pm_constant_id_lookup(scope_node, index_operator_write_node->operator); ADD_SEND(ret, &dummy_line_node, method_id, INT2FIX(1)); - pm_compile_index_write_nodes_add_send(popped, ret, iseq, dummy_line_node, argc, flag, block_offset); + pm_compile_index_write_nodes_add_send(popped, ret, iseq, dummy_line_node, argc, flag, block_offset, NULL); return; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 4cd7bff60a..0998c8fa5d 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -385,6 +385,15 @@ module Prism hash["key", &(Proc.new { _1.upcase })] &&= "value" hash CODE + + # Test with keyword arguments + assert_prism_eval(<<~RUBY) + h = Object.new + def h.[](**b) = 0 + def h.[]=(*a, **b); end + + h[foo: 1] &&= 2 + RUBY end def test_IndexOrWriteNode