summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2024-01-22 11:43:00 -0500
committerPeter Zhu <peter@peterzhu.ca>2024-01-22 12:56:43 -0500
commitdbd76d9101cfb35b483ad5e173fc153102c9d03e (patch)
tree4f4a866030048f1d4aa7ad3969864b5bb7e6892e
parentab99ce910ce9a7aeb0b8a3224a1ed1e3e5faf71f (diff)
[PRISM] Fix keyword splat in IndexAndWriteNode and IndexOrWriteNode
Fixes ruby/prism#2232 and ruby/prism#2234.
-rw-r--r--prism_compile.c11
-rw-r--r--test/ruby/test_compile_prism.rb18
2 files changed, 29 insertions, 0 deletions
diff --git a/prism_compile.c b/prism_compile.c
index 40d2eb9806..4d139a57b3 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -952,6 +952,17 @@ 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 (flag & VM_CALL_KW_SPLAT) {
+ if (block_offset > 0) {
+ ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(2));
+ PM_SWAP;
+ ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(3));
+ PM_POP;
+ }
+
+ ADD_INSN(ret, &dummy_line_node, swap);
+ ADD_SEND_R(ret, &dummy_line_node, idASET, FIXNUM_INC(argc, 1), NULL, INT2FIX(flag), keywords);
+ }
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));
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
index 0998c8fa5d..8f42fb5851 100644
--- a/test/ruby/test_compile_prism.rb
+++ b/test/ruby/test_compile_prism.rb
@@ -394,6 +394,15 @@ module Prism
h[foo: 1] &&= 2
RUBY
+
+ # Test with keyword splat
+ assert_prism_eval(<<~RUBY)
+ h = Object.new
+ def h.[](**b) = 1
+ def h.[]=(*a, **b); end
+
+ h[**{}] &&= 2
+ RUBY
end
def test_IndexOrWriteNode
@@ -415,6 +424,15 @@ module Prism
hash["key", &(Proc.new { _1.upcase })] ||= "value"
hash
CODE
+
+ # Test with keyword splat
+ assert_prism_eval(<<~RUBY)
+ h = Object.new
+ def h.[](**b) = nil
+ def h.[]=(*a, **b); end
+
+ h[**{}] ||= 2
+ RUBY
end
def test_IndexOperatorWriteNode