2222
2323#include " rust-system.h"
2424#include " rust-hir-map.h"
25-
26- // gccrs imports
27- // required for AST::Token
2825#include " rust-token.h"
2926#include " rust-location.h"
3027
3128namespace Rust {
3229// TODO: remove typedefs and make actual types for these
3330typedef std::string Identifier;
3431typedef int TupleIndex;
35-
3632struct Session ;
3733
3834namespace AST {
@@ -48,34 +44,6 @@ enum DelimType
4844 CURLY
4945};
5046
51- // Base AST node object - TODO is this really required or useful? Where to draw
52- // line?
53- /* class Node {
54- public:
55- // Gets node's Location.
56- Location get_locus() const {
57- return loc;
58- }
59-
60- // Sets node's Location.
61- void set_locus(Location loc_) {
62- loc = loc_;
63- }
64-
65- // Get node output as a string. Pure virtual.
66- virtual std::string as_string() const = 0;
67-
68- virtual ~Node() {}
69-
70- // TODO: constructor including Location? Make all derived classes have
71- Location?
72-
73- private:
74- // The node's location.
75- Location loc;
76- };*/
77- // decided to not have node as a "node" would never need to be stored
78-
7947// forward decl for use in token tree method
8048class Token ;
8149
@@ -108,6 +76,14 @@ class TokenTree
10876class MacroMatch
10977{
11078public:
79+ enum MacroMatchType
80+ {
81+ Fragment,
82+ Repetition,
83+ Matcher,
84+ Tok
85+ };
86+
11187 virtual ~MacroMatch () {}
11288
11389 virtual std::string as_string () const = 0;
@@ -121,6 +97,8 @@ class MacroMatch
12197
12298 virtual void accept_vis (ASTVisitor &vis) = 0;
12399
100+ virtual MacroMatchType get_macro_match_type () const = 0;
101+
124102protected:
125103 // pure virtual clone implementation
126104 virtual MacroMatch *clone_macro_match_impl () const = 0;
@@ -234,6 +212,11 @@ class Token : public TokenTree, public MacroMatch
234212 // Get a new token pointer copy.
235213 const_TokenPtr get_tok_ptr () const { return tok_ref; }
236214
215+ MacroMatchType get_macro_match_type () const override
216+ {
217+ return MacroMatchType::Tok;
218+ }
219+
237220protected:
238221 // No virtual for now as not polymorphic but can be in future
239222 /* virtual*/ Token *clone_token_impl () const { return new Token (*this ); }
@@ -788,6 +771,13 @@ class DelimTokenTree : public TokenTree, public AttrInput
788771 {
789772 return AttrInput::AttrInputType::TOKEN_TREE;
790773 }
774+
775+ std::vector<std::unique_ptr<TokenTree> > &get_token_trees ()
776+ {
777+ return token_trees;
778+ }
779+
780+ DelimType get_delim_type () const { return delim_type; }
791781};
792782
793783/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to
@@ -1485,6 +1475,160 @@ struct MacroInvocData
14851475 }
14861476};
14871477
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+
14881632/* A macro invocation item (or statement) AST node (i.e. semi-coloned macro
14891633 * invocation) */
14901634class MacroInvocationSemi : public MacroItem ,
@@ -1496,14 +1640,20 @@ class MacroInvocationSemi : public MacroItem,
14961640 std::vector<Attribute> outer_attrs;
14971641 MacroInvocData invoc_data;
14981642 Location locus;
1643+ NodeId node_id;
1644+
1645+ // this is the expanded macro
1646+ ASTFragment fragment;
14991647
15001648public:
15011649 std::string as_string () const override ;
15021650
15031651 MacroInvocationSemi (MacroInvocData invoc_data,
15041652 std::vector<Attribute> outer_attrs, Location locus)
15051653 : outer_attrs (std::move (outer_attrs)),
1506- 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 ())
15071657 {}
15081658
15091659 void accept_vis (ASTVisitor &vis) override ;
@@ -1527,6 +1677,14 @@ class MacroInvocationSemi : public MacroItem,
15271677
15281678 Location get_locus () const override final { return locus; }
15291679
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+
15301688protected:
15311689 MacroInvocationSemi *clone_macro_invocation_semi_impl () const
15321690 {
0 commit comments