Skip to content

Commit 51c7cf4

Browse files
Merge #998
998: Parse macro expansion properly r=CohenArthur a=CohenArthur This PR adds a base for trying to parse statements or items in macro invocations. We are now able to parse multiple items / expressions / statements properly, but do not lower them properly, which is the last remaining task in #943 New macro parsing logic: ```mermaid flowchart TD; has_semi -- Yes --> stmt; has_semi -- No --> invocation; invocation -- Is Parens --> expr; invocation -- Is Square --> expr; invocation -- Is Curly --> stmt; ``` Closes #943 Closes #959 Closes #952 Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
2 parents 77a4950 + f02392c commit 51c7cf4

30 files changed

+475
-255
lines changed

gcc/rust/ast/rust-ast.h

Lines changed: 105 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,21 +1491,21 @@ class SingleASTNode
14911491
};
14921492

14931493
SingleASTNode (std::unique_ptr<Expr> expr)
1494-
: type (EXPRESSION), expr (std::move (expr)), item (nullptr), stmt (nullptr)
1494+
: kind (EXPRESSION), expr (std::move (expr)), item (nullptr), stmt (nullptr)
14951495
{}
14961496

14971497
SingleASTNode (std::unique_ptr<Item> item)
1498-
: type (ITEM), expr (nullptr), item (std::move (item)), stmt (nullptr)
1498+
: kind (ITEM), expr (nullptr), item (std::move (item)), stmt (nullptr)
14991499
{}
15001500

15011501
SingleASTNode (std::unique_ptr<Stmt> stmt)
1502-
: type (STMT), expr (nullptr), item (nullptr), stmt (std::move (stmt))
1502+
: kind (STMT), expr (nullptr), item (nullptr), stmt (std::move (stmt))
15031503
{}
15041504

