diff options
Diffstat (limited to 'gcc/rust/ast/rust-ast.h')
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 224 |
1 files changed, 191 insertions, 33 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index ba973f1..e72937e 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -22,9 +22,6 @@ #include "rust-system.h" #include "rust-hir-map.h" - -// gccrs imports -// required for AST::Token #include "rust-token.h" #include "rust-location.h" @@ -32,7 +29,6 @@ namespace Rust { // TODO: remove typedefs and make actual types for these typedef std::string Identifier; typedef int TupleIndex; - struct Session; namespace AST { @@ -48,34 +44,6 @@ enum DelimType CURLY }; -// Base AST node object - TODO is this really required or useful? Where to draw -// line? -/*class Node { - public: - // Gets node's Location. - Location get_locus() const { - return loc; - } - - // Sets node's Location. - void set_locus(Location loc_) { - loc = loc_; - } - - // Get node output as a string. Pure virtual. - virtual std::string as_string() const = 0; - - virtual ~Node() {} - - // TODO: constructor including Location? Make all derived classes have -Location? - - private: - // The node's location. - Location loc; -};*/ -// decided to not have node as a "node" would never need to be stored - // forward decl for use in token tree method class Token; @@ -108,6 +76,14 @@ protected: class MacroMatch { public: + enum MacroMatchType + { + Fragment, + Repetition, + Matcher, + Tok + }; + virtual ~MacroMatch () {} virtual std::string as_string () const = 0; @@ -121,6 +97,8 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + virtual MacroMatchType get_macro_match_type () const = 0; + protected: // pure virtual clone implementation virtual MacroMatch *clone_macro_match_impl () const = 0; @@ -234,6 +212,11 @@ public: // Get a new token pointer copy. const_TokenPtr get_tok_ptr () const { return tok_ref; } + MacroMatchType get_macro_match_type () const override + { + return MacroMatchType::Tok; + } + protected: // No virtual for now as not polymorphic but can be in future /*virtual*/ Token *clone_token_impl () const { return new Token (*this); } @@ -788,6 +771,13 @@ public: { return AttrInput::AttrInputType::TOKEN_TREE; } + + std::vector<std::unique_ptr<TokenTree> > &get_token_trees () + { + return token_trees; + } + + DelimType get_delim_type () const { return delim_type; } }; /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to @@ -1485,6 +1475,160 @@ public: } }; +class SingleASTNode +{ +public: + enum NodeType + { + EXPRESSION, + ITEM, + STMT, + }; + + SingleASTNode (std::unique_ptr<Expr> expr) + : type (EXPRESSION), expr (std::move (expr)), item (nullptr), stmt (nullptr) + {} + + SingleASTNode (std::unique_ptr<Item> item) + : type (ITEM), expr (nullptr), item (std::move (item)), stmt (nullptr) + {} + + SingleASTNode (std::unique_ptr<Stmt> stmt) + : type (STMT), expr (nullptr), item (nullptr), stmt (std::move (stmt)) + {} + + SingleASTNode (SingleASTNode const &other) + { + type = other.type; + switch (type) + { + case EXPRESSION: + expr = other.expr->clone_expr (); + break; + + case ITEM: + item = other.item->clone_item (); + break; + + case STMT: + stmt = other.stmt->clone_stmt (); + break; + } + } + + SingleASTNode operator= (SingleASTNode const &other) + { + type = other.type; + switch (type) + { + case EXPRESSION: + expr = other.expr->clone_expr (); + break; + + case ITEM: + item = other.item->clone_item (); + break; + + case STMT: + stmt = other.stmt->clone_stmt (); + break; + } + return *this; + } + + SingleASTNode (SingleASTNode &&other) = default; + SingleASTNode &operator= (SingleASTNode &&other) = default; + + std::unique_ptr<Expr> &get_expr () + { + rust_assert (type == EXPRESSION); + return expr; + } + + std::unique_ptr<Item> &get_item () + { + rust_assert (type == ITEM); + return item; + } + + std::unique_ptr<Stmt> &get_stmt () + { + rust_assert (type == STMT); + return stmt; + } + + void accept_vis (ASTVisitor &vis) + { + switch (type) + { + case EXPRESSION: + expr->accept_vis (vis); + break; + + case ITEM: + item->accept_vis (vis); + break; + + case STMT: + stmt->accept_vis (vis); + break; + } + } + +private: + NodeType type; + + // FIXME make this a union + std::unique_ptr<Expr> expr; + std::unique_ptr<Item> item; + std::unique_ptr<Stmt> stmt; +}; + +/* Basically, a "fragment" that can be incorporated into the AST, created as + * a result of macro expansion. Really annoying to work with due to the fact + * that macros can really expand to anything. As such, horrible representation + * at the moment. */ +class ASTFragment +{ +private: + /* basic idea: essentially, a vector of tagged unions of different AST node + * types. Now, this could actually be stored without a tagged union if the + * different AST node types had a unified parent, but that would create + * issues with the diamond problem or significant performance penalties. So + * a tagged union had to be used instead. A vector is used to represent the + * ability for a macro to expand to two statements, for instance. */ + + std::vector<SingleASTNode> nodes; + +public: + ASTFragment (std::vector<SingleASTNode> nodes) : nodes (std::move (nodes)) {} + + ASTFragment (ASTFragment const &other) + { + nodes.clear (); + nodes.reserve (other.nodes.size ()); + for (auto &n : other.nodes) + { + nodes.push_back (n); + } + } + + ASTFragment &operator= (ASTFragment const &other) + { + nodes.clear (); + nodes.reserve (other.nodes.size ()); + for (auto &n : other.nodes) + { + nodes.push_back (n); + } + return *this; + } + + static ASTFragment create_empty () { return ASTFragment ({}); } + + std::vector<SingleASTNode> &get_nodes () { return nodes; } +}; + /* A macro invocation item (or statement) AST node (i.e. semi-coloned macro * invocation) */ class MacroInvocationSemi : public MacroItem, @@ -1496,6 +1640,10 @@ class MacroInvocationSemi : public MacroItem, std::vector<Attribute> outer_attrs; MacroInvocData invoc_data; Location locus; + NodeId node_id; + + // this is the expanded macro + ASTFragment fragment; public: std::string as_string () const override; @@ -1503,7 +1651,9 @@ public: MacroInvocationSemi (MacroInvocData invoc_data, std::vector<Attribute> outer_attrs, Location locus) : outer_attrs (std::move (outer_attrs)), - invoc_data (std::move (invoc_data)), locus (locus) + invoc_data (std::move (invoc_data)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()), + fragment (ASTFragment::create_empty ()) {} void accept_vis (ASTVisitor &vis) override; @@ -1527,6 +1677,14 @@ public: Location get_locus () const override final { return locus; } + MacroInvocData &get_invoc_data () { return invoc_data; } + + ASTFragment &get_fragment () { return fragment; } + + void set_fragment (ASTFragment &&f) { fragment = std::move (f); } + + NodeId get_macro_node_id () const { return node_id; } + protected: MacroInvocationSemi *clone_macro_invocation_semi_impl () const { |