Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #ifndef RUST_AST_FRAGMENT_H
20 : : #define RUST_AST_FRAGMENT_H
21 : :
22 : : #include "rust-ast.h"
23 : : #include "rust-system.h"
24 : :
25 : : namespace Rust {
26 : : namespace AST {
27 : :
28 : : enum class FragmentKind
29 : : {
30 : : /**
31 : : * A completely expanded AST Fragment. This signifies that all
32 : : * `SingleASTNode`s in the `nodes` vector are valid.
33 : : *
34 : : * Note that this doesn't imply that the expansion is "done". One of the
35 : : * expanded nodes could very well be another macro invocation
36 : : */
37 : : Complete,
38 : : /**
39 : : * An error fragment.
40 : : */
41 : : Error,
42 : : };
43 : :
44 : : /**
45 : : * An AST Fragment. Previously named `ASTFragment`.
46 : : *
47 : : * Basically, a "fragment" that can be incorporated into the AST, created as
48 : : * a result of macro expansion. Really annoying to work with due to the fact
49 : : * that macros can really expand to anything. As such, horrible representation
50 : : * at the moment.
51 : : */
52 : 2369215 : class Fragment
53 : : {
54 : : public:
55 : : Fragment (Fragment const &other);
56 : : Fragment &operator= (Fragment const &other);
57 : :
58 : : /**
59 : : * Create an error fragment
60 : : */
61 : : static Fragment create_error ();
62 : :
63 : : /**
64 : : * Create an empty fragment
65 : : */
66 : : static Fragment create_empty ();
67 : :
68 : : /**
69 : : * Create a complete AST fragment
70 : : */
71 : : Fragment (std::vector<AST::SingleASTNode> nodes,
72 : : std::vector<std::unique_ptr<AST::Token>> tokens);
73 : :
74 : : /**
75 : : * Create a complete AST fragment made of a single token
76 : : */
77 : : Fragment (std::vector<AST::SingleASTNode> nodes,
78 : : std::unique_ptr<AST::Token> tok);
79 : :
80 : : FragmentKind get_kind () const;
81 : : std::vector<SingleASTNode> &get_nodes ();
82 : : std::vector<std::unique_ptr<AST::Token>> &get_tokens ();
83 : :
84 : : bool is_error () const;
85 : : bool should_expand () const;
86 : :
87 : : bool is_expression_fragment () const;
88 : : bool is_type_fragment () const;
89 : :
90 : : std::unique_ptr<Expr> take_expression_fragment ();
91 : : std::unique_ptr<Type> take_type_fragment ();
92 : :
93 : : void accept_vis (ASTVisitor &vis);
94 : :
95 : : private:
96 : : Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes,
97 : : std::vector<std::unique_ptr<AST::Token>> tokens);
98 : :
99 : : FragmentKind kind;
100 : :
101 : : /**
102 : : * Basic idea: essentially, a vector of tagged unions of different AST node
103 : : * types. Now, this could actually be stored without a tagged union if the
104 : : * different AST node types had a unified parent, but that would create
105 : : * issues with the diamond problem or significant performance penalties. So
106 : : * a tagged union had to be used instead. A vector is used to represent the
107 : : * ability for a macro to expand to two statements, for instance.
108 : : */
109 : : std::vector<SingleASTNode> nodes;
110 : :
111 : : /**
112 : : * The tokens associated with an AST fragment. This vector represents the
113 : : * actual tokens of the various nodes that are part of the fragment.
114 : : */
115 : : std::vector<std::unique_ptr<AST::Token>> tokens;
116 : :
117 : : /**
118 : : * We need to make a special case for Expression and Type fragments as only
119 : : * one Node will be extracted from the `nodes` vector
120 : : */
121 : : bool is_single_fragment () const;
122 : : bool is_single_fragment_of_kind (SingleASTNode::NodeType expected) const;
123 : : void assert_single_fragment (SingleASTNode::NodeType expected) const;
124 : : };
125 : :
126 : : /**
127 : : * This is the type for transcriber functions found in
128 : : * rust-macro-builtins.{h,cc}.
129 : : */
130 : : using MacroTranscriberFunc
131 : : = std::function<tl::optional<Fragment> (location_t, MacroInvocData &)>;
132 : :
133 : : } // namespace AST
134 : : } // namespace Rust
135 : :
136 : : #endif // !RUST_AST_FRAGMENT_H
|