[PRISM] Fix attrset edge cases

In some cases code may look like an attrset ID but should actually
return the value of the method, not the passed values.

In ruby/prism#2051 a flag was added when we have a attribute write call.
I used this flag to add the proper instructions when we have a real
attrset instead of using `rb_is_attrset_id` which was kind of hacky
anyway.

The value that should be returned in the newly added test is 42, not 2.
Previously the changes we had made returned 2.

Related to ruby/prism#1715
This commit is contained in:
eileencodes 2023-12-12 14:24:00 -05:00 коммит произвёл Jemma Issroff
Родитель 36ca99b343
Коммит 1ad991c54d
2 изменённых файлов: 16 добавлений и 8 удалений

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

@ -1802,6 +1802,8 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
int lineno = (int)pm_newline_list_line_column(&newline_list, ((pm_node_t *)call_node)->location.start).line;
NODE dummy_line_node = generate_dummy_line_node(lineno, lineno);
pm_node_t *pm_node = (pm_node_t *)call_node;
int flags = 0;
struct rb_callinfo_kwarg *kw_arg = NULL;
@ -1817,7 +1819,7 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
ISEQ_COMPILE_DATA(iseq)->current_block = block_iseq;
}
else {
if (((pm_node_t *)call_node)->flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL) {
if (pm_node->flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL) {
flags |= VM_CALL_VCALL;
}
@ -1835,15 +1837,15 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
flags |= VM_CALL_FCALL;
}
if (rb_is_attrset_id(method_id)) {
if (pm_node->flags & PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) {
ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 1));
}
ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
if (rb_is_attrset_id(method_id)) {
PM_POP;
}
else {
ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
}
PM_POP_IF_POPPED;
}
@ -2293,7 +2295,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
pm_call_node_t *call_node = (pm_call_node_t *) node;
ID method_id = pm_constant_id_lookup(scope_node, call_node->name);
if (rb_is_attrset_id(method_id)) {
if (node->flags & PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) {
PM_PUTNIL;
}

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

@ -1411,6 +1411,12 @@ module Prism
foo(1)
CODE
assert_prism_eval(<<-CODE)
foo = Object.new
def foo.[]=(k,v); 42; end
foo.[]=(1,2)
CODE
assert_prism_eval(<<-CODE)
def self.prism_opt_var_trail_hash(a = nil, *b, c, **d); end
prism_opt_var_trail_hash("a")