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