Project

General

Profile

Feature #16378 ยป ruby_2_7_lead_args_forwarding.patch

jeremyevans0 (Jeremy Evans), 06/19/2020 04:20 PM

View differences:

parse.y
2421 2421
		    /*% %*/
2422 2422
		    /*% ripper: arg_paren!(escape_Qundef($2)) %*/
2423 2423
		    }
2424
		| '(' args ',' args_forward rparen
2425
		    {
2426
			if (!local_id(p, idFWD_REST) ||
2427
#if idFWD_KWREST
2428
			    !local_id(p, idFWD_KWREST) ||
2429
#endif
2430
			    !local_id(p, idFWD_BLOCK)) {
2431
			    compile_error(p, "unexpected ...");
2432
			    $$ = Qnone;
2433
			}
2434
			else {
2435
			/*%%%*/
2436
			    NODE *splat = NEW_SPLAT(NEW_LVAR(idFWD_REST, &@4), &@4);
2437
#if idFWD_KWREST
2438
			    NODE *kwrest = list_append(p, NEW_LIST(0, &@4), NEW_LVAR(idFWD_KWREST, &@4));
2439
#endif
2440
			    NODE *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@4), &@4);
2441
			    $$ = rest_arg_append(p, $2, splat, &@$);
2442
#if idFWD_KWREST
2443
			    $$ = arg_append(p, $$, new_hash(p, kwrest, &@4), &@4);
2444
#endif
2445
			    $$ = arg_blk_pass($$, block);
2446
			/*% %*/
2447
			/*% ripper: arg_paren!(args_add!($2, $4)) %*/
2448
			}
2449
		    }
2424 2450
		| '(' args_forward rparen
