[前][次][番号順一覧][スレッド一覧]

ruby-changes:57493

From: Jeremy <ko1@a...>
Date: Tue, 3 Sep 2019 00:21:46 +0900 (JST)
Subject: [ruby-changes:57493] f560609d66 (master): Merge pull request #2418 from jeremyevans/array-empty-kwsplat

https://git.ruby-lang.org/ruby.git/commit/?id=f560609d66

From f560609d66502101264706877577220e3ebf5a38 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Mon, 2 Sep 2019 08:21:30 -0700
Subject: Merge pull request #2418 from jeremyevans/array-empty-kwsplat

Ignore empty keyword splats in arrays

diff --git a/compile.c b/compile.c
index 774aced..ad99982 100644
--- a/compile.c
+++ b/compile.c
@@ -4025,8 +4025,21 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro https://github.com/ruby/ruby/blob/trunk/compile.c#L4025
 	    else {
 		if (!popped || kw) {
 		    switch (type) {
-		      case COMPILE_ARRAY_TYPE_ARRAY:
-			ADD_INSN1(anchor, line, newarray, INT2FIX(i));
+                      case COMPILE_ARRAY_TYPE_ARRAY: {
+                        const NODE *check_node = node_root;
+
+                        /* Find last node in array, and if it is a keyword argument, then set
+                           flag to check and remove empty keyword arguments hash from array */
+                        while(check_node->nd_next) {
+                            check_node = check_node->nd_next;
+                        }
+                        if (nd_type(check_node->nd_head) == NODE_HASH && check_node->nd_head->nd_brace == 0) {
+                            ADD_INSN1(anchor, line, newarraykwsplat, INT2FIX(i));
+                        }
+                        else {
+                            ADD_INSN1(anchor, line, newarray, INT2FIX(i));
+                        }
+
 
 			if (first) {
 			    first = 0;
@@ -4037,6 +4050,7 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro https://github.com/ruby/ruby/blob/trunk/compile.c#L4050
 
 			APPEND_LIST(ret, anchor);
 			break;
+                      }
 		      case COMPILE_ARRAY_TYPE_HASH:
 			if (i > 0) {
 			    if (first) {
diff --git a/insns.def b/insns.def
index 35a6aa9..1399687 100644
--- a/insns.def
+++ b/insns.def
@@ -441,6 +441,26 @@ newarray https://github.com/ruby/ruby/blob/trunk/insns.def#L441
     val = rb_ary_new4(num, STACK_ADDR_FROM_TOP(num));
 }
 
+/* put new array initialized with num values on the stack. There
+   should be at least one element on the stack, and the top element
+   should be a hash.  If the top element is empty, it is not
+   included in the array.
+ */
+DEFINE_INSN
+newarraykwsplat
+(rb_num_t num)
+(...)
+(VALUE val)
+// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
+{
+    if (RHASH_EMPTY_P(*STACK_ADDR_FROM_TOP(1))) {
+        val = rb_ary_new4(num-1, STACK_ADDR_FROM_TOP(num));
+    }
+    else {
+        val = rb_ary_new4(num, STACK_ADDR_FROM_TOP(num));
+    }
+}
+
 /* dup array */
 DEFINE_INSN
 duparray
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index b98a233..56e2937 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -100,6 +100,33 @@ class TestSyntax < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L100
     EOS
   end
 
+  def test_array_kwsplat_hash
+    kw = {}
+    h = {a: 1}
+    assert_equal([], [**{}])
+    assert_equal([], [**kw])
+    assert_equal([h], [**h])
+    assert_equal([{}], [{}])
+    assert_equal([kw], [kw])
+    assert_equal([h], [h])
+
+    assert_equal([1], [1, **{}])
+    assert_equal([1], [1, **kw])
+    assert_equal([1, h], [1, **h])
+    assert_equal([1, {}], [1, {}])
+    assert_equal([1, kw], [1, kw])
+    assert_equal([1, h], [1, h])
+
+    assert_equal([], [**kw, **kw])
+    assert_equal([], [**kw, **{}, **kw])
+    assert_equal([1], [1, **kw, **{}, **kw])
+
+    assert_equal([{}], [{}, **kw, **kw])
+    assert_equal([kw], [kw, **kw, **kw])
+    assert_equal([h], [h, **kw, **kw])
+    assert_equal([h, h], [h, **kw, **kw, **h])
+  end
+
   def test_normal_argument
     assert_valid_syntax('def foo(x) end')
     assert_syntax_error('def foo(X) end', /constant/)
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]