Skip to content

Commit 37415ee

Browse files
committed
Semicolon based macro invocation
This allows for macro invocation at the toplevel or as statements. This patched required us to propogate the delimited token tree fix to include the delimiter tokens. The rest of the fix was straight forward to call the apropriate visitors in names resolution and hir lowering. Some thought will be needed to handle hir lowering for repeating items.
1 parent 4c70d7e commit 37415ee

15 files changed

+430
-156
lines changed

gcc/rust/ast/rust-ast.h

Lines changed: 169 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,160 @@ struct MacroInvocData
14751475
}
14761476
};
14771477

1478+
class SingleASTNode
1479+
{
1480+
public:
1481+
enum NodeType
1482+
{
1483+
EXPRESSION,
1484+
ITEM,
1485+
STMT,
1486+
};
1487+
1488+
SingleASTNode (std::unique_ptr<Expr> expr)
1489+
: type (EXPRESSION), expr (std::move (expr)), item (nullptr), stmt (nullptr)
1490+
{}
1491+
1492+
SingleASTNode (std::unique_ptr<Item> item)
1493+
: type (ITEM), expr (nullptr), item (std::move (item)), stmt (nullptr)
1494+
{}
1495+
1496+
SingleASTNode (std::unique_ptr<Stmt> stmt)
1497+
: type (STMT), expr (nullptr), item (nullptr), stmt (std::move (stmt))
1498+
{}
1499+
1500+
SingleASTNode (SingleASTNode const &other)
1501+
{
1502+
type = other.type;
1503+
switch (type)
1504+
{
1505+
case EXPRESSION:
1506+
expr = other.expr->clone_expr ();
1507+
break;
1508+
1509+
case ITEM:
1510+
item = other.item->clone_item ();
1511+
break;
1512+
1513+
case STMT:
1514+
stmt = other.stmt->clone_stmt ();
1515+
break;
1516+
}
1517+
}
1518+
1519+
SingleASTNode operator= (SingleASTNode const &other)
1520+
{
1521+
type = other.type;
1522+
switch (type)
1523+
{
1524+
case EXPRESSION:
1525+
expr = other.expr->clone_expr ();
1526+
break;
1527+
1528+
case ITEM:
1529+
item = other.item->clone_item ();
1530+
break;
1531+
1532+
case STMT:
1533+
stmt = other.stmt->clone_stmt ();
1534+
break;
1535+
}
1536+
return *this;
1537+
}
1538+
1539+
SingleASTNode (SingleASTNode &&other) = default;
1540+
SingleASTNode &operator= (SingleASTNode &&other) = default;
1541+
1542+
std::unique_ptr<Expr> &get_expr ()
1543+
{
1544+
rust_assert (type == EXPRESSION);
1545+
return expr;
1546+
}
1547+
1548+
std::unique_ptr<Item> &get_item ()
1549+
{
1550+
rust_assert (type == ITEM);
1551+
return item;
1552+
}
1553+
1554+
std::unique_ptr<Stmt> &get_stmt ()
1555+
{
1556+
rust_assert (type == STMT);
1557+
return stmt;
1558+
}
1559+
1560+
void accept_vis (ASTVisitor &vis)
1561+
{
1562+
switch (type)
1563+
{
1564+
case EXPRESSION:
1565+
expr->accept_vis (vis);
1566+
break;
1567+
1568+
case ITEM:
1569+
item->accept_vis (vis);
1570+
break;
1571+
1572+
case STMT:
1573+
stmt->accept_vis (vis);
1574+
break;
1575+
}
1576+
}
1577+
1578+
private:
1579+
NodeType type;
1580+
1581+
// FIXME make this a union
1582+
std::unique_ptr<Expr> expr;
1583+
std::unique_ptr<Item> item;
1584+
std::unique_ptr<Stmt> stmt;
1585+
};
1586+
1587+
/* Basically, a "fragment" that can be incorporated into the AST, created as
1588+
* a result of macro expansion. Really annoying to work with due to the fact
1589+
* that macros can really expand to anything. As such, horrible representation
1590+
* at the moment. */
1591+
class ASTFragment
1592+
{
1593+
private:
1594+
/* basic idea: essentially, a vector of tagged unions of different AST node
1595+
* types. Now, this could actually be stored without a tagged union if the
1596+
* different AST node types had a unified parent, but that would create
1597+
* issues with the diamond problem or significant performance penalties. So
1598+
* a tagged union had to be used instead. A vector is used to represent the
1599+
* ability for a macro to expand to two statements, for instance. */
1600+
1601+
std::vector<SingleASTNode> nodes;
1602+
1603+
public:
1604+
ASTFragment (std::vector<SingleASTNode> nodes) : nodes (std::move (nodes)) {}
1605+
1606+
ASTFragment (ASTFragment const &other)
1607+
{
1608+
nodes.clear ();
1609+
nodes.reserve (other.nodes.size ());
1610+
for (auto &n : other.nodes)
1611+
{
1612+
nodes.push_back (n);
1613+
}
1614+
}
1615+
1616+
ASTFragment &operator= (ASTFragment const &other)
1617+
{
1618+
nodes.clear ();
1619+
nodes.reserve (other.nodes.size ());
1620+
for (auto &n : other.nodes)
1621+
{
1622+
nodes.push_back (n);
1623+
}
1624+
return *this;
1625+
}
1626+
1627+
static ASTFragment create_empty () { return ASTFragment ({}); }
1628+
1629+
std::vector<SingleASTNode> &get_nodes () { return nodes; }
1630+
};
1631+
14781632
/* A macro invocation item (or statement) AST node (i.e. semi-coloned macro
14791633
* invocation) */
14801634
class MacroInvocationSemi : public MacroItem,
@@ -1486,14 +1640,20 @@ class MacroInvocationSemi : public MacroItem,
14861640
std::vector<Attribute> outer_attrs;
14871641
MacroInvocData invoc_data;
14881642
Location locus;
1643+
NodeId node_id;
1644+
1645+
// this is the expanded macro
1646+
ASTFragment fragment;
14891647

