Line data Source code
1 : // Copyright (C) 2020-2026 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 3284418 : 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 : bool is_pattern_fragment () const;
90 :
91 : std::unique_ptr<Expr> take_expression_fragment ();
92 : std::unique_ptr<Type> take_type_fragment ();
93 : std::unique_ptr<Pattern> take_pattern_fragment ();
94 :
95 : void accept_vis (ASTVisitor &vis);
96 :
97 : private:
98 : Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes,
99 : std::vector<std::unique_ptr<AST::Token>> tokens);
100 :
101 : FragmentKind kind;
102 :
103 : /**
104 : * Basic idea: essentially, a vector of tagged unions of different AST node
105 : * types. Now, this could actually be stored without a tagged union if the
106 : * different AST node types had a unified parent, but that would create
107 : * issues with the diamond problem or significant performance penalties. So
108 : * a tagged union had to be used instead. A vector is used to represent the
109 : * ability for a macro to expand to two statements, for instance.
110 : */
111 : std::vector<SingleASTNode> nodes;
112 :
113 : /**
114 : * The tokens associated with an AST fragment. This vector represents the
115 : * actual tokens of the various nodes that are part of the fragment.
116 : */
117 : std::vector<std::unique_ptr<AST::Token>> tokens;
118 :
119 : /**
120 : * We need to make a special case for Expression and Type fragments as only
121 : * one Node will be extracted from the `nodes` vector
122 : */
123 : bool is_single_fragment () const;
124 : bool is_single_fragment_of_kind (SingleASTNode::Kind expected) const;
125 : void assert_single_fragment (SingleASTNode::Kind expected) const;
126 : };
127 :
128 : enum class InvocKind
129 : {
130 : Expr,
131 : Semicoloned,
132 : };
133 :
134 : enum class AsmKind
135 : {
136 : Global,
137 : Inline
138 : };
139 :
140 : /**
141 : * This is the type for transcriber functions found in
142 : * rust-macro-builtins.{h,cc}.
143 : */
144 : using MacroTranscriberFunc
145 : = std::function<tl::optional<Fragment> (location_t, MacroInvocData &,
146 : InvocKind semicolon)>;
147 :
148 : } // namespace AST
149 : } // namespace Rust
150 :
151 : #endif // !RUST_AST_FRAGMENT_H
|