15051505
SingleASTNode (SingleASTNode const &other)
15061506
{
1507-
type = other.type;
1508-
switch (type)
1507+
kind = other.kind;
1508+
switch (kind)
15091509
{
15101510
case EXPRESSION:
15111511
expr = other.expr->clone_expr ();
@@ -1523,8 +1523,8 @@ class SingleASTNode
15231523

15241524
SingleASTNode operator= (SingleASTNode const &other)
15251525
{
1526-
type = other.type;
1527-
switch (type)
1526+
kind = other.kind;
1527+
switch (kind)
15281528
{
15291529
case EXPRESSION:
15301530
expr = other.expr->clone_expr ();
@@ -1544,27 +1544,52 @@ class SingleASTNode
15441544
SingleASTNode (SingleASTNode &&other) = default;
15451545
SingleASTNode &operator= (SingleASTNode &&other) = default;
15461546

1547-
std::unique_ptr<Expr> &get_expr ()
1547+
NodeType get_kind () const { return kind; }
1548+
1549+
std::unique_ptr<Expr> &get_inner ()
15481550
{
1549-
rust_assert (type == EXPRESSION);
1551+
rust_assert (kind == EXPRESSION);
15501552
return expr;
15511553
}
15521554

15531555
std::unique_ptr<Item> &get_item ()
15541556
{
1555-
rust_assert (type == ITEM);
1557+
rust_assert (kind == ITEM);
15561558
return item;
15571559
}
15581560

15591561
std::unique_ptr<Stmt> &get_stmt ()
15601562
{
1561-
rust_assert (type == STMT);
1563+
rust_assert (kind == STMT);
15621564
return stmt;
15631565
}
15641566

1567+
/**
1568+
* Access the inner nodes and take ownership of them.
1569+
* You can only call these functions once per node
1570+
*/
1571+
1572+
std::unique_ptr<Stmt> take_stmt ()
1573+
{
1574+
rust_assert (!is_error ());
1575+
return std::move (stmt);
1576+
}
1577+
1578+
std::unique_ptr<Expr> take_expr ()
1579+
{
1580+
rust_assert (!is_error ());
1581+
return std::move (expr);
1582+
}
1583+
1584+
std::unique_ptr<Item> take_item ()
1585+
{
1586+
rust_assert (!is_error ());
1587+
return std::move (item);
1588+
}
1589+
15651590
void accept_vis (ASTVisitor &vis)
15661591
{
1567-
switch (type)
1592+
switch (kind)
15681593
{
15691594
case EXPRESSION:
15701595
expr->accept_vis (vis);
@@ -1580,8 +1605,38 @@ class SingleASTNode
15801605
}
15811606
}
15821607

1608+
bool is_error ()
1609+
{
1610+
switch (kind)
1611+
{
1612+
case EXPRESSION:
1613+
return expr == nullptr;
1614+
case ITEM:
1615+
return item == nullptr;
1616+
case STMT:
1617+
return stmt == nullptr;
1618+
default:
1619+
return true;
1620+
}
1621+
}
1622+
1623+
std::string as_string ()
1624+
{
1625+
switch (kind)
1626+
{
1627+
case EXPRESSION:
1628+
return "Expr: " + expr->as_string ();
1629+
case ITEM:
1630+
return "Item: " + item->as_string ();
1631+
case STMT:
1632+
return "Stmt: " + stmt->as_string ();
1633+
default:
1634+
return "";
1635+
}
1636+
}
1637+
15831638
private:
1584-
NodeType type;
1639+
NodeType kind;
15851640

15861641
// FIXME make this a union
15871642
std::unique_ptr<Expr> expr;
@@ -1604,11 +1659,18 @@ class ASTFragment
16041659
* ability for a macro to expand to two statements, for instance. */
16051660

16061661
std::vector<SingleASTNode> nodes;
1662+
bool fragment_is_error;
16071663

16081664
public:
1609-
ASTFragment (std::vector<SingleASTNode> nodes) : nodes (std::move (nodes)) {}
1665+
ASTFragment (std::vector<SingleASTNode> nodes, bool fragment_is_error = false)
1666+
: nodes (std::move (nodes)), fragment_is_error (fragment_is_error)
1667+
{
1668+
if (fragment_is_error)
1669+
rust_assert (nodes.empty ());
1670+
}
16101671

16111672
ASTFragment (ASTFragment const &other)
1673+
: fragment_is_error (other.fragment_is_error)
16121674
{
16131675
nodes.clear ();
16141676
nodes.reserve (other.nodes.size ());
@@ -1620,18 +1682,47 @@ class ASTFragment
16201682

16211683
ASTFragment &operator= (ASTFragment const &other)
16221684
{
1685+
fragment_is_error = other.fragment_is_error;
16231686
nodes.clear ();
16241687
nodes.reserve (other.nodes.size ());
16251688
for (auto &n : other.nodes)
16261689
{
16271690
nodes.push_back (n);
16281691
}
1692+
16291693
return *this;
16301694
}
16311695

16321696
static ASTFragment create_empty () { return ASTFragment ({}); }
1697+
static ASTFragment create_error () { return ASTFragment ({}, true); }
16331698

16341699
std::vector<SingleASTNode> &get_nodes () { return nodes; }
1700+
bool is_error () const { return fragment_is_error; }
1701+
1702+
bool should_expand () const { return !is_error () && !nodes.empty (); }
1703+
1704+
/**
1705+
* We need to make a special case for Expression fragments as only one
1706+
* Node will be extracted from the `nodes` vector
1707+
*/
1708+
1709+
bool is_expression_fragment () const
1710+
{
1711+
return nodes.size () == 1
1712+
&& nodes[0].get_kind () == SingleASTNode::NodeType::EXPRESSION;
1713+
}
1714+
1715+
std::unique_ptr<Expr> take_expression_fragment ()
1716+
{
1717+
rust_assert (is_expression_fragment ());
1718+
return nodes[0].take_expr ();
1719+
}
1720+
1721+
void accept_vis (ASTVisitor &vis)
1722+
{
1723+
for (auto &node : nodes)
1724+
node.accept_vis (vis);
1725+
}
16351726
};
16361727

16371728
// A crate AST object - holds all the data for a single compilation unit

gcc/rust/ast/rust-macro.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,6 @@ class MacroInvocation : public TypeNoBounds,
464464
MacroInvocData invoc_data;
465465
Location locus;
466466

467-
// this is the expanded macro
468-
ASTFragment fragment;
469-
470467
// Important for when we actually expand the macro
471468
bool is_semi_coloned;
472469

@@ -480,7 +477,6 @@ class MacroInvocation : public TypeNoBounds,
480477
bool is_semi_coloned = false)
481478
: outer_attrs (std::move (outer_attrs)),
482479
invoc_data (std::move (invoc_data)), locus (locus),
483-
fragment (ASTFragment::create_empty ()),
484480
is_semi_coloned (is_semi_coloned),
485481
node_id (Analysis::Mappings::get ()->get_next_node_id ())
486482
{}
@@ -513,10 +509,6 @@ class MacroInvocation : public TypeNoBounds,
513509

514510
MacroInvocData &get_invoc_data () { return invoc_data; }
515511

516-
ASTFragment &get_fragment () { return fragment; }
517-
518-
void set_fragment (ASTFragment &&f) { fragment = std::move (f); }
519-
520512
bool has_semicolon () const { return is_semi_coloned; }
521513

522514
protected:

0 commit comments

Comments
 (0)