diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-10-21 13:05:18 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-21 13:05:18 +0000 |
commit | 60b21d2f58f46c93fc33f6192682abfed62d8dd9 (patch) | |
tree | 2f8fd5e728e601f5fa74d71afe1579a5fd3ba440 /gcc/rust/ast/rust-ast-fragment.h | |
parent | dfb5921b76589c09e7794f5f8010427b93616e9d (diff) | |
parent | 89490980726d298311107a452bdebeb43a2ff7e6 (diff) | |
download | gcc-60b21d2f58f46c93fc33f6192682abfed62d8dd9.zip gcc-60b21d2f58f46c93fc33f6192682abfed62d8dd9.tar.gz gcc-60b21d2f58f46c93fc33f6192682abfed62d8dd9.tar.bz2 |
Merge #1607
1607: Improve AST Fragment class r=CohenArthur a=CohenArthur
This changes the APIs around creating AST fragments and refactors the class into its own header and source file, hopefully making it easier to use. This will also help creating "unexpanded" AST fragments for proper builtin macro expansion with the new fixed-point algorithm introduced by #1606
`@liushuyu` pinging you since you've worked extensively with the macro system. Would love your review!
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Diffstat (limited to 'gcc/rust/ast/rust-ast-fragment.h')
-rw-r--r-- | gcc/rust/ast/rust-ast-fragment.h | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h new file mode 100644 index 0000000..3ef4ba1 --- /dev/null +++ b/gcc/rust/ast/rust-ast-fragment.h @@ -0,0 +1,118 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_FRAGMENT_H +#define RUST_AST_FRAGMENT_H + +#include "rust-ast.h" +#include "rust-system.h" + +namespace Rust { +namespace AST { + +enum class FragmentKind +{ + /** + * If an AST Fragment still contains unexpanded tokens - this should only be + * used in the case of builtin macros which need to be expanded eagerly. + */ + Unexpanded, + /** + * A completely expanded AST Fragment. This signifies that all + * `SingleASTNode`s in the `nodes` vector are valid. + * + * Note that this doesn't imply that the expansion is "done". One of the + * expanded nodes could very well be another macro invocation + */ + Complete, + /** + * An error fragment. + */ + Error, +}; + +/** + * An AST Fragment. Previously named `ASTFragment`. + * + * 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 Fragment +{ +public: + Fragment (Fragment const &other); + Fragment &operator= (Fragment const &other); + + /** + * Create an error fragment + */ + static Fragment create_error (); + + /** + * Create a complete AST fragment + */ + static Fragment complete (std::vector<AST::SingleASTNode> nodes); + + /** + * Create a fragment which contains unexpanded nodes + */ + static Fragment unexpanded (); + + FragmentKind get_kind () const; + std::vector<SingleASTNode> &get_nodes (); + + bool is_error () const; + bool should_expand () const; + + bool is_expression_fragment () const; + bool is_type_fragment () const; + + std::unique_ptr<Expr> take_expression_fragment (); + std::unique_ptr<Type> take_type_fragment (); + + void accept_vis (ASTVisitor &vis); + +private: + Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes); + + FragmentKind kind; + + /** + * 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; + + /** + * We need to make a special case for Expression and Type fragments as only + * one Node will be extracted from the `nodes` vector + */ + bool is_single_fragment () const; + bool is_single_fragment_of_kind (SingleASTNode::NodeType expected) const; + void assert_single_fragment (SingleASTNode::NodeType expected) const; +}; +} // namespace AST +} // namespace Rust + +#endif // !RUST_AST_FRAGMENT_H |