From 2760f2377425e2b04cc6c25df179525b43176e50 Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Mon, 27 Nov 2023 15:55:15 -0500 Subject: [PATCH] [PRISM] Compile YieldNode with different arguments --- prism_compile.c | 76 ++++++++++++++++----------------- test/ruby/test_compile_prism.rb | 1 + 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 7951f25e62..2e7bcb28f7 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -836,6 +836,38 @@ pm_compile_call_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t return; } +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) +{ + if (!popped) { + ADD_INSN1(ret, &dummy_line_node, setn, FIXNUM_INC(argc, 2 + block_offset)); + } + + if (flag & VM_CALL_ARGS_SPLAT) { + ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(1)); + if (block_offset > 0) { + ADD_INSN1(ret, &dummy_line_node, dupn, INT2FIX(3)); + PM_SWAP; + PM_POP; + } + ADD_INSN(ret, &dummy_line_node, concatarray); + if (block_offset > 0) { + ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(3)); + PM_POP; + } + ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idASET, argc, INT2FIX(flag)); + } + else { + if (block_offset > 0) { + PM_SWAP; + } + ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag)); + } + + PM_POP; + return; +} + static int pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinfo_kwarg **kw_arg, rb_iseq_t *iseq, LINK_ANCHOR *const ret, const uint8_t *src, bool popped, pm_scope_node_t *scope_node, NODE dummy_line_node, pm_parser_t *parser) { @@ -907,12 +939,14 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf else { PM_SWAP; } + + *flags |= VM_CALL_KW_SPLAT_MUT; } pm_assoc_splat_node_t *assoc_splat = (pm_assoc_splat_node_t *)cur_node; PM_COMPILE_NOT_POPPED(assoc_splat->value); - *flags |= VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT; + *flags |= VM_CALL_KW_SPLAT; if (len > 1) { ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_kwd, INT2FIX(2)); @@ -996,38 +1030,6 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf return orig_argc; } -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) -{ - if (!popped) { - ADD_INSN1(ret, &dummy_line_node, setn, FIXNUM_INC(argc, 2 + block_offset)); - } - - if (flag & VM_CALL_ARGS_SPLAT) { - ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(1)); - if (block_offset > 0) { - ADD_INSN1(ret, &dummy_line_node, dupn, INT2FIX(3)); - PM_SWAP; - PM_POP; - } - ADD_INSN(ret, &dummy_line_node, concatarray); - if (block_offset > 0) { - ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(3)); - PM_POP; - } - ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idASET, argc, INT2FIX(flag)); - } - else { - if (block_offset > 0) { - PM_SWAP; - } - ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag)); - } - - PM_POP; - return; -} - static void pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t *value, pm_arguments_node_t *arguments, pm_node_t *block, LINK_ANCHOR *const ret, rb_iseq_t *iseq, int lineno, const uint8_t * src, bool popped, pm_scope_node_t *scope_node, pm_parser_t *parser) { @@ -4042,18 +4044,16 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_YIELD_NODE: { pm_yield_node_t *yield_node = (pm_yield_node_t *)node; - unsigned int flag = 0; + int flags = 0; struct rb_callinfo_kwarg *keywords = NULL; int argc = 0; if (yield_node->arguments) { - PM_COMPILE_NOT_POPPED((pm_node_t *)yield_node->arguments); - - argc = (int) yield_node->arguments->arguments.size; + argc = pm_setup_args(yield_node->arguments, &flags, &keywords, iseq, ret, src, popped, scope_node, dummy_line_node, parser); } - ADD_INSN1(ret, &dummy_line_node, invokeblock, new_callinfo(iseq, 0, argc, flag, keywords, FALSE)); + ADD_INSN1(ret, &dummy_line_node, invokeblock, new_callinfo(iseq, 0, argc, flags, keywords, FALSE)); PM_POP_IF_POPPED; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 2f3c2dc062..d3cb1c646c 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -841,6 +841,7 @@ module Prism def test_YieldNode assert_prism_eval("def prism_test_yield_node; yield; end") assert_prism_eval("def prism_test_yield_node; yield 1, 2; end") + assert_prism_eval("def prism_test_yield_node; yield **kw if condition; end") # Test case where there's a call directly after the yield call assert_prism_eval("def prism_test_yield_node; yield; 1; end")