From ad671c49fea40240fc25c49546acc7f1f0b0945f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 7 Dec 2022 22:24:36 -0500 Subject: [PATCH] Ruby 3.2 argument forwarding --- lib/syntax_tree/yarv/compiler.rb | 54 ++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/lib/syntax_tree/yarv/compiler.rb b/lib/syntax_tree/yarv/compiler.rb index 3ea6d22a..046fb438 100644 --- a/lib/syntax_tree/yarv/compiler.rb +++ b/lib/syntax_tree/yarv/compiler.rb @@ -650,14 +650,36 @@ def visit_call(node) flag |= CallData::CALL_ARGS_SPLAT visit(arg_part) when ArgsForward - flag |= CallData::CALL_ARGS_SPLAT - flag |= CallData::CALL_ARGS_BLOCKARG flag |= CallData::CALL_TAILCALL if options.tailcall_optimization? - lookup = iseq.local_table.find(:*) - iseq.getlocal(lookup.index, lookup.level) - iseq.splatarray(arg_parts.length != 1) + if RUBY_VERSION < "3.2" + flag |= CallData::CALL_ARGS_SPLAT + lookup = iseq.local_table.find(:*) + iseq.getlocal(lookup.index, lookup.level) + iseq.splatarray(arg_parts.length != 1) + else + flag |= CallData::CALL_ARGS_SPLAT + lookup = iseq.local_table.find(:*) + iseq.getlocal(lookup.index, lookup.level) + iseq.splatarray(true) + + flag |= CallData::CALL_KW_SPLAT + iseq.putspecialobject(PutSpecialObject::OBJECT_VMCORE) + iseq.newhash(0) + lookup = iseq.local_table.find(:**) + iseq.getlocal(lookup.index, lookup.level) + iseq.send( + YARV.calldata( + :"core#hash_merge_kwd", + 2, + CallData::CALL_ARGS_SIMPLE + ) + ) + iseq.newarray(1) + iseq.concatarray + end + flag |= CallData::CALL_ARGS_BLOCKARG lookup = iseq.local_table.find(:&) iseq.getblockparamproxy(lookup.index, lookup.level) when BareAssocHash @@ -1304,13 +1326,25 @@ def visit_params(node) end if node.keyword_rest.is_a?(ArgsForward) - iseq.local_table.plain(:*) - iseq.local_table.plain(:&) + if RUBY_VERSION >= "3.2" + iseq.local_table.plain(:*) + iseq.local_table.plain(:**) + iseq.local_table.plain(:&) + + iseq.argument_options[:rest_start] = iseq.argument_size + iseq.argument_options[:block_start] = iseq.argument_size + 2 + iseq.argument_options[:kwrest] = iseq.argument_size + 1 - iseq.argument_options[:rest_start] = iseq.argument_size - iseq.argument_options[:block_start] = iseq.argument_size + 1 + iseq.argument_size += 3 + else + iseq.local_table.plain(:*) + iseq.local_table.plain(:&) + + iseq.argument_options[:rest_start] = iseq.argument_size + iseq.argument_options[:block_start] = iseq.argument_size + 1 - iseq.argument_size += 2 + iseq.argument_size += 2 + end elsif node.keyword_rest visit(node.keyword_rest) end