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 RUST_AST_BASE_H
20 : : #define RUST_AST_BASE_H
21 : : // Base for AST used in gccrs, basically required by all specific ast things
22 : :
23 : : #include "rust-system.h"
24 : : #include "rust-hir-map.h"
25 : : #include "rust-token.h"
26 : : #include "rust-location.h"
27 : : #include "rust-diagnostics.h"
28 : : #include "rust-keyword-values.h"
29 : :
30 : : namespace Rust {
31 : : // TODO: remove typedefs and make actual types for these
32 : : typedef int TupleIndex;
33 : : struct Session;
34 : : struct MacroExpander;
35 : :
36 : 3600570 : class Identifier
37 : : {
38 : : public:
39 : : // Create dummy identifier
40 : 980 : Identifier () : ident (""), loc (UNDEF_LOCATION) {}
41 : : // Create identifier with dummy location
42 : 284781 : Identifier (std::string ident, location_t loc = UNDEF_LOCATION)
43 : 568501 : : ident (ident), loc (loc)
44 : : {}
45 : : // Create identifier from token
46 : 41648 : Identifier (const_TokenPtr token)
47 : 41648 : : ident (token->get_str ()), loc (token->get_locus ())
48 : 41648 : {}
49 : :
50 : 3915159 : Identifier (const Identifier &) = default;
51 : 1070568 : Identifier (Identifier &&) = default;
52 : 0 : Identifier &operator= (const Identifier &) = default;
53 : 3239 : Identifier &operator= (Identifier &&) = default;
54 : :
55 : 1128 : location_t get_locus () const { return loc; }
56 : 1819833 : const std::string &as_string () const { return ident; }
57 : :
58 : 195256 : bool empty () const { return ident.empty (); }
59 : :
60 : : bool operator== (const Identifier &other) const
61 : : {
62 : : return ident == other.ident;
63 : : }
64 : :
65 : 0 : operator const std::string & () const { return ident; }
66 : :
67 : : private:
68 : : std::string ident;
69 : : location_t loc;
70 : : };
71 : :
72 : : std::ostream &operator<< (std::ostream &os, Identifier const &i);
73 : :
74 : : namespace AST {
75 : : // foward decl: ast visitor
76 : : class ASTVisitor;
77 : : using AttrVec = std::vector<Attribute>;
78 : :
79 : 220577 : class Visitable
80 : : {
81 : : public:
82 : 131019 : virtual ~Visitable () = default;
83 : : virtual void accept_vis (ASTVisitor &vis) = 0;
84 : : };
85 : :
86 : : /**
87 : : * Base function for reconstructing and asserting that the new NodeId is
88 : : * different from the old NodeId. It then wraps the given pointer into a unique
89 : : * pointer and returns it.
90 : : */
91 : : template <typename T>
92 : : std::unique_ptr<T>
93 : 93 : reconstruct_base (const T *instance)
94 : : {
95 : 93 : auto *reconstructed = instance->reconstruct_impl ();
96 : :
97 : 0 : rust_assert (reconstructed->get_node_id () != instance->get_node_id ());
98 : :
99 : 93 : return std::unique_ptr<T> (reconstructed);
100 : : }
101 : :
102 : : /**
103 : : * Reconstruct multiple items in a vector
104 : : */
105 : : template <typename T>
106 : : std::vector<std::unique_ptr<T>>
107 : 93 : reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct)
108 : : {
109 : 93 : std::vector<std::unique_ptr<T>> reconstructed;
110 : 93 : reconstructed.reserve (to_reconstruct.size ());
111 : :
112 : 186 : for (const auto &elt : to_reconstruct)
113 : 93 : reconstructed.emplace_back (std::unique_ptr<T> (elt->reconstruct_impl ()));
114 : :
115 : 93 : return reconstructed;
116 : : }
117 : :
118 : : // Delimiter types - used in macros and whatever.
119 : : enum DelimType
120 : : {
121 : : PARENS,
122 : : SQUARE,
123 : : CURLY
124 : : };
125 : :
126 : : // forward decl for use in token tree method
127 : : class Token;
128 : :
129 : : // A tree of tokens (or a single token) - abstract base class
130 : 161713 : class TokenTree : public Visitable
131 : : {
132 : : public:
133 : 25084 : virtual ~TokenTree () {}
134 : :
135 : : // Unique pointer custom clone function
136 : 211893 : std::unique_ptr<TokenTree> clone_token_tree () const
137 : : {
138 : 211893 : return std::unique_ptr<TokenTree> (clone_token_tree_impl ());
139 : : }
140 : :
141 : : virtual std::string as_string () const = 0;
142 : :
143 : : /* Converts token tree to a flat token stream. Tokens must be pointer to
144 : : * avoid mutual dependency with Token. */
145 : : virtual std::vector<std::unique_ptr<Token>> to_token_stream () const = 0;
146 : :
147 : : protected:
148 : : // pure virtual clone implementation
149 : : virtual TokenTree *clone_token_tree_impl () const = 0;
150 : : };
151 : :
152 : : // Abstract base class for a macro match
153 : 6834 : class MacroMatch : public Visitable
154 : : {
155 : : public:
156 : : enum MacroMatchType
157 : : {
158 : : Fragment,
159 : : Repetition,
160 : : Matcher,
161 : : Tok
162 : : };
163 : :
164 : 1182 : virtual ~MacroMatch () {}
165 : :
166 : : virtual std::string as_string () const = 0;
167 : : virtual location_t get_match_locus () const = 0;
168 : :
169 : : // Unique pointer custom clone function
170 : 2101 : std::unique_ptr<MacroMatch> clone_macro_match () const
171 : : {
172 : 2101 : return std::unique_ptr<MacroMatch> (clone_macro_match_impl ());
173 : : }
174 : :
175 : : virtual MacroMatchType get_macro_match_type () const = 0;
176 : :
177 : : protected:
178 : : // pure virtual clone implementation
179 : : virtual MacroMatch *clone_macro_match_impl () const = 0;
180 : : };
181 : :
182 : : // A token is a kind of token tree (except delimiter tokens)
183 : : class Token : public TokenTree, public MacroMatch
184 : : {
185 : : // A token is a kind of token tree (except delimiter tokens)
186 : : // A token is a kind of MacroMatch (except $ and delimiter tokens)
187 : : #if 0
188 : : // TODO: improve member variables - current ones are the same as lexer token
189 : : // Token kind.
190 : : TokenId token_id;
191 : : // Token location.
192 : : location_t locus;
193 : : // Associated text (if any) of token.
194 : : std::string str;
195 : : // Token type hint (if any).
196 : : PrimitiveCoreType type_hint;
197 : : #endif
198 : :
199 : : const_TokenPtr tok_ref;
200 : :
201 : : /* new idea: wrapper around const_TokenPtr used for heterogeneuous storage
202 : : * in token trees. rather than convert back and forth when parsing macros,
203 : : * just wrap it. */
204 : :
205 : : public:
206 : : // Unique pointer custom clone function
207 : 1032489 : std::unique_ptr<Token> clone_token () const
208 : : {
209 : 1032489 : return std::unique_ptr<Token> (clone_token_impl ());
210 : : }
211 : :
212 : : #if 0
213 : : /* constructor from general text - avoid using if lexer const_TokenPtr is
214 : : * available */
215 : : Token (TokenId token_id, location_t locus, std::string str,
216 : : PrimitiveCoreType type_hint)
217 : : : token_id (token_id), locus (locus), str (std::move (str)),
218 : : type_hint (type_hint)
219 : : {}
220 : : #endif
221 : : // not doable with new implementation - will have to make a const_TokenPtr
222 : :
223 : : // Constructor from lexer const_TokenPtr
224 : : #if 0
225 : : /* TODO: find workaround for std::string being nullptr - probably have to
226 : : * introduce new method in lexer Token, or maybe make conversion method
227 : : * there */
228 : : Token (const_TokenPtr lexer_token_ptr)
229 : : : token_id (lexer_token_ptr->get_id ()),
230 : : locus (lexer_token_ptr->get_locus ()), str (""),
231 : : type_hint (lexer_token_ptr->get_type_hint ())
232 : : {
233 : : // FIXME: change to "should have str" later?
234 : : if (lexer_token_ptr->has_str ())
235 : : {
236 : : str = lexer_token_ptr->get_str ();
237 : :
238 : : // DEBUG
239 : : rust_debug ("ast token created with str '%s'", str.c_str ());
240 : : }
241 : : else
242 : : {
243 : : // FIXME: is this returning correct thing?
244 : : str = lexer_token_ptr->get_token_description ();
245 : :
246 : : // DEBUG
247 : : rust_debug ("ast token created with string '%s'", str.c_str ());
248 : : }
249 : :
250 : : // DEBUG
251 : : if (lexer_token_ptr->should_have_str () && !lexer_token_ptr->has_str ())
252 : : {
253 : : rust_debug (
254 : : "BAD: for token '%s', should have string but does not!",
255 : : lexer_token_ptr->get_token_description ());
256 : : }
257 : : }
258 : : #endif
259 : 85892 : Token (const_TokenPtr lexer_tok_ptr) : tok_ref (std::move (lexer_tok_ptr)) {}
260 : :
261 : 37616 : bool is_string_lit () const
262 : : {
263 : 37616 : switch (get_id ())
264 : : {
265 : : case STRING_LITERAL:
266 : : case BYTE_STRING_LITERAL:
267 : : case RAW_STRING_LITERAL:
268 : : return true;
269 : 36833 : default:
270 : 36833 : return false;
271 : : }
272 : : }
273 : :
274 : : std::string as_string () const override;
275 : 180 : location_t get_match_locus () const override
276 : : {
277 : 180 : return tok_ref->get_locus ();
278 : : };
279 : :
280 : : void accept_vis (ASTVisitor &vis) override;
281 : :
282 : : // Return copy of itself but in token stream form.
283 : : std::vector<std::unique_ptr<Token>> to_token_stream () const override;
284 : :
285 : 266403 : TokenId get_id () const { return tok_ref->get_id (); }
286 : 17 : bool has_str () const { return tok_ref->has_str (); }
287 : 25064 : const std::string &get_str () const { return tok_ref->get_str (); }
288 : :
289 : 1021 : location_t get_locus () const { return tok_ref->get_locus (); }
290 : :
291 : 1 : PrimitiveCoreType get_type_hint () const { return tok_ref->get_type_hint (); }
292 : :
293 : : // Get a new token pointer copy.
294 : 745773 : const_TokenPtr get_tok_ptr () const { return tok_ref; }
295 : :
296 : 4186 : MacroMatchType get_macro_match_type () const override
297 : : {
298 : 4186 : return MacroMatchType::Tok;
299 : : }
300 : :
301 : : protected:
302 : : // No virtual for now as not polymorphic but can be in future
303 : 1359201 : /*virtual*/ Token *clone_token_impl () const { return new Token (*this); }
304 : :
305 : : /* Use covariance to implement clone function as returning this object
306 : : * rather than base */
307 : 204729 : Token *clone_token_tree_impl () const final override
308 : : {
309 : 204729 : return clone_token_impl ();
310 : : }
311 : :
312 : : /* Use covariance to implement clone function as returning this object
313 : : * rather than base */
314 : 0 : Token *clone_macro_match_impl () const final override
315 : : {
316 : 0 : return clone_token_impl ();
317 : : }
318 : : };
319 : :
320 : : // A literal - value with a type. Used in LiteralExpr and LiteralPattern.
321 : 21416 : struct Literal
322 : : {
323 : : public:
324 : : enum LitType
325 : : {
326 : : CHAR,
327 : : STRING,
328 : : BYTE,
329 : : BYTE_STRING,
330 : : RAW_STRING,
331 : : INT,
332 : : FLOAT,
333 : : BOOL,
334 : : ERROR
335 : : };
336 : :
337 : : private:
338 : : /* TODO: maybe make subclasses of each type of literal with their typed
339 : : * values (or generics) */
340 : : std::string value_as_string;
341 : : LitType type;
342 : : PrimitiveCoreType type_hint;
343 : :
344 : : public:
345 : 31956 : std::string as_string () const { return value_as_string; }
346 : :
347 : 21861 : LitType get_lit_type () const { return type; }
348 : :
349 : 19469 : PrimitiveCoreType get_type_hint () const { return type_hint; }
350 : :
351 : 36834 : Literal (std::string value_as_string, LitType type,
352 : : PrimitiveCoreType type_hint)
353 : 36834 : : value_as_string (std::move (value_as_string)), type (type),
354 : 36834 : type_hint (type_hint)
355 : : {}
356 : :
357 : 0 : static Literal create_error ()
358 : : {
359 : 0 : return Literal ("", ERROR, PrimitiveCoreType::CORETYPE_UNKNOWN);
360 : : }
361 : :
362 : : // Returns whether literal is in an invalid state.
363 : 608104 : bool is_error () const { return type == ERROR; }
364 : : };
365 : :
366 : : /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
367 : : * to be defined */
368 : : class AttrInputLiteral;
369 : :
370 : : /* TODO: move applicable stuff into here or just don't include it because
371 : : * nothing uses it A segment of a path (maybe) */
372 : 56276 : class PathSegment
373 : : {
374 : : public:
375 : 14301 : virtual ~PathSegment () {}
376 : :
377 : : virtual std::string as_string () const = 0;
378 : :
379 : : // TODO: add visitor here?
380 : : };
381 : :
382 : : // A segment of a simple path without generic or type arguments
383 : 51773 : class SimplePathSegment : public PathSegment
384 : : {
385 : : std::string segment_name;
386 : : location_t locus;
387 : : NodeId node_id;
388 : :
389 : : // only allow identifiers, "super", "self", "crate", or "$crate"
390 : : public:
391 : : // TODO: put checks in constructor to enforce this rule?
392 : 27798 : SimplePathSegment (std::string segment_name, location_t locus)
393 : 55596 : : segment_name (std::move (segment_name)), locus (locus),
394 : 27798 : node_id (Analysis::Mappings::get ().get_next_node_id ())
395 : 27798 : {}
396 : :
397 : : /* Returns whether simple path segment is in an invalid state (currently, if
398 : : * empty). */
399 : 227192 : bool is_error () const { return segment_name.empty (); }
400 : :
401 : : // Creates an error SimplePathSegment
402 : 213 : static SimplePathSegment create_error ()
403 : : {
404 : 213 : return SimplePathSegment (std::string (""), UNDEF_LOCATION);
405 : : }
406 : :
407 : : std::string as_string () const override;
408 : :
409 : 18677 : location_t get_locus () const { return locus; }
410 : 19435 : NodeId get_node_id () const { return node_id; }
411 : 51257 : const std::string &get_segment_name () const { return segment_name; }
412 : 25969 : bool is_super_path_seg () const
413 : : {
414 : 25969 : return as_string ().compare (Values::Keywords::SUPER) == 0;
415 : : }
416 : 36297 : bool is_crate_path_seg () const
417 : : {
418 : 36297 : return as_string ().compare (Values::Keywords::CRATE) == 0;
419 : : }
420 : 48005 : bool is_lower_self_seg () const
421 : : {
422 : 48005 : return as_string ().compare (Values::Keywords::SELF) == 0;
423 : : }
424 : 2060 : bool is_big_self () const
425 : : {
426 : 2060 : return as_string ().compare (Values::Keywords::SELF_ALIAS) == 0;
427 : : }
428 : : };
429 : :
430 : : // A simple path without generic or type arguments
431 : 267619 : class SimplePath
432 : : {
433 : : bool opening_scope_resolution;
434 : : std::vector<SimplePathSegment> segments;
435 : : location_t locus;
436 : : NodeId node_id;
437 : :
438 : : public:
439 : : // Constructor
440 : 93702 : explicit SimplePath (std::vector<SimplePathSegment> path_segments,
441 : : bool has_opening_scope_resolution = false,
442 : : location_t locus = UNDEF_LOCATION)
443 : 93702 : : opening_scope_resolution (has_opening_scope_resolution),
444 : 93702 : segments (std::move (path_segments)), locus (locus),
445 : 93702 : node_id (Analysis::Mappings::get ().get_next_node_id ())
446 : 93702 : {}
447 : :
448 : 286 : explicit SimplePath (Identifier ident)
449 : 286 : : opening_scope_resolution (false),
450 : 858 : segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}),
451 : 286 : locus (ident.get_locus ()),
452 : 286 : node_id (Analysis::Mappings::get ().get_next_node_id ())
453 : 286 : {}
454 : :
455 : : // Creates an empty SimplePath.
456 : 67419 : static SimplePath create_empty ()
457 : : {
458 : 67419 : return SimplePath (std::vector<SimplePathSegment> ());
459 : : }
460 : :
461 : : // Returns whether the SimplePath is empty, i.e. has path segments.
462 : 23791 : bool is_empty () const { return segments.empty (); }
463 : :
464 : : const std::string as_string () const;
465 : :
466 : 11297 : bool has_opening_scope_resolution () const
467 : : {
468 : 11297 : return opening_scope_resolution;
469 : : }
470 : :
471 : 2756 : location_t get_locus () const { return locus; }
472 : 124 : NodeId get_node_id () const { return node_id; }
473 : :
474 : : // does this need visitor if not polymorphic? probably not
475 : :
476 : : // path-to-string comparison operator
477 : 161938 : bool operator== (const std::string &rhs) const
478 : : {
479 : 161938 : return !opening_scope_resolution && segments.size () == 1
480 : 323876 : && segments[0].as_string () == rhs;
481 : : }
482 : :
483 : : /* Creates a single-segment SimplePath from a string. This will not check to
484 : : * ensure that this is a valid identifier in path, so be careful. Also, this
485 : : * will have no location data.
486 : : * TODO have checks? */
487 : 4346 : static SimplePath from_str (std::string str, location_t locus)
488 : : {
489 : 4346 : std::vector<AST::SimplePathSegment> single_segments
490 : 8692 : = {AST::SimplePathSegment (std::move (str), locus)};
491 : 4346 : return SimplePath (std::move (single_segments), false, locus);
492 : 4346 : }
493 : :
494 : 11379 : const std::vector<SimplePathSegment> &get_segments () const
495 : : {
496 : 14393 : return segments;
497 : : }
498 : :
499 : 56114 : std::vector<SimplePathSegment> &get_segments () { return segments; }
500 : :
501 : 11447 : const SimplePathSegment &get_final_segment () const
502 : : {
503 : 11447 : return segments.back ();
504 : : }
505 : : };
506 : :
507 : : // path-to-string inverse comparison operator
508 : : inline bool
509 : 748 : operator!= (const SimplePath &lhs, const std::string &rhs)
510 : : {
511 : 748 : return !(lhs == rhs);
512 : : }
513 : :
514 : : // forward decl for Attribute
515 : : class AttrInput;
516 : :
517 : : // Visibility of item - if the item has it, then it is some form of public
518 : 185562 : struct Visibility
519 : : {
520 : : public:
521 : : enum VisType
522 : : {
523 : : PRIV,
524 : : PUB,
525 : : PUB_CRATE,
526 : : PUB_SELF,
527 : : PUB_SUPER,
528 : : PUB_IN_PATH
529 : : };
530 : :
531 : : private:
532 : : VisType vis_type;
533 : : // Only assigned if vis_type is IN_PATH
534 : : SimplePath in_path;
535 : : location_t locus;
536 : :
537 : : // should this store location info?
538 : :
539 : : public:
540 : : // Creates a Visibility - TODO make constructor protected or private?
541 : 61230 : Visibility (VisType vis_type, SimplePath in_path, location_t locus)
542 : 4722 : : vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
543 : : {}
544 : :
545 : 3492 : VisType get_vis_type () const { return vis_type; }
546 : :
547 : : // Returns whether visibility is in an error state.
548 : 611872 : bool is_error () const
549 : : {
550 : 36032 : return vis_type == PUB_IN_PATH && in_path.is_empty ();
551 : : }
552 : :
553 : : // Returns whether a visibility has a path
554 : 576127 : bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; }
555 : :
556 : : // Returns whether visibility is public or not.
557 : 2460 : bool is_public () const { return vis_type != PRIV && !is_error (); }
558 : :
559 : 2633 : location_t get_locus () const { return locus; }
560 : :
561 : : // empty?
562 : : // Creates an error visibility.
563 : 5231 : static Visibility create_error ()
564 : : {
565 : 5231 : return Visibility (PUB_IN_PATH, SimplePath::create_empty (),
566 : 5231 : UNDEF_LOCATION);
567 : : }
568 : :
569 : : // Unique pointer custom clone function
570 : : /*std::unique_ptr<Visibility> clone_visibility() const {
571 : : return std::unique_ptr<Visibility>(clone_visibility_impl());
572 : : }*/
573 : :
574 : : /* TODO: think of a way to only allow valid Visibility states - polymorphism
575 : : * is one idea but may be too resource-intensive. */
576 : :
577 : : // Creates a public visibility with no further features/arguments.
578 : : // empty?
579 : 8059 : static Visibility create_public (location_t pub_vis_location)
580 : : {
581 : 8059 : return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
582 : : }
583 : :
584 : : // Creates a public visibility with crate-relative paths
585 : 53 : static Visibility create_crate (location_t crate_tok_location,
586 : : location_t crate_vis_location)
587 : : {
588 : 53 : return Visibility (PUB_CRATE,
589 : 53 : SimplePath::from_str (Values::Keywords::CRATE,
590 : : crate_tok_location),
591 : 53 : crate_vis_location);
592 : : }
593 : :
594 : : // Creates a public visibility with self-relative paths
595 : 0 : static Visibility create_self (location_t self_tok_location,
596 : : location_t self_vis_location)
597 : : {
598 : 0 : return Visibility (PUB_SELF,
599 : 0 : SimplePath::from_str (Values::Keywords::SELF,
600 : : self_tok_location),
601 : 0 : self_vis_location);
602 : : }
603 : :
604 : : // Creates a public visibility with parent module-relative paths
605 : 1 : static Visibility create_super (location_t super_tok_location,
606 : : location_t super_vis_location)
607 : : {
608 : 1 : return Visibility (PUB_SUPER,
609 : 1 : SimplePath::from_str (Values::Keywords::SUPER,
610 : : super_tok_location),
611 : 1 : super_vis_location);
612 : : }
613 : :
614 : : // Creates a private visibility
615 : 47874 : static Visibility create_private ()
616 : : {
617 : 47874 : return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION);
618 : : }
619 : :
620 : : // Creates a public visibility with a given path or whatever.
621 : 12 : static Visibility create_in_path (SimplePath in_path,
622 : : location_t in_path_vis_location)
623 : : {
624 : 12 : return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
625 : : }
626 : :
627 : : std::string as_string () const;
628 : 61 : const SimplePath &get_path () const { return in_path; }
629 : 992 : SimplePath &get_path () { return in_path; }
630 : :
631 : : protected:
632 : : // Clone function implementation - not currently virtual but may be if
633 : : // polymorphism used
634 : : /*virtual*/ Visibility *clone_visibility_impl () const
635 : : {
636 : : return new Visibility (*this);
637 : : }
638 : : };
639 : :
640 : : // aka Attr
641 : : // Attribute AST representation
642 : : struct Attribute
643 : : {
644 : : private:
645 : : SimplePath path;
646 : :
647 : : // bool has_attr_input;
648 : : std::unique_ptr<AttrInput> attr_input;
649 : :
650 : : location_t locus;
651 : :
652 : : bool inner_attribute;
653 : :
654 : : // TODO: maybe a variable storing whether attr input is parsed or not
655 : :
656 : : public:
657 : : // Returns whether Attribute has AttrInput
658 : 69823 : bool has_attr_input () const { return attr_input != nullptr; }
659 : :
660 : : // Constructor has pointer AttrInput for polymorphism reasons
661 : 27153 : Attribute (SimplePath path, std::unique_ptr<AttrInput> input,
662 : : location_t locus = UNDEF_LOCATION, bool inner_attribute = false)
663 : 27153 : : path (std::move (path)), attr_input (std::move (input)), locus (locus),
664 : 27153 : inner_attribute (inner_attribute)
665 : : {}
666 : :
667 : : bool is_derive () const;
668 : :
669 : : std::vector<std::reference_wrapper<AST::SimplePath>> get_traits_to_derive ();
670 : :
671 : : // default destructor
672 : 93763 : ~Attribute () = default;
673 : :
674 : : // no point in being defined inline as requires virtual call anyway
675 : : Attribute (const Attribute &other);
676 : :
677 : : // no point in being defined inline as requires virtual call anyway
678 : : Attribute &operator= (const Attribute &other);
679 : :
680 : : // default move semantics
681 : 58744 : Attribute (Attribute &&other) = default;
682 : 5 : Attribute &operator= (Attribute &&other) = default;
683 : :
684 : : // Unique pointer custom clone function
685 : : std::unique_ptr<Attribute> clone_attribute () const
686 : : {
687 : : return std::unique_ptr<Attribute> (clone_attribute_impl ());
688 : : }
689 : :
690 : : // Creates an empty attribute (which is invalid)
691 : 5403 : static Attribute create_empty ()
692 : : {
693 : 5403 : return Attribute (SimplePath::create_empty (), nullptr);
694 : : }
695 : :
696 : : // Returns whether the attribute is considered an "empty" attribute.
697 : 20022 : bool is_empty () const { return attr_input == nullptr && path.is_empty (); }
698 : :
699 : : // Returns whether the attribute has no input
700 : 613 : bool empty_input () const { return !attr_input; }
701 : :
702 : 2704 : location_t get_locus () const { return locus; }
703 : :
704 : 27430 : AttrInput &get_attr_input () const { return *attr_input; }
705 : :
706 : : /* e.g.:
707 : : #![crate_type = "lib"]
708 : : #[test]
709 : : #[cfg(target_os = "linux")]
710 : : #[allow(non_camel_case_types)]
711 : : #![allow(unused_variables)]
712 : : */
713 : :
714 : : // Full built-in attribute list:
715 : : /* cfg
716 : : * cfg_attr
717 : : * test
718 : : * ignore
719 : : * should_panic
720 : : * derive
721 : : * macro_export
722 : : * macro_use
723 : : * proc_macro
724 : : * proc_macro_derive
725 : : * proc_macro_attribute
726 : : * allow
727 : : * warn
728 : : * deny
729 : : * forbid
730 : : * deprecated
731 : : * must_use
732 : : * link
733 : : * link_name
734 : : * no_link
735 : : * repr
736 : : * crate_type
737 : : * no_main
738 : : * export_name
739 : : * link_section
740 : : * no_mangle
741 : : * used
742 : : * crate_name
743 : : * inline
744 : : * cold
745 : : * no_builtins
746 : : * target_feature
747 : : * doc
748 : : * no_std
749 : : * no_implicit_prelude
750 : : * path
751 : : * recursion_limit
752 : : * type_length_limit
753 : : * panic_handler
754 : : * global_allocator
755 : : * windows_subsystem
756 : : * feature */
757 : :
758 : : std::string as_string () const;
759 : :
760 : 2060 : bool is_inner_attribute () const { return inner_attribute; }
761 : :
762 : : // no visitor pattern as not currently polymorphic
763 : :
764 : 111231 : const SimplePath &get_path () const { return path; }
765 : 125275 : SimplePath &get_path () { return path; }
766 : :
767 : : // Call to parse attribute body to meta item syntax.
768 : : void parse_attr_to_meta_item ();
769 : :
770 : : /* Determines whether cfg predicate is true and item with attribute should
771 : : * not be stripped. Attribute body must already be parsed to meta item. */
772 : : bool check_cfg_predicate (const Session &session) const;
773 : :
774 : : // Returns whether body has been parsed to meta item form or not.
775 : : bool is_parsed_to_meta_item () const;
776 : :
777 : : /* Returns any attributes generated from cfg_attr attributes. Attribute body
778 : : * must already be parsed to meta item. */
779 : : std::vector<Attribute> separate_cfg_attrs () const;
780 : :
781 : : protected:
782 : : // not virtual as currently no subclasses of Attribute, but could be in
783 : : // future
784 : : /*virtual*/ Attribute *clone_attribute_impl () const
785 : : {
786 : : return new Attribute (*this);
787 : : }
788 : : };
789 : :
790 : : // Attribute body - abstract base class
791 : 59057 : class AttrInput : public Visitable
792 : : {
793 : : public:
794 : : enum AttrInputType
795 : : {
796 : : LITERAL,
797 : : MACRO,
798 : : META_ITEM,
799 : : TOKEN_TREE,
800 : : };
801 : :
802 : 25084 : virtual ~AttrInput () {}
803 : :
804 : : // Unique pointer custom clone function
805 : 45852 : std::unique_ptr<AttrInput> clone_attr_input () const
806 : : {
807 : 45852 : return std::unique_ptr<AttrInput> (clone_attr_input_impl ());
808 : : }
809 : :
810 : : virtual std::string as_string () const = 0;
811 : :
812 : : virtual bool check_cfg_predicate (const Session &session) const = 0;
813 : :
814 : : // Parse attribute input to meta item, if possible
815 : 0 : virtual AttrInput *parse_to_meta_item () const { return nullptr; }
816 : :
817 : 0 : virtual std::vector<Attribute> separate_cfg_attrs () const { return {}; }
818 : :
819 : : // Returns whether attr input has been parsed to meta item syntax.
820 : : virtual bool is_meta_item () const = 0;
821 : :
822 : : virtual AttrInputType get_attr_input_type () const = 0;
823 : :
824 : : protected:
825 : : // pure virtual clone implementation
826 : : virtual AttrInput *clone_attr_input_impl () const = 0;
827 : : };
828 : :
829 : : // Forward decl - defined in rust-macro.h
830 : : class MetaNameValueStr;
831 : :
832 : : // abstract base meta item inner class
833 : 27 : class MetaItemInner : public Visitable
834 : : {
835 : : protected:
836 : : // pure virtual as MetaItemInner
837 : : virtual MetaItemInner *clone_meta_item_inner_impl () const = 0;
838 : :
839 : : public:
840 : : enum class Kind
841 : : {
842 : : LitExpr,
843 : : MetaItem,
844 : : };
845 : :
846 : : // Unique pointer custom clone function
847 : 2448 : std::unique_ptr<MetaItemInner> clone_meta_item_inner () const
848 : : {
849 : 2448 : return std::unique_ptr<MetaItemInner> (clone_meta_item_inner_impl ());
850 : : }
851 : :
852 : : virtual Kind get_kind () = 0;
853 : :
854 : : virtual ~MetaItemInner ();
855 : :
856 : : virtual location_t get_locus () const = 0;
857 : :
858 : : virtual std::string as_string () const = 0;
859 : :
860 : : /* HACK: used to simplify parsing - creates a copy of that type, or returns
861 : : * null */
862 : : virtual std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const;
863 : :
864 : : // HACK: used to simplify parsing - same thing
865 : 0 : virtual SimplePath to_path_item () const
866 : : {
867 : 0 : return SimplePath::create_empty ();
868 : : }
869 : :
870 : 0 : virtual Attribute to_attribute () const { return Attribute::create_empty (); }
871 : :
872 : : virtual bool check_cfg_predicate (const Session &session) const = 0;
873 : :
874 : 35 : virtual bool is_key_value_pair () const { return false; }
875 : : };
876 : :
877 : : // Container used to store MetaItems as AttrInput (bridge-ish kinda thing)
878 : : class AttrInputMetaItemContainer : public AttrInput
879 : : {
880 : : std::vector<std::unique_ptr<MetaItemInner>> items;
881 : :
882 : : public:
883 : 2157 : AttrInputMetaItemContainer (std::vector<std::unique_ptr<MetaItemInner>> items)
884 : 2157 : : items (std::move (items))
885 : : {}
886 : :
887 : : // copy constructor with vector clone
888 : 2299 : AttrInputMetaItemContainer (const AttrInputMetaItemContainer &other)
889 : 2299 : {
890 : 2299 : items.reserve (other.items.size ());
891 : 4718 : for (const auto &e : other.items)
892 : 2419 : items.push_back (e->clone_meta_item_inner ());
893 : 2299 : }
894 : :
895 : : // copy assignment operator with vector clone
896 : : AttrInputMetaItemContainer &
897 : : operator= (const AttrInputMetaItemContainer &other)
898 : : {
899 : : AttrInput::operator= (other);
900 : :
901 : : items.reserve (other.items.size ());
902 : : for (const auto &e : other.items)
903 : : items.push_back (e->clone_meta_item_inner ());
904 : :
905 : : return *this;
906 : : }
907 : :
908 : : // default move constructors
909 : : AttrInputMetaItemContainer (AttrInputMetaItemContainer &&other) = default;
910 : : AttrInputMetaItemContainer &operator= (AttrInputMetaItemContainer &&other)
911 : : = default;
912 : :
913 : : std::string as_string () const override;
914 : :
915 : : void accept_vis (ASTVisitor &vis) override;
916 : :
917 : : bool check_cfg_predicate (const Session &session) const override;
918 : :
919 : 255 : AttrInputType get_attr_input_type () const final override
920 : : {
921 : 255 : return AttrInput::AttrInputType::META_ITEM;
922 : : }
923 : :
924 : : // Clones this object.
925 : : std::unique_ptr<AttrInputMetaItemContainer>
926 : : clone_attr_input_meta_item_container () const
927 : : {
928 : : return std::unique_ptr<AttrInputMetaItemContainer> (
929 : : clone_attr_input_meta_item_container_impl ());
930 : : }
931 : :
932 : : std::vector<Attribute> separate_cfg_attrs () const override;
933 : :
934 : 6142 : bool is_meta_item () const override { return true; }
935 : :
936 : : // TODO: this mutable getter seems dodgy
937 : 3126 : std::vector<std::unique_ptr<MetaItemInner>> &get_items () { return items; }
938 : : const std::vector<std::unique_ptr<MetaItemInner>> &get_items () const
939 : : {
940 : : return items;
941 : : }
942 : :
943 : : protected:
944 : : // Use covariance to implement clone function as returning this type
945 : 2299 : AttrInputMetaItemContainer *clone_attr_input_impl () const final override
946 : : {
947 : 2299 : return clone_attr_input_meta_item_container_impl ();
948 : : }
949 : :
950 : 2299 : AttrInputMetaItemContainer *clone_attr_input_meta_item_container_impl () const
951 : : {
952 : 2299 : return new AttrInputMetaItemContainer (*this);
953 : : }
954 : : };
955 : :
956 : : // A token tree with delimiters
957 : 21423 : class DelimTokenTree : public TokenTree, public AttrInput
958 : : {
959 : : DelimType delim_type;
960 : : std::vector<std::unique_ptr<TokenTree>> token_trees;
961 : : location_t locus;
962 : :
963 : : protected:
964 : 19080 : DelimTokenTree *clone_delim_tok_tree_impl () const
965 : : {
966 : 19080 : return new DelimTokenTree (*this);
967 : : }
968 : :
969 : : /* Use covariance to implement clone function as returning a DelimTokenTree
970 : : * object */
971 : 0 : DelimTokenTree *clone_attr_input_impl () const final override
972 : : {
973 : 0 : return clone_delim_tok_tree_impl ();
974 : : }
975 : :
976 : : /* Use covariance to implement clone function as returning a DelimTokenTree
977 : : * object */
978 : 7164 : DelimTokenTree *clone_token_tree_impl () const final override
979 : : {
980 : 7164 : return clone_delim_tok_tree_impl ();
981 : : }
982 : :
983 : : public:
984 : 16081 : DelimTokenTree (DelimType delim_type,
985 : : std::vector<std::unique_ptr<TokenTree>> token_trees
986 : : = std::vector<std::unique_ptr<TokenTree>> (),
987 : : location_t locus = UNDEF_LOCATION)
988 : 16081 : : delim_type (delim_type), token_trees (std::move (token_trees)),
989 : 16081 : locus (locus)
990 : : {}
991 : :
992 : : // Copy constructor with vector clone
993 : 34000 : DelimTokenTree (DelimTokenTree const &other)
994 : 34000 : : delim_type (other.delim_type), locus (other.locus)
995 : : {
996 : 34000 : token_trees.clear ();
997 : 34000 : token_trees.reserve (other.token_trees.size ());
998 : 245730 : for (const auto &e : other.token_trees)
999 : 211730 : token_trees.push_back (e->clone_token_tree ());
1000 : 34000 : }
1001 : :
1002 : : // overloaded assignment operator with vector clone
1003 : 42 : DelimTokenTree &operator= (DelimTokenTree const &other)
1004 : : {
1005 : 42 : delim_type = other.delim_type;
1006 : 42 : locus = other.locus;
1007 : :
1008 : 42 : token_trees.clear ();
1009 : 42 : token_trees.reserve (other.token_trees.size ());
1010 : 205 : for (const auto &e : other.token_trees)
1011 : 163 : token_trees.push_back (e->clone_token_tree ());
1012 : :
1013 : 42 : return *this;
1014 : : }
1015 : :
1016 : : // move constructors
1017 : 4066 : DelimTokenTree (DelimTokenTree &&other) = default;
1018 : : DelimTokenTree &operator= (DelimTokenTree &&other) = default;
1019 : :
1020 : 20 : static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); }
1021 : :
1022 : : std::string as_string () const override;
1023 : :
1024 : : void accept_vis (ASTVisitor &vis) override;
1025 : :
1026 : 0 : bool check_cfg_predicate (const Session &) const override
1027 : : {
1028 : : // this should never be called - should be converted first
1029 : 0 : rust_assert (false);
1030 : : return false;
1031 : : }
1032 : :
1033 : : AttrInputMetaItemContainer *parse_to_meta_item () const override;
1034 : :
1035 : : std::vector<std::unique_ptr<Token>> to_token_stream () const override;
1036 : :
1037 : : std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const
1038 : : {
1039 : : return std::unique_ptr<DelimTokenTree> (clone_delim_tok_tree_impl ());
1040 : : }
1041 : :
1042 : 1131 : bool is_meta_item () const override { return false; }
1043 : :
1044 : 2318 : AttrInputType get_attr_input_type () const final override
1045 : : {
1046 : 2318 : return AttrInput::AttrInputType::TOKEN_TREE;
1047 : : }
1048 : :
1049 : : std::vector<std::unique_ptr<TokenTree>> &get_token_trees ()
1050 : : {
1051 : 62386 : return token_trees;
1052 : : }
1053 : :
1054 : : const std::vector<std::unique_ptr<TokenTree>> &get_token_trees () const
1055 : : {
1056 : 0 : return token_trees;
1057 : : }
1058 : :
1059 : 7679 : DelimType get_delim_type () const { return delim_type; }
1060 : 2398 : location_t get_locus () const { return locus; }
1061 : : };
1062 : :
1063 : : /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
1064 : : * to be defined */
1065 : : class AttrInputLiteral;
1066 : :
1067 : : // abstract base meta item class
1068 : 2723 : class MetaItem : public MetaItemInner
1069 : : {
1070 : : public:
1071 : : enum class ItemKind
1072 : : {
1073 : : Path,
1074 : : Word,
1075 : : NameValueStr,
1076 : : PathExpr,
1077 : : Seq,
1078 : : ListPaths,
1079 : : ListNameValueStr,
1080 : : };
1081 : :
1082 : 481 : MetaItemInner::Kind get_kind () override
1083 : : {
1084 : 481 : return MetaItemInner::Kind::MetaItem;
1085 : : }
1086 : :
1087 : : virtual ItemKind get_item_kind () const = 0;
1088 : : };
1089 : :
1090 : : // Forward decl - defined in rust-expr.h
1091 : : class MetaItemLitExpr;
1092 : :
1093 : : // Forward decl - defined in rust-expr.h
1094 : : class MetaItemPathExpr;
1095 : :
1096 : : // Forward decl - defined in rust-macro.h
1097 : : class MetaItemPath;
1098 : :
1099 : : // Forward decl - defined in rust-macro.h
1100 : : class MetaItemSeq;
1101 : :
1102 : : // Forward decl - defined in rust-macro.h
1103 : : class MetaWord;
1104 : :
1105 : : // Forward decl - defined in rust-macro.h
1106 : : class MetaListPaths;
1107 : :
1108 : : // Forward decl - defined in rust-macro.h
1109 : : class MetaListNameValueStr;
1110 : :
1111 : : /* Base statement abstract class. Note that most "statements" are not allowed
1112 : : * in top-level module scope - only a subclass of statements called "items"
1113 : : * are. */
1114 : 1055 : class Stmt : public Visitable
1115 : : {
1116 : : public:
1117 : : enum class Kind
1118 : : {
1119 : : Empty,
1120 : : Item,
1121 : : Let,
1122 : : Expr,
1123 : : MacroInvocation,
1124 : : };
1125 : :
1126 : : // Unique pointer custom clone function
1127 : 9835 : std::unique_ptr<Stmt> clone_stmt () const
1128 : : {
1129 : 9835 : return std::unique_ptr<Stmt> (clone_stmt_impl ());
1130 : : }
1131 : :
1132 : : virtual ~Stmt () {}
1133 : :
1134 : : virtual std::string as_string () const = 0;
1135 : :
1136 : : virtual location_t get_locus () const = 0;
1137 : :
1138 : : virtual void mark_for_strip () = 0;
1139 : : virtual bool is_marked_for_strip () const = 0;
1140 : 407657 : NodeId get_node_id () const { return node_id; }
1141 : :
1142 : : virtual Kind get_stmt_kind () = 0;
1143 : :
1144 : : // TODO: Can we remove these two?
1145 : : virtual bool is_item () const = 0;
1146 : 4002 : virtual bool is_expr () const { return false; }
1147 : :
1148 : 37 : virtual void add_semicolon () {}
1149 : :
1150 : : protected:
1151 : 114219 : Stmt () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1152 : :
1153 : : // Clone function implementation as pure virtual method
1154 : : virtual Stmt *clone_stmt_impl () const = 0;
1155 : :
1156 : : NodeId node_id;
1157 : : };
1158 : :
1159 : : // Rust "item" AST node (declaration of top-level/module-level allowed stuff)
1160 : 18373 : class Item : public Stmt
1161 : : {
1162 : : public:
1163 : : enum class Kind
1164 : : {
1165 : : MacroRulesDefinition,
1166 : : MacroInvocation,
1167 : : Module,
1168 : : ExternCrate,
1169 : : UseDeclaration,
1170 : : Function,
1171 : : TypeAlias,
1172 : : Struct,
1173 : : EnumItem,
1174 : : Enum,
1175 : : Union,
1176 : : ConstantItem,
1177 : : StaticItem,
1178 : : Trait,
1179 : : Impl,
1180 : : ExternBlock,
1181 : : };
1182 : :
1183 : : virtual Kind get_item_kind () const = 0;
1184 : :
1185 : : // Unique pointer custom clone function
1186 : 10829 : std::unique_ptr<Item> clone_item () const
1187 : : {
1188 : 10829 : return std::unique_ptr<Item> (clone_item_impl ());
1189 : : }
1190 : :
1191 : : /* Adds crate names to the vector passed by reference, if it can
1192 : : * (polymorphism). TODO: remove, unused. */
1193 : : virtual void
1194 : 0 : add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
1195 : 0 : {}
1196 : :
1197 : 3051 : Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Item; }
1198 : :
1199 : : // FIXME: ARTHUR: Is it okay to have removed that final? Is it *required*
1200 : : // behavior that we have items that can also be expressions?
1201 : 0 : bool is_item () const override { return true; }
1202 : :
1203 : : virtual std::vector<Attribute> &get_outer_attrs () = 0;
1204 : : virtual const std::vector<Attribute> &get_outer_attrs () const = 0;
1205 : :
1206 : 57221 : virtual bool has_outer_attrs () const { return !get_outer_attrs ().empty (); }
1207 : :
1208 : : protected:
1209 : : // Clone function implementation as pure virtual method
1210 : : virtual Item *clone_item_impl () const = 0;
1211 : :
1212 : : /* Save having to specify two clone methods in derived classes by making
1213 : : * statement clone return item clone. Hopefully won't affect performance too
1214 : : * much. */
1215 : 425 : Item *clone_stmt_impl () const final override { return clone_item_impl (); }
1216 : : };
1217 : :
1218 : : // Item that supports visibility - abstract base class
1219 : : class VisItem : public Item
1220 : : {
1221 : : Visibility visibility;
1222 : : std::vector<Attribute> outer_attrs;
1223 : :
1224 : : protected:
1225 : : // Visibility constructor
1226 : 42999 : VisItem (Visibility visibility,
1227 : : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1228 : 42999 : : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs))
1229 : 42999 : {}
1230 : :
1231 : : // Visibility copy constructor
1232 : 26324 : VisItem (VisItem const &other)
1233 : 26324 : : visibility (other.visibility), outer_attrs (other.outer_attrs)
1234 : 26324 : {}
1235 : :
1236 : : // Overload assignment operator to clone
1237 : 0 : VisItem &operator= (VisItem const &other)
1238 : : {
1239 : 0 : visibility = other.visibility;
1240 : 0 : outer_attrs = other.outer_attrs;
1241 : :
1242 : 0 : return *this;
1243 : : }
1244 : :
1245 : : // move constructors
1246 : 943 : VisItem (VisItem &&other) = default;
1247 : : VisItem &operator= (VisItem &&other) = default;
1248 : :
1249 : : public:
1250 : : /* Does the item have some kind of public visibility (non-default
1251 : : * visibility)? */
1252 : 1239 : bool has_visibility () const { return visibility.is_public (); }
1253 : :
1254 : : std::string as_string () const override;
1255 : :
1256 : : // TODO: this mutable getter seems really dodgy. Think up better way.
1257 : 552624 : Visibility &get_visibility () { return visibility; }
1258 : : const Visibility &get_visibility () const { return visibility; }
1259 : :
1260 : 889228 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1261 : 73503 : const std::vector<Attribute> &get_outer_attrs () const override
1262 : : {
1263 : 73503 : return outer_attrs;
1264 : : }
1265 : :
1266 : : virtual Item::Kind get_item_kind () const override = 0;
1267 : : };
1268 : :
1269 : : // forward decl of ExprWithoutBlock
1270 : : class ExprWithoutBlock;
1271 : :
1272 : : // Base expression AST node - abstract
1273 : 25303 : class Expr : public Visitable
1274 : : {
1275 : : public:
1276 : : enum class Kind
1277 : : {
1278 : : PathInExpression,
1279 : : QualifiedPathInExpression,
1280 : : Literal,
1281 : : Operator,
1282 : : Grouped,
1283 : : Array,
1284 : : ArrayIndex,
1285 : : Tuple,
1286 : : TupleIndex,
1287 : : Struct,
1288 : : Call,
1289 : : MethodCall,
1290 : : FieldAccess,
1291 : : Closure,
1292 : : Block,
1293 : : ConstExpr,
1294 : : ConstBlock,
1295 : : Continue,
1296 : : Break,
1297 : : Range,
1298 : : Box,
1299 : : Return,
1300 : : UnsafeBlock,
1301 : : Loop,
1302 : : If,
1303 : : IfLet,
1304 : : Match,
1305 : : Await,
1306 : : AsyncBlock,
1307 : : InlineAsm,
1308 : : LlvmInlineAsm,
1309 : : Identifier,
1310 : : FormatArgs,
1311 : : OffsetOf,
1312 : : MacroInvocation,
1313 : : Borrow,
1314 : : Dereference,
1315 : : ErrorPropagation,
1316 : : Negation,
1317 : : ArithmeticOrLogical,
1318 : : Comparison,
1319 : : LazyBoolean,
1320 : : TypeCast,
1321 : : Assignment,
1322 : : CompoundAssignment,
1323 : : Try,
1324 : : };
1325 : :
1326 : : virtual Kind get_expr_kind () const = 0;
1327 : :
1328 : : // Unique pointer custom clone function
1329 : 0 : std::unique_ptr<Expr> clone_expr () const
1330 : : {
1331 : 145613 : return std::unique_ptr<Expr> (clone_expr_impl ());
1332 : : }
1333 : :
1334 : : /* TODO: public methods that could be useful:
1335 : : * - get_type() - returns type of expression. set_type() may also be useful
1336 : : * for some?
1337 : : * - evaluate() - evaluates expression if constant? can_evaluate()? */
1338 : :
1339 : : virtual std::string as_string () const = 0;
1340 : :
1341 : 1801 : virtual ~Expr () {}
1342 : :
1343 : : virtual location_t get_locus () const = 0;
1344 : :
1345 : 40 : virtual bool is_literal () const { return false; }
1346 : :
1347 : : // HACK: strictly not needed, but faster than full downcast clone
1348 : : virtual bool is_expr_without_block () const = 0;
1349 : :
1350 : : virtual void mark_for_strip () = 0;
1351 : : virtual bool is_marked_for_strip () const = 0;
1352 : :
1353 : 275151 : virtual NodeId get_node_id () const { return node_id; }
1354 : :
1355 : 0 : virtual void set_node_id (NodeId id) { node_id = id; }
1356 : :
1357 : : virtual std::vector<Attribute> &get_outer_attrs () = 0;
1358 : :
1359 : : // TODO: think of less hacky way to implement this kind of thing
1360 : : // Sets outer attributes.
1361 : : virtual void set_outer_attrs (std::vector<Attribute>) = 0;
1362 : :
1363 : : protected:
1364 : : // Constructor
1365 : 250505 : Expr () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1366 : :
1367 : : // Clone function implementation as pure virtual method
1368 : : virtual Expr *clone_expr_impl () const = 0;
1369 : :
1370 : : NodeId node_id;
1371 : : };
1372 : :
1373 : : // AST node for an expression without an accompanying block - abstract
1374 : 214009 : class ExprWithoutBlock : public Expr
1375 : : {
1376 : : protected:
1377 : : // pure virtual clone implementation
1378 : : virtual ExprWithoutBlock *clone_expr_without_block_impl () const = 0;
1379 : :
1380 : : /* Save having to specify two clone methods in derived classes by making
1381 : : * expr clone return exprwithoutblock clone. Hopefully won't affect
1382 : : * performance too much. */
1383 : 138187 : ExprWithoutBlock *clone_expr_impl () const final override
1384 : : {
1385 : 138187 : return clone_expr_without_block_impl ();
1386 : : }
1387 : :
1388 : 32692 : bool is_expr_without_block () const final override { return true; };
1389 : :
1390 : : public:
1391 : : // Unique pointer custom clone function
1392 : 31 : std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const
1393 : : {
1394 : 31 : return std::unique_ptr<ExprWithoutBlock> (clone_expr_without_block_impl ());
1395 : : }
1396 : : };
1397 : :
1398 : : /* HACK: IdentifierExpr, delete when figure out identifier vs expr problem in
1399 : : * Pratt parser */
1400 : : /* Alternatively, identifiers could just be represented as single-segment
1401 : : * paths
1402 : : */
1403 : : class IdentifierExpr : public ExprWithoutBlock
1404 : : {
1405 : : std::vector<Attribute> outer_attrs;
1406 : : Identifier ident;
1407 : : location_t locus;
1408 : :
1409 : : public:
1410 : 24747 : IdentifierExpr (Identifier ident, std::vector<Attribute> outer_attrs,
1411 : : location_t locus)
1412 : 74241 : : outer_attrs (std::move (outer_attrs)), ident (std::move (ident)),
1413 : 24747 : locus (locus)
1414 : 24747 : {}
1415 : :
1416 : 12 : std::string as_string () const override { return ident.as_string (); }
1417 : :
1418 : 86221 : location_t get_locus () const override final { return locus; }
1419 : :
1420 : 49632 : Identifier get_ident () const { return ident; }
1421 : :
1422 : : void accept_vis (ASTVisitor &vis) override;
1423 : :
1424 : : // Clones this object.
1425 : : std::unique_ptr<IdentifierExpr> clone_identifier_expr () const
1426 : : {
1427 : : return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ());
1428 : : }
1429 : :
1430 : : // "Error state" if ident is empty, so base stripping on this.
1431 : 0 : void mark_for_strip () override { ident = {""}; }
1432 : 165706 : bool is_marked_for_strip () const override { return ident.empty (); }
1433 : :
1434 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1435 : 860175 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1436 : :
1437 : 0 : void set_outer_attrs (std::vector<Attribute> new_attrs) override
1438 : : {
1439 : 0 : outer_attrs = std::move (new_attrs);
1440 : 0 : }
1441 : :
1442 : 5903 : Expr::Kind get_expr_kind () const override { return Expr::Kind::Identifier; }
1443 : :
1444 : : protected:
1445 : : // Clone method implementation
1446 : 26140 : IdentifierExpr *clone_expr_without_block_impl () const final override
1447 : : {
1448 : 26140 : return clone_identifier_expr_impl ();
1449 : : }
1450 : :
1451 : 26140 : IdentifierExpr *clone_identifier_expr_impl () const
1452 : : {
1453 : 26140 : return new IdentifierExpr (*this);
1454 : : }
1455 : : };
1456 : :
1457 : : // Pattern base AST node
1458 : 134750 : class Pattern : public Visitable
1459 : : {
1460 : : public:
1461 : : enum class Kind
1462 : : {
1463 : : Literal,
1464 : : Identifier,
1465 : : Wildcard,
1466 : : Rest,
1467 : : Range,
1468 : : Reference,
1469 : : Struct,
1470 : : TupleStruct,
1471 : : Tuple,
1472 : : Grouped,
1473 : : Slice,
1474 : : Alt,
1475 : : Path,
1476 : : MacroInvocation,
1477 : : };
1478 : :
1479 : : // Unique pointer custom clone function
1480 : 20998 : std::unique_ptr<Pattern> clone_pattern () const
1481 : : {
1482 : 20998 : return std::unique_ptr<Pattern> (clone_pattern_impl ());
1483 : : }
1484 : :
1485 : : virtual Kind get_pattern_kind () = 0;
1486 : :
1487 : : // possible virtual methods: is_refutable()
1488 : :
1489 : : virtual ~Pattern () {}
1490 : :
1491 : : virtual std::string as_string () const = 0;
1492 : :
1493 : : // as only one kind of pattern can be stripped, have default of nothing
1494 : 0 : virtual void mark_for_strip () {}
1495 : 136801 : virtual bool is_marked_for_strip () const { return false; }
1496 : :
1497 : : virtual location_t get_locus () const = 0;
1498 : : virtual NodeId get_node_id () const = 0;
1499 : :
1500 : : protected:
1501 : : // Clone pattern implementation as pure virtual method
1502 : : virtual Pattern *clone_pattern_impl () const = 0;
1503 : : };
1504 : :
1505 : : // forward decl for Type
1506 : : class TraitBound;
1507 : :
1508 : : // Base class for types as represented in AST - abstract
1509 : 56742 : class Type : public Visitable
1510 : : {
1511 : : public:
1512 : : // Unique pointer custom clone function
1513 : 50686 : std::unique_ptr<Type> clone_type () const
1514 : : {
1515 : 50686 : return std::unique_ptr<Type> (clone_type_impl ());
1516 : : }
1517 : :
1518 : : // Similar to `clone_type`, but generates a new instance of the node with a
1519 : : // different NodeId
1520 : 93 : std::unique_ptr<Type> reconstruct () const { return reconstruct_base (this); }
1521 : :
1522 : : // virtual destructor
1523 : 63955 : virtual ~Type () {}
1524 : :
1525 : : virtual std::string as_string () const = 0;
1526 : :
1527 : : /* HACK: convert to trait bound. Virtual method overriden by classes that
1528 : : * enable this. */
1529 : 4 : virtual TraitBound *to_trait_bound (bool) const { return nullptr; }
1530 : : /* as pointer, shouldn't require definition beforehand, only forward
1531 : : * declaration. */
1532 : :
1533 : : // as only two kinds of types can be stripped, have default of nothing
1534 : 0 : virtual void mark_for_strip () {}
1535 : 74196 : virtual bool is_marked_for_strip () const { return false; }
1536 : :
1537 : : virtual location_t get_locus () const = 0;
1538 : :
1539 : 46304 : NodeId get_node_id () const { return node_id; }
1540 : : virtual Type *reconstruct_impl () const = 0;
1541 : :
1542 : : protected:
1543 : 242189 : Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1544 : 2 : Type (NodeId node_id) : node_id (node_id) {}
1545 : :
1546 : : // Clone and reconstruct function implementations as pure virtual methods
1547 : : virtual Type *clone_type_impl () const = 0;
1548 : :
1549 : : NodeId node_id;
1550 : : };
1551 : :
1552 : : // A type without parentheses? - abstract
1553 : 116628 : class TypeNoBounds : public Type
1554 : : {
1555 : : public:
1556 : : // Unique pointer custom clone function
1557 : 8635 : std::unique_ptr<TypeNoBounds> clone_type_no_bounds () const
1558 : : {
1559 : 8635 : return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
1560 : : }
1561 : :
1562 : 0 : std::unique_ptr<TypeNoBounds> reconstruct () const
1563 : : {
1564 : 0 : return reconstruct_base (this);
1565 : : }
1566 : :
1567 : : virtual TypeNoBounds *reconstruct_impl () const override = 0;
1568 : :
1569 : : protected:
1570 : : // Clone function implementation as pure virtual method
1571 : : virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
1572 : :
1573 : : /* Save having to specify two clone methods in derived classes by making
1574 : : * type clone return typenobounds clone. Hopefully won't affect performance
1575 : : * too much. */
1576 : 50684 : TypeNoBounds *clone_type_impl () const final override
1577 : : {
1578 : 50684 : return clone_type_no_bounds_impl ();
1579 : : }
1580 : :
1581 : 242175 : TypeNoBounds () : Type () {}
1582 : : };
1583 : :
1584 : : /* Abstract base class representing a type param bound - Lifetime and
1585 : : * TraitBound extends it */
1586 : : class TypeParamBound : public Visitable
1587 : : {
1588 : : public:
1589 : : enum TypeParamBoundType
1590 : : {
1591 : : TRAIT,
1592 : : LIFETIME
1593 : : };
1594 : :
1595 : 10682 : virtual ~TypeParamBound () {}
1596 : :
1597 : : // Unique pointer custom clone function
1598 : 75 : std::unique_ptr<TypeParamBound> clone_type_param_bound () const
1599 : : {
1600 : 75 : return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
1601 : : }
1602 : :
1603 : 0 : std::unique_ptr<TypeParamBound> reconstruct () const
1604 : : {
1605 : 0 : return reconstruct_base (this);
1606 : : }
1607 : :
1608 : : virtual std::string as_string () const = 0;
1609 : :
1610 : 11282 : NodeId get_node_id () const { return node_id; }
1611 : :
1612 : : virtual location_t get_locus () const = 0;
1613 : :
1614 : : virtual TypeParamBoundType get_bound_type () const = 0;
1615 : :
1616 : : virtual TypeParamBound *reconstruct_impl () const = 0;
1617 : :
1618 : : protected:
1619 : : // Clone function implementation as pure virtual method
1620 : : virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
1621 : :
1622 : : TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ())
1623 : : {}
1624 : 518 : TypeParamBound (NodeId node_id) : node_id (node_id) {}
1625 : :
1626 : : NodeId node_id;
1627 : : };
1628 : :
1629 : : // Represents a lifetime (and is also a kind of type param bound)
1630 : 33866 : class Lifetime : public TypeParamBound
1631 : : {
1632 : : public:
1633 : : enum LifetimeType
1634 : : {
1635 : : NAMED, // corresponds to LIFETIME_OR_LABEL
1636 : : STATIC, // corresponds to 'static
1637 : : WILDCARD // corresponds to '_
1638 : : };
1639 : :
1640 : : private:
1641 : : LifetimeType lifetime_type;
1642 : : std::string lifetime_name;
1643 : : location_t locus;
1644 : : NodeId node_id;
1645 : :
1646 : : public:
1647 : : // Constructor
1648 : 23109 : Lifetime (LifetimeType type, std::string name = std::string (),
1649 : : location_t locus = UNDEF_LOCATION)
1650 : 23109 : : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()),
1651 : 23109 : lifetime_type (type), lifetime_name (std::move (name)), locus (locus)
1652 : 23109 : {}
1653 : :
1654 : 0 : Lifetime (NodeId id, LifetimeType type, std::string name = std::string (),
1655 : : location_t locus = UNDEF_LOCATION)
1656 : 0 : : TypeParamBound (id), lifetime_type (type),
1657 : 0 : lifetime_name (std::move (name)), locus (locus)
1658 : : {}
1659 : :
1660 : 22269 : static Lifetime elided () { return Lifetime (WILDCARD, ""); }
1661 : :
1662 : : // Returns true if the lifetime is in an error state.
1663 : : std::string as_string () const override;
1664 : :
1665 : : void accept_vis (ASTVisitor &vis) override;
1666 : :
1667 : 10137 : LifetimeType get_lifetime_type () const { return lifetime_type; }
1668 : :
1669 : 10207 : location_t get_locus () const override final { return locus; }
1670 : :
1671 : 29745 : std::string get_lifetime_name () const { return lifetime_name; }
1672 : :
1673 : 0 : TypeParamBoundType get_bound_type () const override
1674 : : {
1675 : 0 : return TypeParamBound::TypeParamBoundType::LIFETIME;
1676 : : }
1677 : :
1678 : : protected:
1679 : : /* Use covariance to implement clone function as returning this object
1680 : : * rather than base */
1681 : 0 : Lifetime *clone_type_param_bound_impl () const override
1682 : : {
1683 : 0 : return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
1684 : : }
1685 : 0 : Lifetime *reconstruct_impl () const override
1686 : : {
1687 : 0 : return new Lifetime (lifetime_type, lifetime_name, locus);
1688 : : }
1689 : : };
1690 : :
1691 : : /* Base generic parameter in AST. Abstract - can be represented by a Lifetime
1692 : : * or Type param */
1693 : : class GenericParam : public Visitable
1694 : : {
1695 : : public:
1696 : : enum class Kind
1697 : : {
1698 : : Lifetime,
1699 : : Type,
1700 : : Const,
1701 : : };
1702 : :
1703 : : virtual ~GenericParam () {}
1704 : :
1705 : : // Unique pointer custom clone function
1706 : 557 : std::unique_ptr<GenericParam> clone_generic_param () const
1707 : : {
1708 : 557 : return std::unique_ptr<GenericParam> (clone_generic_param_impl ());
1709 : : }
1710 : :
1711 : : virtual std::string as_string () const = 0;
1712 : :
1713 : : virtual location_t get_locus () const = 0;
1714 : :
1715 : : virtual Kind get_kind () const = 0;
1716 : :
1717 : 93482 : NodeId get_node_id () const { return node_id; }
1718 : :
1719 : : protected:
1720 : 317 : GenericParam () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1721 : 8169 : GenericParam (NodeId node_id) : node_id (node_id) {}
1722 : :
1723 : : // Clone function implementation as pure virtual method
1724 : : virtual GenericParam *clone_generic_param_impl () const = 0;
1725 : :
1726 : : NodeId node_id;
1727 : : };
1728 : :
1729 : : // A lifetime generic parameter (as opposed to a type generic parameter)
1730 : : class LifetimeParam : public GenericParam
1731 : : {
1732 : : Lifetime lifetime;
1733 : : std::vector<Lifetime> lifetime_bounds;
1734 : : AST::AttrVec outer_attrs;
1735 : : location_t locus;
1736 : :
1737 : : public:
1738 : 0 : Lifetime get_lifetime () const { return lifetime; }
1739 : :
1740 : 3490 : Lifetime &get_lifetime () { return lifetime; }
1741 : :
1742 : 3758 : AST::AttrVec &get_outer_attrs () { return outer_attrs; }
1743 : :
1744 : : // Returns whether the lifetime param has any lifetime bounds.
1745 : 20 : bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }
1746 : :
1747 : 3277 : std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
1748 : :
1749 : : const std::vector<Lifetime> &get_lifetime_bounds () const
1750 : : {
1751 : 0 : return lifetime_bounds;
1752 : : }
1753 : :
1754 : : // Returns whether the lifetime param has an outer attribute.
1755 : 0 : bool has_outer_attribute () const { return !outer_attrs.empty (); }
1756 : :
1757 : : // Constructor
1758 : 271 : LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
1759 : : AST::AttrVec outer_attrs, location_t locus)
1760 : 542 : : lifetime (std::move (lifetime)),
1761 : 271 : lifetime_bounds (std::move (lifetime_bounds)),
1762 : 271 : outer_attrs (std::move (outer_attrs)), locus (locus)
1763 : 271 : {}
1764 : :
1765 : : std::string as_string () const override;
1766 : :
1767 : : void accept_vis (ASTVisitor &vis) override;
1768 : :
1769 : 386 : location_t get_locus () const override final { return locus; }
1770 : :
1771 : 486 : Kind get_kind () const override final { return Kind::Lifetime; }
1772 : :
1773 : : protected:
1774 : : /* Use covariance to implement clone function as returning this object
1775 : : * rather than base */
1776 : 440 : LifetimeParam *clone_generic_param_impl () const override
1777 : : {
1778 : 440 : return new LifetimeParam (*this);
1779 : : }
1780 : : };
1781 : :
1782 : 17377 : class AssociatedItem : public Visitable
1783 : : {
1784 : : protected:
1785 : : // Clone function implementation as pure virtual method
1786 : : virtual AssociatedItem *clone_associated_item_impl () const = 0;
1787 : :
1788 : : public:
1789 : : virtual ~AssociatedItem () {}
1790 : :
1791 : 15597 : std::unique_ptr<AssociatedItem> clone_associated_item () const
1792 : : {
1793 : 15597 : return std::unique_ptr<AssociatedItem> (clone_associated_item_impl ());
1794 : : }
1795 : :
1796 : : virtual std::string as_string () const = 0;
1797 : :
1798 : : virtual void mark_for_strip () = 0;
1799 : : virtual bool is_marked_for_strip () const = 0;
1800 : :
1801 : : virtual location_t get_locus () const = 0;
1802 : : };
1803 : :
1804 : : // Item used in trait declarations - abstract base class
1805 : : class TraitItem : public AssociatedItem
1806 : : {
1807 : : protected:
1808 : 13540 : TraitItem (location_t locus)
1809 : 13540 : : node_id (Analysis::Mappings::get ().get_next_node_id ()),
1810 : 27080 : vis (Visibility::create_private ()), locus (locus)
1811 : 13540 : {}
1812 : :
1813 : 735 : TraitItem (Visibility vis, location_t locus)
1814 : 735 : : node_id (Analysis::Mappings::get ().get_next_node_id ()), vis (vis),
1815 : 735 : locus (locus)
1816 : 735 : {}
1817 : :
1818 : : // Clone function implementation as pure virtual method
1819 : : virtual TraitItem *clone_associated_item_impl () const override = 0;
1820 : :
1821 : : NodeId node_id;
1822 : : Visibility vis;
1823 : : location_t locus;
1824 : :
1825 : : public:
1826 : : // Unique pointer custom clone function
1827 : : std::unique_ptr<TraitItem> clone_trait_item () const
1828 : : {
1829 : : return std::unique_ptr<TraitItem> (clone_associated_item_impl ());
1830 : : }
1831 : :
1832 : 3455 : NodeId get_node_id () const { return node_id; }
1833 : 3724 : location_t get_locus () const override { return locus; }
1834 : : };
1835 : :
1836 : : // Abstract base class for an item used inside an extern block
1837 : : class ExternalItem : public Visitable
1838 : : {
1839 : : public:
1840 : 2955 : ExternalItem () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1841 : :
1842 : 41827 : ExternalItem (NodeId node_id) : node_id (node_id) {}
1843 : :
1844 : : virtual ~ExternalItem () {}
1845 : :
1846 : : // Unique pointer custom clone function
1847 : 63 : std::unique_ptr<ExternalItem> clone_external_item () const
1848 : : {
1849 : 63 : return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
1850 : : }
1851 : :
1852 : : virtual std::string as_string () const = 0;
1853 : :
1854 : : virtual void mark_for_strip () = 0;
1855 : : virtual bool is_marked_for_strip () const = 0;
1856 : :
1857 : 4 : virtual NodeId get_node_id () const { return node_id; }
1858 : :
1859 : : protected:
1860 : : // Clone function implementation as pure virtual method
1861 : : virtual ExternalItem *clone_external_item_impl () const = 0;
1862 : :
1863 : : NodeId node_id;
1864 : : };
1865 : :
1866 : : /* Data structure to store the data used in macro invocations and macro
1867 : : * invocations with semicolons. */
1868 : : struct MacroInvocData
1869 : : {
1870 : : private:
1871 : : SimplePath path;
1872 : : DelimTokenTree token_tree;
1873 : :
1874 : : // One way of parsing the macro. Probably not applicable for all macros.
1875 : : std::vector<std::unique_ptr<MetaItemInner>> parsed_items;
1876 : : bool parsed_to_meta_item = false;
1877 : : MacroExpander *expander = nullptr;
1878 : :
1879 : : public:
1880 : : std::string as_string () const;
1881 : :
1882 : 2951 : MacroInvocData (SimplePath path, DelimTokenTree token_tree)
1883 : 2951 : : path (std::move (path)), token_tree (std::move (token_tree))
1884 : 2951 : {}
1885 : :
1886 : : // Copy constructor with vector clone
1887 : 13486 : MacroInvocData (const MacroInvocData &other)
1888 : 13486 : : path (other.path), token_tree (other.token_tree),
1889 : 13486 : parsed_to_meta_item (other.parsed_to_meta_item)
1890 : : {
1891 : 13486 : parsed_items.reserve (other.parsed_items.size ());
1892 : 13486 : for (const auto &e : other.parsed_items)
1893 : 0 : parsed_items.push_back (e->clone_meta_item_inner ());
1894 : 13486 : }
1895 : :
1896 : : // Copy assignment operator with vector clone
1897 : : MacroInvocData &operator= (const MacroInvocData &other)
1898 : : {
1899 : : path = other.path;
1900 : : token_tree = other.token_tree;
1901 : : parsed_to_meta_item = other.parsed_to_meta_item;
1902 : : expander = other.expander;
1903 : :
1904 : : parsed_items.reserve (other.parsed_items.size ());
1905 : : for (const auto &e : other.parsed_items)
1906 : : parsed_items.push_back (e->clone_meta_item_inner ());
1907 : :
1908 : : return *this;
1909 : : }
1910 : :
1911 : : // Move constructors
1912 : 3329 : MacroInvocData (MacroInvocData &&other) = default;
1913 : : MacroInvocData &operator= (MacroInvocData &&other) = default;
1914 : :
1915 : : // Invalid if path is empty, so base stripping on that.
1916 : 0 : void mark_for_strip () { path = SimplePath::create_empty (); }
1917 : 6120 : bool is_marked_for_strip () const { return path.is_empty (); }
1918 : :
1919 : : // Returns whether the macro has been parsed already.
1920 : 47 : bool is_parsed () const { return parsed_to_meta_item; }
1921 : : // TODO: update on other ways of parsing it
1922 : :
1923 : : // TODO: this mutable getter seems kinda dodgy
1924 : 6950 : DelimTokenTree &get_delim_tok_tree () { return token_tree; }
1925 : : const DelimTokenTree &get_delim_tok_tree () const { return token_tree; }
1926 : :
1927 : : // Set the delim token tree of a macro invocation
1928 : 42 : void set_delim_tok_tree (DelimTokenTree tree) { token_tree = tree; }
1929 : :
1930 : : // TODO: this mutable getter seems kinda dodgy
1931 : 6984 : SimplePath &get_path () { return path; }
1932 : : const SimplePath &get_path () const { return path; }
1933 : :
1934 : 2788 : void set_expander (MacroExpander *new_expander) { expander = new_expander; }
1935 : 218 : MacroExpander *get_expander ()
1936 : : {
1937 : 218 : rust_assert (expander);
1938 : 218 : return expander;
1939 : : }
1940 : :
1941 : : void
1942 : 47 : set_meta_item_output (std::vector<std::unique_ptr<MetaItemInner>> new_items)
1943 : : {
1944 : 47 : parsed_items = std::move (new_items);
1945 : : }
1946 : : // TODO: mutable getter seems kinda dodgy
1947 : : std::vector<std::unique_ptr<MetaItemInner>> &get_meta_items ()
1948 : : {
1949 : : return parsed_items;
1950 : : }
1951 : : const std::vector<std::unique_ptr<MetaItemInner>> &get_meta_items () const
1952 : : {
1953 : : return parsed_items;
1954 : : }
1955 : : };
1956 : :
1957 : : class SingleASTNode : public Visitable
1958 : : {
1959 : : public:
1960 : : enum NodeType
1961 : : {
1962 : : EXPRESSION,
1963 : : ITEM,
1964 : : STMT,
1965 : : EXTERN,
1966 : : ASSOC_ITEM,
1967 : : TYPE,
1968 : : };
1969 : :
1970 : : private:
1971 : : NodeType kind;
1972 : :
1973 : : // FIXME make this a union
1974 : : std::unique_ptr<Expr> expr;
1975 : : std::unique_ptr<Item> item;
1976 : : std::unique_ptr<Stmt> stmt;
1977 : : std::unique_ptr<ExternalItem> external_item;
1978 : : std::unique_ptr<AssociatedItem> assoc_item;
1979 : : std::unique_ptr<Type> type;
1980 : :
1981 : : public:
1982 : 1925 : SingleASTNode (std::unique_ptr<Expr> expr)
1983 : 1925 : : kind (EXPRESSION), expr (std::move (expr))
1984 : : {}
1985 : :
1986 : 2582 : SingleASTNode (std::unique_ptr<Item> item)
1987 : 2582 : : kind (ITEM), item (std::move (item))
1988 : : {}
1989 : :
1990 : 465 : SingleASTNode (std::unique_ptr<Stmt> stmt)
1991 : 465 : : kind (STMT), stmt (std::move (stmt))
1992 : : {}
1993 : :
1994 : 3 : SingleASTNode (std::unique_ptr<ExternalItem> item)
1995 : 3 : : kind (EXTERN), external_item (std::move (item))
1996 : : {}
1997 : :
1998 : 107 : SingleASTNode (std::unique_ptr<AssociatedItem> item)
1999 : 107 : : kind (ASSOC_ITEM), assoc_item (std::move (item))
2000 : : {}
2001 : :
2002 : 28 : SingleASTNode (std::unique_ptr<Type> type)
2003 : 28 : : kind (TYPE), type (std::move (type))
2004 : : {}
2005 : :
2006 : : SingleASTNode (SingleASTNode const &other);
2007 : :
2008 : : SingleASTNode operator= (SingleASTNode const &other);
2009 : :
2010 : 6084 : SingleASTNode (SingleASTNode &&other) = default;
2011 : : SingleASTNode &operator= (SingleASTNode &&other) = default;
2012 : :
2013 : 3782 : NodeType get_kind () const { return kind; }
2014 : :
2015 : : std::unique_ptr<Expr> &get_expr ()
2016 : : {
2017 : : rust_assert (kind == EXPRESSION);
2018 : : return expr;
2019 : : }
2020 : :
2021 : : std::unique_ptr<Item> &get_item ()
2022 : : {
2023 : : rust_assert (kind == ITEM);
2024 : : return item;
2025 : : }
2026 : :
2027 : : std::unique_ptr<Stmt> &get_stmt ()
2028 : : {
2029 : : rust_assert (kind == STMT);
2030 : : return stmt;
2031 : : }
2032 : :
2033 : : /**
2034 : : * Access the inner nodes and take ownership of them.
2035 : : * You can only call these functions once per node
2036 : : */
2037 : :
2038 : 479 : std::unique_ptr<Stmt> take_stmt ()
2039 : : {
2040 : 479 : rust_assert (!is_error ());
2041 : 479 : return std::move (stmt);
2042 : : }
2043 : :
2044 : 1863 : std::unique_ptr<Expr> take_expr ()
2045 : : {
2046 : 1863 : rust_assert (!is_error ());
2047 : 1863 : return std::move (expr);
2048 : : }
2049 : :
2050 : 2581 : std::unique_ptr<Item> take_item ()
2051 : : {
2052 : 2581 : rust_assert (!is_error ());
2053 : 2581 : return std::move (item);
2054 : : }
2055 : :
2056 : 3 : std::unique_ptr<ExternalItem> take_external_item ()
2057 : : {
2058 : 3 : rust_assert (!is_error ());
2059 : 3 : return std::move (external_item);
2060 : : }
2061 : :
2062 : 107 : std::unique_ptr<AssociatedItem> take_assoc_item ()
2063 : : {
2064 : 107 : rust_assert (!is_error ());
2065 : 107 : return std::move (assoc_item);
2066 : : }
2067 : :
2068 : 28 : std::unique_ptr<Type> take_type ()
2069 : : {
2070 : 28 : rust_assert (!is_error ());
2071 : 28 : return std::move (type);
2072 : : }
2073 : :
2074 : : void accept_vis (ASTVisitor &vis) override;
2075 : :
2076 : : bool is_error ();
2077 : :
2078 : : std::string as_string () const;
2079 : : };
2080 : :
2081 : : // A crate AST object - holds all the data for a single compilation unit
2082 : : struct Crate
2083 : : {
2084 : : std::vector<Attribute> inner_attrs;
2085 : : // dodgy spacing required here
2086 : : /* TODO: is it better to have a vector of items here or a module (implicit
2087 : : * top-level one)? */
2088 : : std::vector<std::unique_ptr<Item>> items;
2089 : :
2090 : : NodeId node_id;
2091 : :
2092 : : public:
2093 : : // Constructor
2094 : 4426 : Crate (std::vector<std::unique_ptr<Item>> items,
2095 : : std::vector<Attribute> inner_attrs)
2096 : 4426 : : inner_attrs (std::move (inner_attrs)), items (std::move (items)),
2097 : 4426 : node_id (Analysis::Mappings::get ().get_next_node_id ())
2098 : 4426 : {}
2099 : :
2100 : : // Copy constructor with vector clone
2101 : 16 : Crate (Crate const &other)
2102 : 16 : : inner_attrs (other.inner_attrs), node_id (other.node_id)
2103 : : {
2104 : 16 : items.reserve (other.items.size ());
2105 : 413 : for (const auto &e : other.items)
2106 : 397 : items.push_back (e->clone_item ());
2107 : 16 : }
2108 : :
2109 : 104 : ~Crate () = default;
2110 : :
2111 : : // Overloaded assignment operator with vector clone
2112 : : Crate &operator= (Crate const &other)
2113 : : {
2114 : : inner_attrs = other.inner_attrs;
2115 : : node_id = other.node_id;
2116 : :
2117 : : items.reserve (other.items.size ());
2118 : : for (const auto &e : other.items)
2119 : : items.push_back (e->clone_item ());
2120 : :
2121 : : return *this;
2122 : : }
2123 : :
2124 : : // Move constructors
2125 : : Crate (Crate &&other) = default;
2126 : : Crate &operator= (Crate &&other) = default;
2127 : :
2128 : : // Get crate representation as string (e.g. for debugging).
2129 : : std::string as_string () const;
2130 : :
2131 : : // Delete all crate information, e.g. if fails cfg.
2132 : 0 : void strip_crate ()
2133 : : {
2134 : 0 : inner_attrs.clear ();
2135 : 0 : inner_attrs.shrink_to_fit ();
2136 : :
2137 : 0 : items.clear ();
2138 : 0 : items.shrink_to_fit ();
2139 : : // TODO: is this the best way to do this?
2140 : 0 : }
2141 : :
2142 : 83265 : NodeId get_node_id () const { return node_id; }
2143 : : const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
2144 : 68355 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
2145 : :
2146 : 0 : std::vector<std::unique_ptr<AST::Item>> take_items ()
2147 : : {
2148 : 0 : return std::move (items);
2149 : : }
2150 : :
2151 : 0 : void set_items (std::vector<std::unique_ptr<AST::Item>> &&new_items)
2152 : : {
2153 : 0 : items = std::move (new_items);
2154 : : }
2155 : : };
2156 : :
2157 : : } // namespace AST
2158 : : } // namespace Rust
2159 : :
2160 : : namespace std {
2161 : : template <> struct less<Rust::Identifier>
2162 : : {
2163 : 0 : bool operator() (const Rust::Identifier &lhs,
2164 : : const Rust::Identifier &rhs) const
2165 : : {
2166 : 0 : return lhs.as_string () < rhs.as_string ();
2167 : : }
2168 : : };
2169 : :
2170 : : template <> struct hash<Rust::Identifier>
2171 : : {
2172 : : std::size_t operator() (const Rust::Identifier &k) const
2173 : : {
2174 : : using std::hash;
2175 : : using std::size_t;
2176 : : using std::string;
2177 : :
2178 : : return hash<string> () (k.as_string ()) ^ (hash<int> () (k.get_locus ()));
2179 : : }
2180 : : };
2181 : :
2182 : : } // namespace std
2183 : :
2184 : : #endif
|