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 <initializer_list>
28 :
29 : namespace Rust {
30 : namespace AST {
31 :
32 : template <typename T>
33 : std::vector<std::unique_ptr<T>>
34 581 : vec (std::unique_ptr<T> &&t)
35 : {
36 534 : auto v = std::vector<std::unique_ptr<T>> ();
37 :
38 581 : v.emplace_back (std::move (t));
39 :
40 : return v;
41 : }
42 :
43 : template <typename T>
44 : std::vector<std::unique_ptr<T>>
45 721 : vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2)
46 : {
47 721 : auto v = std::vector<std::unique_ptr<T>> ();
48 :
49 721 : v.emplace_back (std::move (t1));
50 721 : v.emplace_back (std::move (t2));
51 :
52 721 : 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 329 : 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 : std::unique_ptr<Expr>
173 : qualified_call (std::vector<std::string> &&segments,
174 : std::vector<std::unique_ptr<Expr>> &&args) const;
175 :
176 : /* Self parameter for a function definition (`&self`) */
177 : std::unique_ptr<Param> self_ref_param (bool mutability = false) const;
178 : /* A regular named function parameter for a definition (`a: type`) */
179 : std::unique_ptr<Param> function_param (std::unique_ptr<Pattern> &&pattern,
180 : std::unique_ptr<Type> &&type) const;
181 :
182 : /* Empty function qualifiers, with no specific qualifiers */
183 : FunctionQualifiers fn_qualifiers () const;
184 :
185 : std::unique_ptr<Function>
186 : function (std::string function_name,
187 : std::vector<std::unique_ptr<Param>> params,
188 : std::unique_ptr<Type> return_type, std::unique_ptr<BlockExpr> block,
189 : std::vector<std::unique_ptr<GenericParam>> generic_params = {},
190 : FunctionQualifiers qualifiers
191 : = FunctionQualifiers (UNKNOWN_LOCATION, Async::No, Const::No,
192 : Unsafety::Normal),
193 : WhereClause where_clause = WhereClause::create_empty (),
194 : Visibility visibility = Visibility::create_private ()) const;
195 :
196 : /* Create a single path segment from one string */
197 : PathExprSegment path_segment (std::string seg) const;
198 :
199 : /* And similarly for type path segments */
200 : std::unique_ptr<TypePathSegment> type_path_segment (std::string seg) const;
201 : std::unique_ptr<TypePathSegment>
202 : type_path_segment (LangItem::Kind lang_item) const;
203 :
204 : std::unique_ptr<TypePathSegment>
205 : type_path_segment_generic (std::string seg, GenericArgs args) const;
206 : std::unique_ptr<TypePathSegment>
207 : type_path_segment_generic (LangItem::Kind lang_item, GenericArgs args) const;
208 :
209 : /* Create a Type from a single string - the most basic kind of type in our AST
210 : */
211 : std::unique_ptr<Type> single_type_path (std::string type) const;
212 : std::unique_ptr<Type> single_type_path (LangItem::Kind lang_item) const;
213 :
214 : std::unique_ptr<Type> single_generic_type_path (std::string type,
215 : GenericArgs args) const;
216 : std::unique_ptr<Type> single_generic_type_path (LangItem::Kind lang_item,
217 : GenericArgs args) const;
218 :
219 : TypePath type_path (std::vector<std::unique_ptr<TypePathSegment>> &&segment,
220 : bool opening_scope = false) const;
221 : TypePath type_path (std::vector<std::string> &&segments,
222 : bool opening_scope = false) const;
223 : TypePath type_path (std::unique_ptr<TypePathSegment> &&segment) const;
224 : TypePath type_path (std::string type) const;
225 : TypePath type_path (LangItem::Kind lang_item) const;
226 :
227 : std::unique_ptr<Type>
228 : reference_type (std::unique_ptr<TypeNoBounds> &&inner_type,
229 : bool mutability = false) const;
230 :
231 : /**
232 : * Create a path in expression from multiple segments (`Clone::clone`). You
233 : * do not need to separate the segments using `::`, you can simply provide a
234 : * vector of strings to the functions which will get turned into path segments
235 : */
236 : PathInExpression path_in_expression (std::vector<std::string> &&segments,
237 : bool opening_scope = false) const;
238 :
239 : /**
240 : * Create a path in expression from a lang item.
241 : */
242 : PathInExpression path_in_expression (LangItem::Kind lang_item) const;
243 :
244 : /* Create the path to an enum's variant (`Result::Ok`) */
245 : PathInExpression variant_path (const std::string &enum_path,
246 : const std::string &variant) const;
247 :
248 : /* Create a new struct */
249 : std::unique_ptr<Stmt>
250 : struct_struct (std::string struct_name,
251 : std::vector<std::unique_ptr<GenericParam>> &&generics,
252 : std::vector<StructField> &&fields);
253 :
254 : /* Create a struct expression for unit structs (`S`) */
255 : std::unique_ptr<Expr> struct_expr_struct (std::string struct_name) const;
256 :
257 : /**
258 : * Create an expression for struct instantiation with fields (`S { a, b: c }`)
259 : * Named tuple expressions (`S(a, b, c)`) are call expressions and can thus be
260 : * constructed with `call`
261 : */
262 : std::unique_ptr<Expr>
263 : struct_expr (std::string struct_name,
264 : std::vector<std::unique_ptr<StructExprField>> &&fields) const;
265 : std::unique_ptr<Expr>
266 : struct_expr (PathInExpression struct_name,
267 : std::vector<std::unique_ptr<StructExprField>> &&fields) const;
268 :
269 : /* Create a field expression for struct instantiation (`field_name: value`) */
270 : std::unique_ptr<StructExprField>
271 : struct_expr_field (std::string field_name,
272 : std::unique_ptr<Expr> &&value) const;
273 :
274 : /* Create a field access expression (`instance.field`) */
275 : std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance,
276 : std::string field) const;
277 :
278 : std::unique_ptr<StructPatternField>
279 : struct_pattern_ident_pattern (std::string field_name,
280 : std::unique_ptr<Pattern> &&pattern);
281 :
282 : /* Create a wildcard pattern (`_`) */
283 : std::unique_ptr<Pattern> wildcard () const;
284 : /* Create a reference pattern (`&pattern`) */
285 : std::unique_ptr<Pattern> ref_pattern (std::unique_ptr<Pattern> &&inner) const;
286 :
287 : /* Create a lang item path usable as a general path */
288 : std::unique_ptr<Path> lang_item_path (LangItem::Kind) const;
289 :
290 : /* Create match expressions and their components */
291 : std::unique_ptr<Expr> match (std::unique_ptr<Expr> &&scrutinee,
292 : std::vector<MatchCase> &&cases);
293 : MatchArm match_arm (std::unique_ptr<Pattern> &&pattern);
294 : MatchCase match_case (std::unique_ptr<Pattern> &&pattern,
295 : std::unique_ptr<Expr> &&expr);
296 : MatchCase match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr);
297 :
298 : /* Create a loop expression */
299 : std::unique_ptr<Expr> loop (std::vector<std::unique_ptr<Stmt>> &&stmts);
300 :
301 : std::unique_ptr<TypeParamBound> trait_bound (TypePath bound);
302 : std::unique_ptr<Item>
303 : trait_impl (TypePath trait_path, std::unique_ptr<Type> target,
304 : std::vector<std::unique_ptr<AssociatedItem>> trait_items = {},
305 : std::vector<std::unique_ptr<GenericParam>> generics = {},
306 : WhereClause where_clause = WhereClause::create_empty (),
307 : Visibility visibility = Visibility::create_private ()) const;
308 :
309 : std::unique_ptr<GenericParam>
310 : generic_type_param (std::string type_representation,
311 : std::vector<std::unique_ptr<TypeParamBound>> &&bounds,
312 : std::unique_ptr<Type> &&type = nullptr);
313 :
314 : /**
315 : * Create a let statement with the discriminant value of a given enum
316 : * instance. This helper exists since it is a common operation in a lot of the
317 : * derive implementations, and it sucks to repeat all the steps every time.
318 : */
319 : std::unique_ptr<Stmt> discriminant_value (std::string binding_name,
320 2 : std::string instance = "self");
321 :
322 : static std::unique_ptr<GenericParam>
323 : new_lifetime_param (LifetimeParam ¶m);
324 :
325 : std::unique_ptr<GenericParam>
326 : new_const_param (ConstGenericParam ¶m) const;
327 :
328 : static std::unique_ptr<GenericParam> new_type_param (
329 : TypeParam ¶m,
330 : std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {});
331 :
332 : static Lifetime new_lifetime (const Lifetime &lifetime);
333 :
334 : static GenericArgs new_generic_args (GenericArgs &args);
335 :
336 : /* Location of the generated AST nodes */
337 : location_t loc;
338 :
339 : private:
340 : /* Some constexpr helpers for some of the builders */
341 : static constexpr std::initializer_list<const char *> discriminant_value_path
342 : = {"core", "intrinsics", "discriminant_value"};
343 : };
344 :
345 : } // namespace AST
346 : } // namespace Rust
347 :
348 : #endif // AST_BUILDER_H
|