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 AST_BUILDER_H
20 : #define AST_BUILDER_H
21 :
22 : #include "rust-ast-full.h"
23 : #include "rust-expr.h"
24 : #include "rust-ast.h"
25 : #include "rust-item.h"
26 : #include "rust-operators.h"
27 : #include "options.h"
28 : #include "rust-system.h"
29 :
30 : namespace Rust {
31 : namespace AST {
32 :
33 : template <typename T>
34 : std::vector<std::unique_ptr<T>>
35 2004 : vec (std::unique_ptr<T> &&t)
36 : {
37 2004 : auto v = std::vector<std::unique_ptr<T>> ();
38 :
39 2004 : v.emplace_back (std::move (t));
40 :
41 : return v;
42 : }
43 :
44 : template <typename T>
45 : std::vector<std::unique_ptr<T>>
46 1513 : vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2)
47 : {
48 1513 : auto v = std::vector<std::unique_ptr<T>> ();
49 :
50 1513 : v.emplace_back (std::move (t1));
51 1513 : v.emplace_back (std::move (t2));
52 :
53 1513 : return v;
54 : }
55 :
56 : template <typename T>
57 : std::vector<std::unique_ptr<T>>
58 63 : vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2, std::unique_ptr<T> &&t3)
59 : {
60 63 : auto v = std::vector<std::unique_ptr<T>> ();
61 :
62 63 : v.emplace_back (std::move (t1));
63 63 : v.emplace_back (std::move (t2));
64 63 : v.emplace_back (std::move (t3));
65 :
66 63 : return v;
67 : }
68 :
69 : /* Pointer-ify something */
70 : template <typename T>
71 : static std::unique_ptr<T>
72 1434 : ptrify (T value)
73 : {
74 1434 : return std::unique_ptr<T> (new T (value));
75 : }
76 :
77 : // TODO: Use this builder when expanding regular macros
78 : /* Builder class with helper methods to create AST nodes. This builder is
79 : * tailored towards generating multiple AST nodes from a single location, and
80 : * may not be suitable to other purposes */
81 : class Builder
82 : {
83 : public:
84 : /**
85 : * Are we building AST nodes for paths within `core`, or any other crate? This
86 : * affects the leading path segment when constructing canonical paths, and is
87 : * especially important when deriving items.
88 : */
89 : enum class Source
90 : {
91 : InCore,
92 : Any,
93 : };
94 :
95 1686 : Builder (location_t loc, Source item_source)
96 1686 : : loc (loc), item_source (item_source)
97 : {}
98 :
99 : /* Create an expression statement from an expression */
100 : std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&value,
101 : bool semicolon_followed = true) const;
102 :
103 : /* Create a string literal expression ("content") */
104 : std::unique_ptr<Expr> literal_string (std::string &&content) const;
105 :
106 : /* Create a boolean literal expression (true) */
107 : std::unique_ptr<Expr> literal_bool (bool b) const;
108 :
109 : /* Create an identifier expression (`variable`) */
110 : std::unique_ptr<Expr> identifier (std::string name) const;
111 : std::unique_ptr<Pattern> identifier_pattern (std::string name,
112 : bool mut = false) const;
113 :
114 : /* Create a tuple index expression (`receiver.0`) */
115 : std::unique_ptr<Expr> tuple_idx (std::string receiver, int idx) const;
116 :
117 : /* Create a tuple expression (`(a1, a2, a3)`) */
118 : std::unique_ptr<Expr> tuple (std::vector<std::unique_ptr<Expr>> &&values
119 : = {}) const;
120 :
121 : /* Create a reference to an expression (`&of`) */
122 : std::unique_ptr<Expr> ref (std::unique_ptr<Expr> &&of,
123 : bool mut = false) const;
124 :
125 : /* Create a dereference of an expression (`*of`) */
126 : std::unique_ptr<Expr> deref (std::unique_ptr<Expr> &&of) const;
127 :
128 : /* Build a comparison expression (`lhs == rhs`) */
129 : std::unique_ptr<Expr> comparison_expr (std::unique_ptr<Expr> &&lhs,
130 : std::unique_ptr<Expr> &&rhs,
131 : ComparisonOperator op) const;
132 :
133 : /* Build a lazy boolean operator expression (`lhs && rhs`) */
134 : std::unique_ptr<Expr> boolean_operation (std::unique_ptr<Expr> &&lhs,
135 : std::unique_ptr<Expr> &&rhs,
136 : LazyBooleanOperator op) const;
137 :
138 : /* Create a block with an optional tail expression */
139 : std::unique_ptr<BlockExpr> block (std::vector<std::unique_ptr<Stmt>> &&stmts,
140 : std::unique_ptr<Expr> &&tail_expr
141 : = nullptr) const;
142 : std::unique_ptr<BlockExpr> block (tl::optional<std::unique_ptr<Stmt>> &&stmt,
143 : std::unique_ptr<Expr> &&tail_expr
144 : = nullptr) const;
145 : /* Create an empty block */
146 : std::unique_ptr<BlockExpr> block () const;
147 :
148 : /* Create a block with just a tail expression */
149 : std::unique_ptr<BlockExpr> block (std::unique_ptr<Expr> &&tail_expr) const;
150 :
151 : /* Create an early return expression with an optional expression */
152 : std::unique_ptr<Expr> return_expr (std::unique_ptr<Expr> &&to_return
153 : = nullptr);
154 :
155 : /* Create a let binding with an optional type and initializer (`let <name> :
156 : * <type> = <init>`) */
157 : std::unique_ptr<Stmt> let (std::unique_ptr<Pattern> &&pattern,
158 : std::unique_ptr<Type> &&type = nullptr,
159 : std::unique_ptr<Expr> &&init = nullptr) const;
160 :
161 : /**
162 : * Create a call expression to a function, struct or enum variant, given its
163 : * arguments (`path(arg0, arg1, arg2)`)
164 : */
165 : std::unique_ptr<Expr> call (std::unique_ptr<Expr> &&path,
166 : std::vector<std::unique_ptr<Expr>> &&args
167 : = {}) const;
168 : std::unique_ptr<Expr> call (std::unique_ptr<Expr> &&path,
169 : std::unique_ptr<Expr> &&arg) const;
170 :
171 : /**
172 : * Create an array expression (`[member0, member1, member2]`)
173 : */
174 : std::unique_ptr<Expr>
175 : array (std::vector<std::unique_ptr<Expr>> &&members) const;
176 :
177 : /* Create a qualified path in expression (`<type as Trait>::seg::expr`) */
178 : std::unique_ptr<Expr>
179 : qualified_path_in_expression (std::unique_ptr<Type> &&type, TypePath trait,
180 : PathExprSegment segment) const;
181 : std::unique_ptr<Expr>
182 : qualified_path_in_expression (std::unique_ptr<Type> &&type, TypePath trait,
183 : std::vector<PathExprSegment> &&segments
184 : = {}) const;
185 :
186 : std::unique_ptr<Expr>
187 : qualified_call (std::vector<std::string> &&segments,
188 : std::vector<std::unique_ptr<Expr>> &&args) const;
189 :
190 : /* Self parameter for a function definition (`&self`) */
191 : std::unique_ptr<Param> self_ref_param (bool mutability = false) const;
192 : /* A regular named function parameter for a definition (`a: type`) */
193 : std::unique_ptr<Param> function_param (std::unique_ptr<Pattern> &&pattern,
194 : std::unique_ptr<Type> &&type) const;
195 :
196 : /* Empty function qualifiers, with no specific qualifiers */
197 : FunctionQualifiers fn_qualifiers () const;
198 :
199 : std::unique_ptr<Function>
200 : function (std::string function_name,
201 : std::vector<std::unique_ptr<Param>> params,
202 : std::unique_ptr<Type> return_type, std::unique_ptr<BlockExpr> block,
203 : std::vector<std::unique_ptr<GenericParam>> generic_params = {},
204 : FunctionQualifiers qualifiers
205 : = FunctionQualifiers (UNKNOWN_LOCATION, Default::No, Async::No,
206 : Const::No, Unsafety::Normal),
207 : WhereClause where_clause = WhereClause::create_empty (),
208 : Visibility visibility = Visibility::create_private ()) const;
209 :
210 : /* Create a single path segment from one string */
211 : PathExprSegment path_segment (std::string seg) const;
212 :
213 : /* And similarly for type path segments */
214 : std::unique_ptr<TypePathSegment> type_path_segment (std::string seg) const;
215 : std::unique_ptr<TypePathSegment>
216 : type_path_segment (LangItem::Kind lang_item) const;
217 :
218 : std::unique_ptr<TypePathSegment>
219 : type_path_segment_generic (std::string seg, GenericArgs args) const;
220 : std::unique_ptr<TypePathSegment>
221 : type_path_segment_generic (LangItem::Kind lang_item, GenericArgs args) const;
222 :
223 : /* Create a Type from a single string - the most basic kind of type in our AST
224 : */
225 : std::unique_ptr<Type> single_type_path (std::string type) const;
226 : std::unique_ptr<Type> single_type_path (LangItem::Kind lang_item) const;
227 :
228 : std::unique_ptr<Type> single_generic_type_path (std::string type,
229 : GenericArgs args) const;
230 : std::unique_ptr<Type> single_generic_type_path (LangItem::Kind lang_item,
231 : GenericArgs args) const;
232 :
233 : TypePath type_path (std::vector<std::unique_ptr<TypePathSegment>> &&segment,
234 : bool opening_scope = false) const;
235 : TypePath type_path (std::vector<std::string> &&segments,
236 : bool opening_scope = false) const;
237 : TypePath type_path (std::unique_ptr<TypePathSegment> &&segment) const;
238 : TypePath type_path (std::string type) const;
239 : TypePath type_path (LangItem::Kind lang_item) const;
240 :
241 : std::unique_ptr<Type>
242 : reference_type (std::unique_ptr<TypeNoBounds> &&inner_type,
243 : bool mutability = false) const;
244 :
245 : /**
246 : * Create a path in expression from multiple segments (`Clone::clone`). You
247 : * do not need to separate the segments using `::`, you can simply provide a
248 : * vector of strings to the functions which will get turned into path segments
249 : */
250 : PathInExpression path_in_expression (std::vector<std::string> &&segments,
251 : bool opening_scope = false) const;
252 :
253 : /**
254 : * Create a path in expression from a lang item.
255 : */
256 : PathInExpression path_in_expression (LangItem::Kind lang_item) const;
257 :
258 : /* Create the path to an enum's variant (`Result::Ok`) */
259 : PathInExpression variant_path (const std::string &enum_path,
260 : const std::string &variant) const;
261 :
262 : /* Create a new struct */
263 : std::unique_ptr<Stmt>
264 : struct_struct (std::string struct_name,
265 : std::vector<std::unique_ptr<GenericParam>> &&generics,
266 : std::vector<StructField> &&fields);
267 :
268 : /* Create a struct expression for unit structs (`S`) */
269 : std::unique_ptr<Expr> struct_expr_struct (std::string struct_name) const;
270 :
271 : /**
272 : * Create an expression for struct instantiation with fields (`S { a, b: c }`)
273 : * Named tuple expressions (`S(a, b, c)`) are call expressions and can thus be
274 : * constructed with `call`
275 : */
276 : std::unique_ptr<Expr>
277 : struct_expr (std::string struct_name,
278 : std::vector<std::unique_ptr<StructExprField>> &&fields) const;
279 : std::unique_ptr<Expr>
280 : struct_expr (PathInExpression struct_name,
281 : std::vector<std::unique_ptr<StructExprField>> &&fields) const;
282 :
283 : /* Create a field expression for struct instantiation (`field_name: value`) */
284 : std::unique_ptr<StructExprField>
285 : struct_expr_field (std::string field_name,
286 : std::unique_ptr<Expr> &&value) const;
287 :
288 : /* Create a field access expression (`instance.field`) */
289 : std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance,
290 : std::string field) const;
291 :
292 : std::unique_ptr<StructPatternField>
293 : struct_pattern_ident_pattern (std::string field_name,
294 : std::unique_ptr<Pattern> &&pattern);
295 :
296 : /* Create a wildcard pattern (`_`) */
297 : std::unique_ptr<Pattern> wildcard () const;
298 : /* Create a reference pattern (`&pattern`) */
299 : std::unique_ptr<Pattern> ref_pattern (std::unique_ptr<Pattern> &&inner) const;
300 :
301 : /* Create a lang item path usable as a general path */
302 : std::unique_ptr<Path> lang_item_path (LangItem::Kind) const;
303 :
304 : /* Create match expressions and their components */
305 : std::unique_ptr<Expr> match (std::unique_ptr<Expr> &&scrutinee,
306 : std::vector<MatchCase> &&cases);
307 : MatchArm match_arm (std::unique_ptr<Pattern> &&pattern);
308 : MatchCase match_case (std::unique_ptr<Pattern> &&pattern,
309 : std::unique_ptr<Expr> &&expr);
310 : MatchCase match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr);
311 :
312 : /* Create a loop expression */
313 : std::unique_ptr<Expr> loop (std::vector<std::unique_ptr<Stmt>> &&stmts);
314 :
315 : std::unique_ptr<TypeParamBound> trait_bound (TypePath bound);
316 : std::unique_ptr<Item>
317 : trait_impl (TypePath trait_path, std::unique_ptr<Type> target,
318 : std::vector<std::unique_ptr<AssociatedItem>> trait_items = {},
319 : std::vector<std::unique_ptr<GenericParam>> generics = {},
320 : WhereClause where_clause = WhereClause::create_empty (),
321 : Visibility visibility = Visibility::create_private ()) const;
322 :
323 : std::unique_ptr<GenericParam>
324 : generic_type_param (std::string type_representation,
325 : std::vector<std::unique_ptr<TypeParamBound>> &&bounds,
326 : std::unique_ptr<Type> &&type = nullptr);
327 :
328 : /**
329 : * Create a let statement with the discriminant value of a given enum
330 : * instance. This helper exists since it is a common operation in a lot of the
331 : * derive implementations, and it sucks to repeat all the steps every time.
332 : */
333 : std::unique_ptr<Stmt> discriminant_value (std::string binding_name,
334 16 : std::string instance = "self");
335 :
336 : static std::unique_ptr<GenericParam>
337 : new_lifetime_param (LifetimeParam ¶m);
338 :
339 : std::unique_ptr<GenericParam>
340 : new_const_param (ConstGenericParam ¶m) const;
341 :
342 : static std::unique_ptr<GenericParam> new_type_param (
343 : TypeParam ¶m,
344 : std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {});
345 :
346 : static Lifetime new_lifetime (const Lifetime &lifetime);
347 :
348 : static GenericArgs new_generic_args (GenericArgs &args);
349 :
350 : /* Location of the generated AST nodes */
351 : location_t loc;
352 :
353 : /* The source in which we are creating AST nodes */
354 : Builder::Source item_source;
355 :
356 672611 : static Builder::Source get_item_source (const AST::Crate &crate)
357 : {
358 23213835 : for (const auto &attr : crate.inner_attrs)
359 23213835 : if (attr.as_string () == "no_core")
360 672611 : return Source::InCore;
361 :
362 : return Source::Any;
363 : }
364 :
365 2839 : const char *get_path_start () const
366 : {
367 2839 : switch (item_source)
368 : {
369 : case Builder::Source::InCore:
370 : return "crate";
371 0 : case Builder::Source::Any:
372 0 : return "core";
373 0 : default:
374 0 : rust_unreachable ();
375 : }
376 : }
377 : };
378 :
379 : } // namespace AST
380 : } // namespace Rust
381 :
382 : #endif // AST_BUILDER_H
|