From a0c7bb4328c981be5f3f0e82e7ef75fc8bbd51b6 Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Thu, 7 Dec 2023 14:13:33 -0500 Subject: [PATCH] [PRISM] Account for multiple arguments when compiling ArgumentsNode BreakNode, ReturnNode and NextNode all compile the ArgumentsNode directly, but we weren't accounting for multiple arguments. If there is more than one argument, we need to also emit a newarray instruction to put the arguments onto the stack --- prism_compile.c | 7 +++++-- test/ruby/test_compile_prism.rb | 25 ++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 1eeecc5c2a2e4f..71fd05dddf88da 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1762,6 +1762,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, for (size_t index = 0; index < node_list.size; index++) { PM_COMPILE(node_list.nodes[index]); } + if (node_list.size > 1) { + ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(node_list.size)); + } return; } case PM_ARRAY_NODE: { @@ -3578,7 +3581,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_ADJUST(ret, &dummy_line_node, ISEQ_COMPILE_DATA(iseq)->start_label); if (next_node->arguments) { - PM_COMPILE((pm_node_t *)next_node->arguments); + PM_COMPILE_NOT_POPPED((pm_node_t *)next_node->arguments); } else { PM_PUTNIL; @@ -3618,7 +3621,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } if (ip != 0) { if (next_node->arguments) { - PM_COMPILE((pm_node_t *)next_node->arguments); + PM_COMPILE_NOT_POPPED((pm_node_t *)next_node->arguments); } else { PM_PUTNIL; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 1bc08d2db62a2d..50bb61c99da44b 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -742,6 +742,8 @@ def test_BeginNode def test_BreakNode assert_prism_eval("while true; break; end") assert_prism_eval("while true; break 1; end") + assert_prism_eval("while true; break 1, 2; end") + assert_prism_eval("[].each { break }") end @@ -832,6 +834,13 @@ def test_NextNode res CODE + assert_prism_eval(<<-CODE) + (1..5).map do |i| + next i, :even if i.even? + i + end + CODE + assert_prism_eval(<<-CODE) res = [] i = 0 @@ -1001,7 +1010,20 @@ def test_RetryNode end def test_ReturnNode - assert_prism_eval("def return_node; return 1; end") + assert_prism_eval(<<-CODE) + def self.prism_test_return_node + return 1 + end + prism_test_return_node + CODE + + assert_prism_eval(<<-CODE) + def self.prism_test_return_node + return 1, 2 + end + prism_test_return_node + CODE + assert_prism_eval(<<-CODE) def self.prism_test_return_node [1].each do |e| @@ -1010,6 +1032,7 @@ def self.prism_test_return_node end prism_test_return_node CODE + assert_prism_eval(<<-CODE) def self.prism_test_return_node [1].map do |i|