@@ -1595,17 +1595,19 @@ class cppfront
1595
1595
captured_part += " _" + std::to_string (mynum);
1596
1596
}
1597
1597
1598
- // Check to see if it's just a function call with "." syntax,
1598
+ // Check to see if it's just a function call with "." syntax (potentially chained with other methods) ,
1599
1599
// and if so use this path to convert it to UFCS
1600
1600
if (// there's a single-token expression followed by . and (
1601
1601
n.expr ->get_token () && // if the base expression is a single token
1602
1602
std::ssize (n.ops ) >= 2 && // and we're of the form:
1603
1603
n.ops [0 ].op ->type () == lexeme::Dot && // token . id-expr ( expr-list )
1604
1604
n.ops [1 ].op ->type () == lexeme::LeftParen &&
1605
1605
// and either there's nothing after that, or there's just a $ after that
1606
+ // or there is mathod chaining started
1606
1607
(
1607
1608
std::ssize (n.ops ) == 2 ||
1608
- (std::ssize (n.ops ) == 3 && n.ops [2 ].op ->type () == lexeme::Dollar)
1609
+ (std::ssize (n.ops ) == 3 && n.ops [2 ].op ->type () == lexeme::Dollar) ||
1610
+ (std::ssize (n.ops ) > 3 && n.ops [2 ].op ->type () == lexeme::Dot) // fsajdak: chaining identification
1609
1611
)
1610
1612
)
1611
1613
{
@@ -1618,33 +1620,42 @@ class cppfront
1618
1620
1619
1621
// Otherwise, do the UFCS work...
1620
1622
1621
- // The . has its id_expr
1622
- assert (n.ops [0 ].id_expr );
1623
+ // If method are chained we need to go from the last to the first
1624
+ // token.a(a-expr-list).b(b-expr-list).c(c-expr-list) will be tranformed to:
1625
+ // CPP2_UFCS(c, CPP2_UFCS(b, CPP2_UFCS(a,token, a-expr-list), b-expr-list), c-expr-list )
1626
+ for (auto i = std::ssize (n.ops )-1 ; i > 0 ; i -= 2 )
1627
+ {
1628
+ // The . has its id_expr
1629
+ assert (n.ops [i-1 ].id_expr );
1623
1630
1624
- // The ( has its expr_list and op_close
1625
- assert (n.ops [1 ].expr_list && n.ops [1 ].op_close );
1631
+ // The ( has its expr_list and op_close
1632
+ assert (n.ops [i ].expr_list && n.ops [i ].op_close );
1626
1633
1627
- // If there are no additional arguments, use the CPP2_UFCS_0 version
1628
- if (!n.ops [1 ].expr_list ->expressions .empty ()) {
1629
- printer.print_cpp2 (" CPP2_UFCS(" , n.position ());
1630
- }
1631
- else {
1632
- printer.print_cpp2 (" CPP2_UFCS_0(" , n.position ());
1634
+ // If there are no additional arguments, use the CPP2_UFCS_0 version
1635
+ if (!n.ops [i].expr_list ->expressions .empty ()) {
1636
+ printer.print_cpp2 (" CPP2_UFCS(" , n.position ());
1637
+ }
1638
+ else {
1639
+ printer.print_cpp2 (" CPP2_UFCS_0(" , n.position ());
1640
+ }
1641
+ emit (*n.ops [i-1 ].id_expr );
1642
+ printer.print_cpp2 (" , " , n.position ());
1633
1643
}
1634
1644
1635
- // Make the "funcname" the first argument to CPP2_UFCS
1636
- emit (* n.ops [ 0 ]. id_expr );
1637
- printer. print_cpp2 ( " , " , n. position ());
1638
-
1639
- // Then make the base expression the second argument
1640
- emit (*n. expr );
1645
+ // expr-list need to be added in reversed order then CPP2_UFCS macros
1646
+ for ( auto i = 0 ; i < std::ssize ( n.ops ); i += 2 ) {
1647
+ // Then make the base expression the second argument - only needed on the most nested call
1648
+ if (i == 0 ) {
1649
+ emit (*n. expr );
1650
+ }
1641
1651
1642
- // Then tack on any additional arguments
1643
- if (!n.ops [1 ].expr_list ->expressions .empty ()) {
1644
- printer.print_cpp2 (" , " , n.position ());
1645
- emit (*n.ops [1 ].expr_list );
1652
+ // Then tack on any additional arguments
1653
+ if (!n.ops [(i+1 )].expr_list ->expressions .empty ()) {
1654
+ printer.print_cpp2 (" , " , n.position ());
1655
+ emit (*n.ops [(i+1 )].expr_list );
1656
+ }
1657
+ printer.print_cpp2 (" )" , n.position ());
1646
1658
}
1647
- printer.print_cpp2 (" )" , n.position ());
1648
1659
1649
1660
// And we're done. This path has handled this node, so return...
1650
1661
return ;
0 commit comments