[PRISM] Fix keywords arguments in IndexAndWriteNode

Fixes ruby/prism#2233.
This commit is contained in:
Peter Zhu 2024-01-22 10:46:12 -05:00
Родитель 5906ce42fe
Коммит a7af34fa8b
2 изменённых файлов: 22 добавлений и 7 удалений

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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