Branch data Line data Source code
1 : : /* General AST-related method implementations for Rust frontend.
2 : : Copyright (C) 2009-2024 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "rust-system.h"
21 : : #include "rust-ast-full.h"
22 : : #include "rust-diagnostics.h"
23 : : #include "rust-ast-visitor.h"
24 : : #include "rust-macro.h"
25 : : #include "rust-session-manager.h"
26 : : #include "rust-lex.h"
27 : : #include "rust-parse.h"
28 : : #include "rust-operators.h"
29 : :
30 : : namespace Rust {
31 : : namespace AST {
32 : :
33 : : std::string
34 : 553 : GenericArgs::as_string () const
35 : : {
36 : 553 : std::string args;
37 : :
38 : : // lifetime args
39 : 553 : if (!lifetime_args.empty ())
40 : : {
41 : : auto i = lifetime_args.begin ();
42 : : auto e = lifetime_args.end ();
43 : :
44 : 8 : for (; i != e; i++)
45 : : {
46 : 4 : args += (*i).as_string ();
47 : 4 : if (e != i + 1)
48 : 0 : args += ", ";
49 : : }
50 : : }
51 : :
52 : : // type args
53 : 553 : if (!generic_args.empty ())
54 : : {
55 : : auto i = generic_args.begin ();
56 : : auto e = generic_args.end ();
57 : :
58 : 1182 : for (; i != e; i++)
59 : : {
60 : 632 : args += (*i).as_string ();
61 : 632 : if (e != i + 1)
62 : 82 : args += ", ";
63 : : }
64 : : }
65 : :
66 : : // binding args
67 : 553 : if (!binding_args.empty ())
68 : : {
69 : : auto i = binding_args.begin ();
70 : : auto e = binding_args.end ();
71 : :
72 : 0 : for (; i != e; i++)
73 : : {
74 : 0 : args += (*i).as_string ();
75 : 0 : if (e != i + 1)
76 : 0 : args += ", ";
77 : : }
78 : : }
79 : :
80 : 553 : return args;
81 : : }
82 : :
83 : : GenericArg
84 : 4 : GenericArg::disambiguate_to_const () const
85 : : {
86 : 4 : rust_assert (get_kind () == Kind::Either);
87 : :
88 : : // FIXME: is it fine to have no outer attributes?
89 : 4 : return GenericArg::create_const (
90 : 4 : std::unique_ptr<Expr> (new IdentifierExpr (path, {}, locus)));
91 : : }
92 : :
93 : : GenericArg
94 : 1428 : GenericArg::disambiguate_to_type () const
95 : : {
96 : 1428 : rust_assert (get_kind () == Kind::Either);
97 : :
98 : 1428 : auto segment = std::unique_ptr<TypePathSegment> (
99 : 1428 : new TypePathSegment (path.as_string (), false, locus));
100 : 1428 : auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
101 : 1428 : segments.emplace_back (std::move (segment));
102 : :
103 : 1428 : return GenericArg::create_type (
104 : 1428 : std::unique_ptr<Type> (new TypePath (std::move (segments), locus)));
105 : 1428 : }
106 : :
107 : : std::string
108 : 0 : GenericArgsBinding::as_string () const
109 : : {
110 : : // TODO: rewrite to work with non-literalisable types
111 : 0 : return identifier.as_string () + " = " + type->as_string ();
112 : : }
113 : :
114 : : std::string
115 : 0 : ConstGenericParam::as_string () const
116 : : {
117 : 0 : std::string str ("ConstGenericParam: ");
118 : 0 : str += "const " + name.as_string () + ": " + type->as_string ();
119 : :
120 : 0 : if (has_default_value ())
121 : 0 : str += " = " + get_default_value ().as_string ();
122 : :
123 : 0 : return str;
124 : : }
125 : :
126 : : std::string
127 : 4281 : PathExprSegment::as_string () const
128 : : {
129 : : // TODO: rewrite dump to work with non-literalisable types
130 : 4281 : std::string ident_str = segment_name.as_string ();
131 : 4281 : if (has_generic_args ())
132 : 0 : ident_str += "::<" + generic_args.as_string () + ">";
133 : :
134 : 4281 : return ident_str;
135 : : }
136 : :
137 : : std::string
138 : 0 : PathPattern::as_string () const
139 : : {
140 : 0 : std::string str;
141 : :
142 : 0 : for (const auto &segment : segments)
143 : 0 : str += segment.as_string () + "::";
144 : :
145 : : // basically a hack - remove last two characters of string (remove final ::)
146 : 0 : str.erase (str.length () - 2);
147 : :
148 : 0 : return str;
149 : : }
150 : :
151 : : SimplePath
152 : 2116 : PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const
153 : : {
154 : 2116 : if (!has_segments ())
155 : 0 : return SimplePath::create_empty ();
156 : :
157 : : // create vector of reserved size (to minimise reallocations)
158 : 2116 : std::vector<SimplePathSegment> simple_segments;
159 : 2116 : simple_segments.reserve (segments.size ());
160 : :
161 : 4255 : for (const auto &segment : segments)
162 : : {
163 : : // return empty path if doesn't meet simple path segment requirements
164 : 6417 : if (segment.is_error () || segment.has_generic_args ()
165 : 4278 : || segment.as_string () == "Self")
166 : 0 : return SimplePath::create_empty ();
167 : :
168 : : // create segment and add to vector
169 : 2139 : std::string segment_str = segment.as_string ();
170 : 4278 : simple_segments.push_back (
171 : 4278 : SimplePathSegment (std::move (segment_str), segment.get_locus ()));
172 : 2139 : }
173 : :
174 : : // kind of a HACK to get locus depending on opening scope resolution
175 : 2116 : location_t locus = UNKNOWN_LOCATION;
176 : 2116 : if (with_opening_scope_resolution)
177 : 0 : locus = simple_segments[0].get_locus () - 2; // minus 2 chars for ::
178 : : else
179 : 2116 : locus = simple_segments[0].get_locus ();
180 : : // FIXME: this hack probably doesn't actually work
181 : :
182 : 2116 : return SimplePath (std::move (simple_segments), with_opening_scope_resolution,
183 : 2116 : locus);
184 : 2116 : }
185 : :
186 : : void
187 : 102246 : PathInExpression::accept_vis (ASTVisitor &vis)
188 : : {
189 : 102246 : vis.visit (*this);
190 : 102246 : }
191 : :
192 : : std::string
193 : 0 : PathInExpression::as_string () const
194 : : {
195 : 0 : std::string str;
196 : :
197 : 0 : if (has_opening_scope_resolution)
198 : 0 : str = "::";
199 : :
200 : 0 : return str + PathPattern::as_string ();
201 : 0 : }
202 : :
203 : : std::string
204 : 553 : TypePathSegmentGeneric::as_string () const
205 : : {
206 : : // TODO: rewrite to work with non-linearisable types
207 : 1659 : return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">";
208 : : }
209 : :
210 : : std::string
211 : 0 : TypePathSegmentFunction::as_string () const
212 : : {
213 : : // TODO: rewrite to work with non-linearisable types
214 : 0 : return TypePathSegment::as_string () + function_path.as_string ();
215 : : }
216 : :
217 : : std::string
218 : 70351 : TypePath::as_string () const
219 : : {
220 : : /* TODO: this may need to be rewritten if a segment (e.g. function) can't be
221 : : * literalised */
222 : 70351 : std::string str;
223 : :
224 : 70351 : if (has_opening_scope_resolution)
225 : 6 : str = "::";
226 : :
227 : 140739 : for (const auto &segment : segments)
228 : 140776 : str += segment->as_string () + "::";
229 : :
230 : : // kinda hack - remove last 2 '::' characters
231 : 70351 : str.erase (str.length () - 2);
232 : :
233 : 70351 : return str;
234 : : }
235 : :
236 : : SimplePath
237 : 20 : TypePath::as_simple_path () const
238 : : {
239 : 20 : if (segments.empty ())
240 : 0 : return SimplePath::create_empty ();
241 : :
242 : : // create vector of reserved size (to minimise reallocations)
243 : 20 : std::vector<SimplePathSegment> simple_segments;
244 : 20 : simple_segments.reserve (segments.size ());
245 : :
246 : 40 : for (const auto &segment : segments)
247 : : {
248 : : // return empty path if doesn't meet simple path segment requirements
249 : 20 : if (segment == nullptr || segment->is_error ()
250 : 40 : || !segment->is_ident_only () || segment->as_string () == "Self")
251 : 0 : return SimplePath::create_empty ();
252 : :
253 : : // create segment and add to vector
254 : 20 : std::string segment_str = segment->as_string ();
255 : 40 : simple_segments.push_back (
256 : 40 : SimplePathSegment (std::move (segment_str), segment->get_locus ()));
257 : 20 : }
258 : :
259 : 20 : return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
260 : 20 : locus);
261 : 20 : }
262 : :
263 : : // hopefully definition here will prevent circular dependency issue
264 : : TraitBound *
265 : 0 : TypePath::to_trait_bound (bool in_parens) const
266 : : {
267 : 0 : return new TraitBound (TypePath (*this), get_locus (), in_parens);
268 : : }
269 : :
270 : : std::string
271 : 0 : TypePathFunction::as_string () const
272 : : {
273 : : // TODO: rewrite to work with non-linearisable types
274 : 0 : std::string str ("(");
275 : :
276 : 0 : if (has_inputs ())
277 : : {
278 : : auto i = inputs.begin ();
279 : : auto e = inputs.end ();
280 : :
281 : 0 : for (; i != e; i++)
282 : : {
283 : 0 : str += (*i)->as_string ();
284 : 0 : if (e != i + 1)
285 : 0 : str += ", ";
286 : : }
287 : : }
288 : :
289 : 0 : str += ")";
290 : :
291 : 0 : if (has_return_type ())
292 : 0 : str += " -> " + return_type->as_string ();
293 : :
294 : 0 : return str;
295 : : }
296 : :
297 : : std::string
298 : 0 : QualifiedPathInExpression::as_string () const
299 : : {
300 : 0 : return path_type.as_string () + "::" + PathPattern::as_string ();
301 : : }
302 : :
303 : : std::string
304 : 0 : QualifiedPathInType::as_string () const
305 : : {
306 : : /* TODO: this may need adjusting if segments (e.g. with functions) can't be
307 : : * literalised */
308 : 0 : std::string str = path_type.as_string ();
309 : :
310 : 0 : str += "::" + associated_segment->as_string ();
311 : 0 : for (const auto &segment : segments)
312 : 0 : str += "::" + segment->as_string ();
313 : :
314 : 0 : return str;
315 : : }
316 : :
317 : : void
318 : 158 : ConstGenericParam::accept_vis (ASTVisitor &vis)
319 : : {
320 : 158 : vis.visit (*this);
321 : 158 : }
322 : :
323 : : void
324 : 193328 : TypePathSegment::accept_vis (ASTVisitor &vis)
325 : : {
326 : 193328 : vis.visit (*this);
327 : 193328 : }
328 : :
329 : : void
330 : 8841 : TypePathSegmentGeneric::accept_vis (ASTVisitor &vis)
331 : : {
332 : 8841 : vis.visit (*this);
333 : 8841 : }
334 : :
335 : : void
336 : 79 : TypePathSegmentFunction::accept_vis (ASTVisitor &vis)
337 : : {
338 : 79 : vis.visit (*this);
339 : 79 : }
340 : :
341 : : void
342 : 257108 : TypePath::accept_vis (ASTVisitor &vis)
343 : : {
344 : 257108 : vis.visit (*this);
345 : 257108 : }
346 : :
347 : : void
348 : 670 : QualifiedPathInExpression::accept_vis (ASTVisitor &vis)
349 : : {
350 : 670 : vis.visit (*this);
351 : 670 : }
352 : :
353 : : void
354 : 1698 : QualifiedPathInType::accept_vis (ASTVisitor &vis)
355 : : {
356 : 1698 : vis.visit (*this);
357 : 1698 : }
358 : :
359 : : } // namespace AST
360 : : } // namespace Rust
|