2425 2451
		    {
2426 2452
			if (!local_id(p, idFWD_REST) ||
......
4813 4839
			SET_LEX_STATE(EXPR_BEG);
4814 4840
			p->command_start = TRUE;
4815 4841
		    }
4842
		| '(' f_arg ',' args_forward rparen
4843
		    {
4844
			arg_var(p, idFWD_REST);
4845
#if idFWD_KWREST
4846
			arg_var(p, idFWD_KWREST);
4847
#endif
4848
			arg_var(p, idFWD_BLOCK);
4849
		    /*%%%*/
4850
			$$ = new_args_tail(p, Qnone, idFWD_KWREST, idFWD_BLOCK, &@4);
4851
			$$ = new_args(p, $2, Qnone, idFWD_REST, Qnone, $$, &@4);
4852
		    /*% %*/
4853
		    /*% ripper: paren!(params_new($2, Qnone, $4, Qnone, Qnone, Qnone, Qnone)) %*/
4854
			SET_LEX_STATE(EXPR_BEG);
4855
			p->command_start = TRUE;
4856
		    }
4816 4857
		| '(' args_forward rparen
4817 4858
		    {
4818 4859
			arg_var(p, idFWD_REST);
test/ripper/test_parser_events.rb
132 132
  end
133 133

  
134 134
  def test_args_forward
135
    thru_args_forward = false
136
    parse('def m(...) n(...) end', :on_args_forward) {thru_args_forward = true}
137
    assert_equal true, thru_args_forward
135
    [
136
      'def m(...) n(...) end',
137
      'def m(...) end',
138
      'def m(a, ...) n(1, ...) end',
139
      'def m(...) n(1, ...) end',
140
      'def m(a, ...) n(...) end'
141
    ].each do |code|
142
      thru_args_forward = false
143
      parse(code, :on_args_forward) {thru_args_forward = true}
144
      assert_equal true, thru_args_forward, "no args_forward for: #{code}"
145
    end
138 146
  end
139 147

  
140 148
  def test_arg_paren
test/ruby/test_syntax.rb
1539 1539
    end
1540 1540
  end
1541 1541

  
1542
  def test_argument_forwarding_with_leading_arguments
1543
    obj = Object.new
1544
    def obj.bar(*args, **kws, &block)
1545
      if block
1546
        block.call(args, kws)
1547
      else
1548
        [args, kws]
1549
      end
1550
    end
1551
    obj.instance_eval('def foo(_a, ...) bar(...) end', __FILE__, __LINE__)
1552
    assert_equal [[], {}], obj.foo(1)
1553
    assert_equal [[2], {}], obj.foo(1, 2)
1554
    assert_equal [[2, 3], {}], obj.foo(1, 2, 3)
1555
    assert_equal [[], {a: 1}], obj.foo(1, a: 1)
1556
    assert_equal [[2], {a: 1}], obj.foo(1, 2, a: 1)
1557
    assert_equal [[2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1)
1558
    assert_equal [[2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1){|args, kws| [args, kws]}
1559

  
1560
    obj.singleton_class.send(:remove_method, :foo)
1561
    obj.instance_eval('def foo(...) bar(1, ...) end', __FILE__, __LINE__)
1562
    assert_equal [[1], {}], obj.foo
1563
    assert_equal [[1, 1], {}], obj.foo(1)
1564
    assert_equal [[1, 1, 2], {}], obj.foo(1, 2)
1565
    assert_equal [[1, 1, 2, 3], {}], obj.foo(1, 2, 3)
1566
    assert_equal [[1], {a: 1}], obj.foo(a: 1)
1567
    assert_equal [[1, 1], {a: 1}], obj.foo(1, a: 1)
1568
    assert_equal [[1, 1, 2], {a: 1}], obj.foo(1, 2, a: 1)
1569
    assert_equal [[1, 1, 2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1)
1570
    assert_equal [[1, 1, 2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1){|args, kws| [args, kws]}
1571

  
1572
    obj.singleton_class.send(:remove_method, :foo)
1573
    obj.instance_eval('def foo(a, ...) bar(a, ...) end', __FILE__, __LINE__)
1574
    assert_equal [[4], {}], obj.foo(4)
1575
    assert_equal [[4, 2], {}], obj.foo(4, 2)
1576
    assert_equal [[4, 2, 3], {}], obj.foo(4, 2, 3)
1577
    assert_equal [[4], {a: 1}], obj.foo(4, a: 1)
1578
    assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1)
1579
    assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1)
1580
    assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]}
1581

  
1582
    obj.singleton_class.send(:remove_method, :foo)
1583
    obj.instance_eval('def foo(_a, ...) bar(1, ...) end', __FILE__, __LINE__)
1584
    assert_equal [[1], {}], obj.foo(4)
1585
    assert_equal [[1, 2], {}], obj.foo(4, 2)
1586
    assert_equal [[1, 2, 3], {}], obj.foo(4, 2, 3)
1587
    assert_equal [[1], {a: 1}], obj.foo(4, a: 1)
1588
    assert_equal [[1, 2], {a: 1}], obj.foo(4, 2, a: 1)
1589
    assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1)
1590
    assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]}
1591

  
1592
    obj.singleton_class.send(:remove_method, :foo)
1593
    obj.instance_eval('def foo(_a, _b, ...) bar(...) end', __FILE__, __LINE__)
1594
    assert_equal [[], {}], obj.foo(4, 5)
1595
    assert_equal [[2], {}], obj.foo(4, 5, 2)
1596
    assert_equal [[2, 3], {}], obj.foo(4, 5, 2, 3)
1597
    assert_equal [[], {a: 1}], obj.foo(4, 5, a: 1)
1598
    assert_equal [[2], {a: 1}], obj.foo(4, 5, 2, a: 1)