14901648
public:
14911649
std::string as_string () const override;
14921650

14931651
MacroInvocationSemi (MacroInvocData invoc_data,
14941652
std::vector<Attribute> outer_attrs, Location locus)
14951653
: outer_attrs (std::move (outer_attrs)),
1496-
invoc_data (std::move (invoc_data)), locus (locus)
1654+
invoc_data (std::move (invoc_data)), locus (locus),
1655+
node_id (Analysis::Mappings::get ()->get_next_node_id ()),
1656+
fragment (ASTFragment::create_empty ())
14971657
{}
14981658

14991659
void accept_vis (ASTVisitor &vis) override;
@@ -1517,6 +1677,14 @@ class MacroInvocationSemi : public MacroItem,
15171677

15181678
Location get_locus () const override final { return locus; }
15191679

1680+
MacroInvocData &get_invoc_data () { return invoc_data; }
1681+
1682+
ASTFragment &get_fragment () { return fragment; }
1683+
1684+
void set_fragment (ASTFragment &&f) { fragment = std::move (f); }
1685+
1686+
NodeId get_macro_node_id () const { return node_id; }
1687+
15201688
protected:
15211689
MacroInvocationSemi *clone_macro_invocation_semi_impl () const
15221690
{

gcc/rust/ast/rust-macro.h

Lines changed: 0 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -84,135 +84,6 @@ get_frag_spec_from_str (std::string str)
8484
}
8585
}
8686

87-
class SingleASTNode
88-
{
89-
public:
90-
enum NodeType
91-
{
92-
EXPRESSION,
93-
ITEM,
94-
};
95-
96-
SingleASTNode (std::unique_ptr<Expr> expr)
97-
: type (EXPRESSION), expr (std::move (expr)), item (nullptr)
98-
{}
99-
100-
SingleASTNode (std::unique_ptr<Item> item)
101-
: type (ITEM), expr (nullptr), item (std::move (item))
102-
{}
103-
104-
SingleASTNode (SingleASTNode const &other)
105-
{
106-
type = other.type;
107-
switch (type)
108-
{
109-
case EXPRESSION:
110-
expr = other.expr->clone_expr ();
111-
break;
112-
113-
case ITEM:
114-
item = other.item->clone_item ();
115-
break;
116-
}
117-
}
118-
119-
SingleASTNode operator= (SingleASTNode const &other)
120-
{
121-
type = other.type;
122-
switch (type)
123-
{
124-
case EXPRESSION:
125-
expr = other.expr->clone_expr ();
126-
break;
127-
128-
case ITEM:
129-
item = other.item->clone_item ();
130-
break;
131-
}
132-
return *this;
133-
}
134-
135-
SingleASTNode (SingleASTNode &&other) = default;
136-
SingleASTNode &operator= (SingleASTNode &&other) = default;
137-
138-
std::unique_ptr<Expr> &get_expr ()
139-
{
140-
rust_assert (type == EXPRESSION);
141-
return expr;
142-
}
143-
144-
std::unique_ptr<Item> &get_item ()
145-
{
146-
rust_assert (type == ITEM);
147-
return item;
148-
}
149-
150-
void accept_vis (ASTVisitor &vis)
151-
{
152-
switch (type)
153-
{
154-
case EXPRESSION:
155-
expr->accept_vis (vis);
156-
break;
157-
158-
case ITEM:
159-
item->accept_vis (vis);
160-
break;
161-
}
162-
}
163-
164-
private:
165-
NodeType type;
166-
std::unique_ptr<Expr> expr;
167-
std::unique_ptr<Item> item;
168-
// TODO add meta attribute
169-
};
170-
171-
/* Basically, a "fragment" that can be incorporated into the AST, created as
172-
* a result of macro expansion. Really annoying to work with due to the fact
173-
* that macros can really expand to anything. As such, horrible representation
174-
* at the moment. */
175-
class ASTFragment
176-
{
177-
private:
178-
/* basic idea: essentially, a vector of tagged unions of different AST node
179-
* types. Now, this could actually be stored without a tagged union if the
180-
* different AST node types had a unified parent, but that would create
181-
* issues with the diamond problem or significant performance penalties. So
182-
* a tagged union had to be used instead. A vector is used to represent the
183-
* ability for a macro to expand to two statements, for instance. */
184-
185-
std::vector<SingleASTNode> nodes;
186-
187-
public:
188-
ASTFragment (std::vector<SingleASTNode> nodes) : nodes (std::move (nodes)) {}
189-
190-
ASTFragment (ASTFragment const &other)
191-
{
192-
nodes.clear ();
193-
nodes.reserve (other.nodes.size ());
194-
for (auto &n : other.nodes)
195-
{
196-
nodes.push_back (n);
197-
}
198-
}
199-
200-
ASTFragment &operator= (ASTFragment const &other)
201-
{
202-
nodes.clear ();
203-
nodes.reserve (other.nodes.size ());
204-
for (auto &n : other.nodes)
205-
{
206-
nodes.push_back (n);
207-
}
208-
return *this;
209-
}
210-
211-
static ASTFragment create_empty () { return ASTFragment ({}); }
212-
213-
std::vector<SingleASTNode> &get_nodes () { return nodes; }
214-
};
215-
21687
// A macro match that has an identifier and fragment spec
21788
class MacroMatchFragment : public MacroMatch
21889
{

0 commit comments

Comments
 (0)