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