1599
    assert_equal [[2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1)
1600
    assert_equal [[2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]}
1601

  
1602
    obj.singleton_class.send(:remove_method, :foo)
1603
    obj.instance_eval('def foo(_a, _b, ...) bar(1, ...) end', __FILE__, __LINE__)
1604
    assert_equal [[1], {}], obj.foo(4, 5)
1605
    assert_equal [[1, 2], {}], obj.foo(4, 5, 2)
1606
    assert_equal [[1, 2, 3], {}], obj.foo(4, 5, 2, 3)
1607
    assert_equal [[1], {a: 1}], obj.foo(4, 5, a: 1)
1608
    assert_equal [[1, 2], {a: 1}], obj.foo(4, 5, 2, a: 1)
1609
    assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1)
1610
    assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]}
1611

  
1612
    obj.singleton_class.send(:remove_method, :foo)
1613
    obj.instance_eval('def foo(_a, ...) bar(1, 2, ...) end', __FILE__, __LINE__)
1614
    assert_equal [[1, 2], {}], obj.foo(5)
1615
    assert_equal [[1, 2, 5], {}], obj.foo(4, 5)
1616
    assert_equal [[1, 2, 5, 2], {}], obj.foo(4, 5, 2)
1617
    assert_equal [[1, 2, 5, 2, 3], {}], obj.foo(4, 5, 2, 3)
1618
    assert_equal [[1, 2, 5], {a: 1}], obj.foo(4, 5, a: 1)
1619
    assert_equal [[1, 2, 5, 2], {a: 1}], obj.foo(4, 5, 2, a: 1)
1620
    assert_equal [[1, 2, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1)
1621
    assert_equal [[1, 2, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]}
1622

  
1623
    obj.singleton_class.send(:remove_method, :foo)
1624
    obj.instance_eval('def foo(a, b, ...) bar(b, a, ...) end', __FILE__, __LINE__)
1625
    assert_equal [[5, 4], {}], obj.foo(4, 5)
1626
    assert_equal [[5, 4, 2], {}], obj.foo(4, 5, 2)
1627
    assert_equal [[5, 4, 2, 3], {}], obj.foo(4, 5, 2, 3)
1628
    assert_equal [[5, 4], {a: 1}], obj.foo(4, 5, a: 1)
1629
    assert_equal [[5, 4, 2], {a: 1}], obj.foo(4, 5, 2, a: 1)
1630
    assert_equal [[5, 4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1)
1631
    assert_equal [[5, 4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]}
1632

  
1633
    obj.singleton_class.send(:remove_method, :foo)
1634
    obj.instance_eval('def foo(a, _b, ...) bar(a, ...) end', __FILE__, __LINE__)
1635
    assert_equal [[4], {}], obj.foo(4, 5)
1636
    assert_equal [[4, 2], {}], obj.foo(4, 5, 2)
1637
    assert_equal [[4, 2, 3], {}], obj.foo(4, 5, 2, 3)
1638
    assert_equal [[4], {a: 1}], obj.foo(4, 5, a: 1)
1639
    assert_equal [[4, 2], {a: 1}], obj.foo(4, 5, 2, a: 1)
1640
    assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1)
1641
    assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]}
1642

  
1643
    obj.singleton_class.send(:remove_method, :foo)
1644
    obj.instance_eval('def foo(a, ...) bar(a, 1, ...) end', __FILE__, __LINE__)
1645
    assert_equal [[4, 1], {}], obj.foo(4)
1646
    assert_equal [[4, 1, 5], {}], obj.foo(4, 5)
1647
    assert_equal [[4, 1, 5, 2], {}], obj.foo(4, 5, 2)
1648
    assert_equal [[4, 1, 5, 2, 3], {}], obj.foo(4, 5, 2, 3)
1649
    assert_equal [[4, 1, 5], {a: 1}], obj.foo(4, 5, a: 1)
1650
    assert_equal [[4, 1, 5, 2], {a: 1}], obj.foo(4, 5, 2, a: 1)
1651
    assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1)
1652
    assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]}
1653
  end
1654

  
1542 1655
  private
1543 1656

  
1544 1657
  def not_label(x) @result = x; @not_label ||= nil end
1545
-