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