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_EXPAND_VISITOR_H
20 : : #define RUST_EXPAND_VISITOR_H
21 : :
22 : : #include "rust-ast-visitor.h"
23 : : #include "rust-macro-expand.h"
24 : : #include "rust-proc-macro.h"
25 : :
26 : : namespace Rust {
27 : :
28 : : /**
29 : : * Whether or not an attribute is a derive attribute
30 : : */
31 : : bool
32 : : is_derive (AST::Attribute &attr);
33 : :
34 : : /**
35 : : * Whether or not an attribute is builtin
36 : : */
37 : : bool
38 : : is_builtin (AST::Attribute &attr);
39 : :
40 : : class ExpandVisitor : public AST::DefaultASTVisitor
41 : : {
42 : : public:
43 : 5257 : ExpandVisitor (MacroExpander &expander) : expander (expander) {}
44 : :
45 : : /* Expand all of the macro invocations currently contained in a crate */
46 : : void go (AST::Crate &crate);
47 : :
48 : : using AST::DefaultASTVisitor::visit;
49 : :
50 : : /* Maybe expand a macro invocation in lieu of an expression */
51 : : void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr);
52 : :
53 : : /* Maybe expand a macro invocation in lieu of a type */
54 : : void maybe_expand_type (std::unique_ptr<AST::Type> &type);
55 : :
56 : : /**
57 : : * Expand all macro invocations in lieu of types within a vector of struct
58 : : * fields
59 : : */
60 : : void expand_struct_fields (std::vector<AST::StructField> &fields);
61 : :
62 : : /**
63 : : * Expand all macro invocations in lieu of types within a vector of tuple
64 : : * fields
65 : : */
66 : : void expand_tuple_fields (std::vector<AST::TupleField> &fields);
67 : :
68 : : /**
69 : : * Expand all macro invocations in lieu of types within a list of function
70 : : * parameters
71 : : */
72 : : void
73 : : expand_function_params (std::vector<std::unique_ptr<AST::Param>> ¶ms);
74 : :
75 : : /**
76 : : * Expand all macro invocations in lieu of types within a list of generic
77 : : * arguments
78 : : */
79 : : void expand_generic_args (AST::GenericArgs &args);
80 : :
81 : : /**
82 : : * Expand a macro invocation in lieu of a qualified path type
83 : : */
84 : : void expand_qualified_path_type (AST::QualifiedPathType &path_type);
85 : :
86 : : // FIXME: Add documentation
87 : : void expand_closure_params (std::vector<AST::ClosureParam> ¶ms);
88 : : void expand_where_clause (AST::WhereClause &where_clause);
89 : :
90 : : /**
91 : : * Expand a set of values, erasing them if they are marked for strip, and
92 : : * replacing them with expanded macro nodes if necessary.
93 : : * This function is slightly different from `expand_pointer_allow_strip` as
94 : : * it can only be called in certain expansion contexts - where macro
95 : : * invocations are allowed.
96 : : *
97 : : * @param ctx Context to use for macro expansion
98 : : * @param values Iterable reference over values to replace or erase
99 : : * @param extractor Function to call when replacing values with the content
100 : : * of an expanded AST node
101 : : */
102 : : template <typename T, typename U>
103 : 7365 : void expand_macro_children (MacroExpander::ContextType ctx, T &values,
104 : : std::function<U (AST::SingleASTNode)> extractor)
105 : : {
106 : 7365 : expander.push_context (ctx);
107 : :
108 : 7365 : expand_macro_children (values, extractor);
109 : :
110 : 7365 : expander.pop_context ();
111 : 7365 : }
112 : :
113 : : /**
114 : : * Same as `expand_macro_children`, but does not push a context. This is
115 : : * useful if you're already pushing the context manually anyway for proc macro
116 : : * expansion, like in `expand_inner_{items, stmts}`
117 : : */
118 : : template <typename T, typename U>
119 : 29523 : void expand_macro_children (T &values,
120 : : std::function<U (AST::SingleASTNode)> extractor)
121 : : {
122 : 77235 : for (auto it = values.begin (); it != values.end ();)
123 : : {
124 : 47712 : auto &value = *it;
125 : :
126 : : // Perform expansion
127 : 47712 : value->accept_vis (*this);
128 : :
129 : 47712 : auto final_fragment = expander.take_expanded_fragment ();
130 : :
131 : : // FIXME: Is that correct? It seems *extremely* dodgy
132 : 47712 : if (final_fragment.should_expand ())
133 : : {
134 : 528 : it = values.erase (it);
135 : 2580 : for (auto &node : final_fragment.get_nodes ())
136 : : {
137 : 2052 : auto new_node = extractor (node);
138 : 2052 : if (new_node != nullptr)
139 : : {
140 : 2039 : it = values.insert (it, std::move (new_node));
141 : 2039 : it++;
142 : : }
143 : : }
144 : : }
145 : : else
146 : : {
147 : 47184 : ++it;
148 : : }
149 : : }
150 : 29523 : }
151 : :
152 : : /**
153 : : * Perform in-place expansion of procedural macros and macro invocations for
154 : : * an item container or statement container, such as `AST::Crate`,
155 : : * `AST::Module` or `AST::BlockExpr`. This function will insert the expanded
156 : : * nodes in place, and replace macro invocations with their expanded nodes.
157 : : *
158 : : * @param values Vector of values to mutate in-place and append into
159 : : */
160 : : void expand_inner_items (std::vector<std::unique_ptr<AST::Item>> &values);
161 : : void expand_inner_stmts (AST::BlockExpr &expr);
162 : :
163 : : // TODO: See if possible to make more specialization for Impl items, Block
164 : : // stmts etc? This could allow us to remove expand_macro_children or at least
165 : : // its extractor parameter
166 : : /**
167 : : * These functions allow to easily visit `std::unique_ptr`s as well as
168 : : * _replace_ them when necessary, e.g when expanding macro invocations in a
169 : : * list of expressions or types. The most generic version of the function will
170 : : * simply call the visitor again on the pointer, but there are two
171 : : * specializations for `std::unique_ptr<Expr>` and `std::unique_ptr<Type>` to
172 : : * enable replacing as well.
173 : : */
174 : 48477 : template <typename T> void visit (std::unique_ptr<T> &value)
175 : : {
176 : 48477 : value->accept_vis (*this);
177 : 11738 : }
178 : :
179 : : template <typename T> void visit (std::unique_ptr<AST::Expr> &expr)
180 : : {
181 : : maybe_expand_expr (expr);
182 : : }
183 : :
184 : : template <typename T> void visit (std::unique_ptr<AST::Type> &type)
185 : : {
186 : : maybe_expand_type (type);
187 : : }
188 : :
189 : : void visit (AST::Crate &crate) override;
190 : : void visit (AST::DelimTokenTree &) override;
191 : : void visit (AST::AttrInputMetaItemContainer &) override;
192 : : void visit (AST::IdentifierExpr &ident_expr) override;
193 : : void visit (AST::LifetimeParam &) override;
194 : : void visit (AST::ConstGenericParam &) override;
195 : :
196 : : void visit (AST::MacroInvocation ¯o_invoc) override;
197 : :
198 : : void visit (AST::PathInExpression &path) override;
199 : : void visit (AST::TypePathSegmentGeneric &segment) override;
200 : : void visit (AST::TypePathSegmentFunction &segment) override;
201 : : void visit (AST::QualifiedPathInExpression &path) override;
202 : : void visit (AST::QualifiedPathInType &path) override;
203 : :
204 : : void visit (AST::LiteralExpr &expr) override;
205 : : void visit (AST::AttrInputLiteral &) override;
206 : : void visit (AST::AttrInputMacro &) override;
207 : : void visit (AST::MetaItemLitExpr &) override;
208 : : void visit (AST::MetaItemPathLit &) override;
209 : : void visit (AST::ErrorPropagationExpr &expr) override;
210 : : void visit (AST::ArithmeticOrLogicalExpr &expr) override;
211 : : void visit (AST::ComparisonExpr &expr) override;
212 : : void visit (AST::LazyBooleanExpr &expr) override;
213 : : void visit (AST::AssignmentExpr &expr) override;
214 : : void visit (AST::CompoundAssignmentExpr &expr) override;
215 : : void visit (AST::GroupedExpr &expr) override;
216 : : void visit (AST::StructExprStruct &expr) override;
217 : :
218 : : void visit (AST::CallExpr &expr) override;
219 : : void visit (AST::MethodCallExpr &expr) override;
220 : : void visit (AST::ClosureExprInner &expr) override;
221 : :
222 : : void visit (AST::BlockExpr &expr) override;
223 : :
224 : : void visit (AST::ClosureExprInnerTyped &expr) override;
225 : : void visit (AST::ContinueExpr &expr) override;
226 : : void visit (AST::IfExpr &expr) override;
227 : : void visit (AST::IfExprConseqElse &expr) override;
228 : : void visit (AST::IfLetExpr &expr) override;
229 : : void visit (AST::IfLetExprConseqElse &expr) override;
230 : : void visit (AST::MatchExpr &expr) override;
231 : : void visit (AST::TypeParam ¶m) override;
232 : : void visit (AST::LifetimeWhereClauseItem &) override;
233 : : void visit (AST::TypeBoundWhereClauseItem &item) override;
234 : : void visit (AST::ExternCrate &crate) override;
235 : : void visit (AST::UseTreeGlob &) override;
236 : : void visit (AST::UseTreeList &) override;
237 : : void visit (AST::UseTreeRebind &) override;
238 : : void visit (AST::UseDeclaration &use_decl) override;
239 : : void visit (AST::Function &function) override;
240 : : void visit (AST::StructStruct &struct_item) override;
241 : : void visit (AST::TupleStruct &tuple_struct) override;
242 : : void visit (AST::EnumItem &item) override;
243 : : void visit (AST::EnumItemTuple &item) override;
244 : : void visit (AST::EnumItemStruct &item) override;
245 : : void visit (AST::EnumItemDiscriminant &item) override;
246 : : void visit (AST::Union &union_item) override;
247 : : void visit (AST::ConstantItem &const_item) override;
248 : : void visit (AST::StaticItem &static_item) override;
249 : : void visit (AST::TraitItemConst &item) override;
250 : : void visit (AST::Trait &trait) override;
251 : : void visit (AST::InherentImpl &impl) override;
252 : : void visit (AST::TraitImpl &impl) override;
253 : : void visit (AST::ExternalTypeItem &item) override;
254 : : void visit (AST::ExternalStaticItem &item) override;
255 : : void visit (AST::ExternalFunctionItem &item) override;
256 : : void visit (AST::ExternBlock &block) override;
257 : :
258 : : // I don't think it would be possible to strip macros without expansion
259 : : void visit (AST::MacroMatchRepetition &) override;
260 : : void visit (AST::MacroMatcher &) override;
261 : : void visit (AST::MacroRulesDefinition &rules_def) override;
262 : : void visit (AST::MetaItemPath &) override;
263 : : void visit (AST::MetaItemSeq &) override;
264 : : void visit (AST::MetaListPaths &) override;
265 : : void visit (AST::MetaListNameValueStr &) override;
266 : : void visit (AST::StructPatternFieldIdent &field) override;
267 : : void visit (AST::GroupedPattern &pattern) override;
268 : :
269 : : void visit (AST::LetStmt &stmt) override;
270 : : void visit (AST::ExprStmt &stmt) override;
271 : :
272 : : void visit (AST::BareFunctionType &type) override;
273 : : void visit (AST::FunctionParam &type) override;
274 : : void visit (AST::SelfParam &type) override;
275 : :
276 : : template <typename T>
277 : : void expand_inner_attribute (T &item, AST::SimplePath &Path);
278 : :
279 : : template <typename T>
280 : : void visit_inner_using_attrs (T &item, std::vector<AST::Attribute> &attrs);
281 : :
282 : : template <typename T> void visit_inner_attrs (T &item);
283 : :
284 : : private:
285 : : MacroExpander &expander;
286 : : };
287 : :
288 : : } // namespace Rust
289 : :
290 : : #endif // RUST_EXPAND_VISITOR_H
|