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/