]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/rust/ast/rust-ast.h
aa6ad5066aa136d5cc2d2da0b42710517a703228
[thirdparty/gcc.git] / gcc / rust / ast / rust-ast.h
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 class Identifier
37 {
38 public:
39 // Create dummy identifier
40 Identifier () : ident (""), loc (UNDEF_LOCATION) {}
41 // Create identifier with dummy location
42 Identifier (std::string ident, location_t loc = UNDEF_LOCATION)
43 : ident (ident), loc (loc)
44 {}
45 // Create identifier from token
46 Identifier (const_TokenPtr token)
47 : ident (token->get_str ()), loc (token->get_locus ())
48 {}
49
50 Identifier (const Identifier &) = default;
51 Identifier (Identifier &&) = default;
52 Identifier &operator= (const Identifier &) = default;
53 Identifier &operator= (Identifier &&) = default;
54
55 location_t get_locus () const { return loc; }
56 const std::string &as_string () const { return ident; }
57
58 bool empty () const { return ident.empty (); }
59
60 bool operator== (const Identifier &other) const
61 {
62 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 class Visitable
79 {
80 public:
81 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 class TokenTree : public Visitable
98 {
99 public:
100 virtual ~TokenTree () {}
101
102 // Unique pointer custom clone function
103 std::unique_ptr<TokenTree> clone_token_tree () const
104 {
105 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 class MacroMatch : public Visitable
121 {
122 public:
123 enum MacroMatchType
124 {
125 Fragment,
126 Repetition,
127 Matcher,
128 Tok
129 };
130
131 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 std::unique_ptr<MacroMatch> clone_macro_match () const
138 {
139 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 std::unique_ptr<Token> clone_token () const
175 {
176 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 Token (const_TokenPtr lexer_tok_ptr) : tok_ref (std::move (lexer_tok_ptr)) {}
227
228 bool is_string_lit () const
229 {
230 switch (get_id ())
231 {
232 case STRING_LITERAL:
233 case BYTE_STRING_LITERAL:
234 case RAW_STRING_LITERAL:
235 return true;
236 default:
237 return false;
238 }
239 }
240
241 std::string as_string () const override;
242 location_t get_match_locus () const override
243 {
244 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 TokenId get_id () const { return tok_ref->get_id (); }
253 const std::string &get_str () const { return tok_ref->get_str (); }
254
255 location_t get_locus () const { return tok_ref->get_locus (); }
256
257 PrimitiveCoreType get_type_hint () const { return tok_ref->get_type_hint (); }
258
259 // Get a new token pointer copy.
260 const_TokenPtr get_tok_ptr () const { return tok_ref; }
261
262 MacroMatchType get_macro_match_type () const override
263 {
264 return MacroMatchType::Tok;
265 }
266
267 protected:
268 // No virtual for now as not polymorphic but can be in future
269 /*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 Token *clone_token_tree_impl () const final override
274 {
275 return clone_token_impl ();
276 }
277
278 /* Use covariance to implement clone function as returning this object
279 * rather than base */
280 Token *clone_macro_match_impl () const final override
281 {
282 return clone_token_impl ();
283 }
284 };
285
286 // A literal - value with a type. Used in LiteralExpr and LiteralPattern.
287 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 std::string as_string () const { return value_as_string; }
312
313 LitType get_lit_type () const { return type; }
314
315 PrimitiveCoreType get_type_hint () const { return type_hint; }
316
317 Literal (std::string value_as_string, LitType type,
318 PrimitiveCoreType type_hint)
319 : value_as_string (std::move (value_as_string)), type (type),
320 type_hint (type_hint)
321 {}
322
323 static Literal create_error ()
324 {
325 return Literal ("", ERROR, PrimitiveCoreType::CORETYPE_UNKNOWN);
326 }
327
328 // Returns whether literal is in an invalid state.
329 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 class PathSegment
339 {
340 public:
341 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 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 SimplePathSegment (std::string segment_name, location_t locus)
359 : segment_name (std::move (segment_name)), locus (locus),
360 node_id (Analysis::Mappings::get ().get_next_node_id ())
361 {}
362
363 /* Returns whether simple path segment is in an invalid state (currently, if
364 * empty). */
365 bool is_error () const { return segment_name.empty (); }
366
367 // Creates an error SimplePathSegment
368 static SimplePathSegment create_error ()
369 {
370 return SimplePathSegment (std::string (""), UNDEF_LOCATION);
371 }
372
373 std::string as_string () const override;
374
375 location_t get_locus () const { return locus; }
376 NodeId get_node_id () const { return node_id; }
377 const std::string &get_segment_name () const { return segment_name; }
378 bool is_super_path_seg () const
379 {
380 return as_string ().compare (Values::Keywords::SUPER) == 0;
381 }
382 bool is_crate_path_seg () const
383 {
384 return as_string ().compare (Values::Keywords::CRATE) == 0;
385 }
386 bool is_lower_self_seg () const
387 {
388 return as_string ().compare (Values::Keywords::SELF) == 0;
389 }
390 bool is_big_self () const
391 {
392 return as_string ().compare (Values::Keywords::SELF_ALIAS) == 0;
393 }
394 };
395
396 // A simple path without generic or type arguments
397 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 SimplePath (std::vector<SimplePathSegment> path_segments,
407 bool has_opening_scope_resolution = false,
408 location_t locus = UNDEF_LOCATION)
409 : opening_scope_resolution (has_opening_scope_resolution),
410 segments (std::move (path_segments)), locus (locus),
411 node_id (Analysis::Mappings::get ().get_next_node_id ())
412 {}
413
414 SimplePath (Identifier ident)
415 : opening_scope_resolution (false),
416 segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}),
417 locus (ident.get_locus ()),
418 node_id (Analysis::Mappings::get ().get_next_node_id ())
419 {}
420
421 // Creates an empty SimplePath.
422 static SimplePath create_empty ()
423 {
424 return SimplePath (std::vector<SimplePathSegment> ());
425 }
426
427 // Returns whether the SimplePath is empty, i.e. has path segments.
428 bool is_empty () const { return segments.empty (); }
429
430 const std::string as_string () const;
431
432 bool has_opening_scope_resolution () const
433 {
434 return opening_scope_resolution;
435 }
436
437 location_t get_locus () const { return locus; }
438 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 bool operator== (const std::string &rhs) const
444 {
445 return !opening_scope_resolution && segments.size () == 1
446 && 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 static SimplePath from_str (std::string str, location_t locus)
454 {
455 std::vector<AST::SimplePathSegment> single_segments
456 = {AST::SimplePathSegment (std::move (str), locus)};
457 return SimplePath (std::move (single_segments), false, locus);
458 }
459
460 const std::vector<SimplePathSegment> &get_segments () const
461 {
462 return segments;
463 }
464
465 std::vector<SimplePathSegment> &get_segments () { return segments; }
466
467 const SimplePathSegment &get_final_segment () const
468 {
469 return segments.back ();
470 }
471 };
472
473 // path-to-string inverse comparison operator
474 inline bool
475 operator!= (const SimplePath &lhs, const std::string &rhs)
476 {
477 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 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 Visibility (VisType vis_type, SimplePath in_path, location_t locus)
508 : vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
509 {}
510
511 VisType get_vis_type () const { return vis_type; }
512
513 // Returns whether visibility is in an error state.
514 bool is_error () const
515 {
516 return vis_type == PUB_IN_PATH && in_path.is_empty ();
517 }
518
519 // Returns whether a visibility has a path
520 bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; }
521
522 // Returns whether visibility is public or not.
523 bool is_public () const { return vis_type != PRIV && !is_error (); }
524
525 location_t get_locus () const { return locus; }
526
527 // empty?
528 // Creates an error visibility.
529 static Visibility create_error ()
530 {
531 return Visibility (PUB_IN_PATH, SimplePath::create_empty (),
532 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 static Visibility create_public (location_t pub_vis_location)
546 {
547 return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
548 }
549
550 // Creates a public visibility with crate-relative paths
551 static Visibility create_crate (location_t crate_tok_location,
552 location_t crate_vis_location)
553 {
554 return Visibility (PUB_CRATE,
555 SimplePath::from_str (Values::Keywords::CRATE,
556 crate_tok_location),
557 crate_vis_location);
558 }
559
560 // Creates a public visibility with self-relative paths
561 static Visibility create_self (location_t self_tok_location,
562 location_t self_vis_location)
563 {
564 return Visibility (PUB_SELF,
565 SimplePath::from_str (Values::Keywords::SELF,
566 self_tok_location),
567 self_vis_location);
568 }
569
570 // Creates a public visibility with parent module-relative paths
571 static Visibility create_super (location_t super_tok_location,
572 location_t super_vis_location)
573 {
574 return Visibility (PUB_SUPER,
575 SimplePath::from_str (Values::Keywords::SUPER,
576 super_tok_location),
577 super_vis_location);
578 }
579
580 // Creates a private visibility
581 static Visibility create_private ()
582 {
583 return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION);
584 }
585
586 // Creates a public visibility with a given path or whatever.
587 static Visibility create_in_path (SimplePath in_path,
588 location_t in_path_vis_location)
589 {
590 return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
591 }
592
593 std::string as_string () const;
594 const SimplePath &get_path () const { return in_path; }
595 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 bool has_attr_input () const { return attr_input != nullptr; }
625
626 // Constructor has pointer AttrInput for polymorphism reasons
627 Attribute (SimplePath path, std::unique_ptr<AttrInput> input,
628 location_t locus = UNDEF_LOCATION, bool inner_attribute = false)
629 : path (std::move (path)), attr_input (std::move (input)), locus (locus),
630 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 ~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 Attribute (Attribute &&other) = default;
648 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 static Attribute create_empty ()
658 {
659 return Attribute (SimplePath::create_empty (), nullptr);
660 }
661
662 // Returns whether the attribute is considered an "empty" attribute.
663 bool is_empty () const { return attr_input == nullptr && path.is_empty (); }
664
665 // Returns whether the attribute has no input
666 bool empty_input () const { return !attr_input; }
667
668 location_t get_locus () const { return locus; }
669
670 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 bool is_inner_attribute () const { return inner_attribute; }
727
728 // no visitor pattern as not currently polymorphic
729
730 const SimplePath &get_path () const { return path; }
731 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 class AttrInput : public Visitable
758 {
759 public:
760 enum AttrInputType
761 {
762 LITERAL,
763 MACRO,
764 META_ITEM,
765 TOKEN_TREE,
766 };
767
768 virtual ~AttrInput () {}
769
770 // Unique pointer custom clone function
771 std::unique_ptr<AttrInput> clone_attr_input () const
772 {
773 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 virtual AttrInput *parse_to_meta_item () const { return nullptr; }
782
783 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 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 std::unique_ptr<MetaItemInner> clone_meta_item_inner () const
814 {
815 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 virtual SimplePath to_path_item () const
832 {
833 return SimplePath::create_empty ();
834 }
835
836 virtual Attribute to_attribute () const { return Attribute::create_empty (); }
837
838 virtual bool check_cfg_predicate (const Session &session) const = 0;
839
840 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 AttrInputMetaItemContainer (std::vector<std::unique_ptr<MetaItemInner>> items)
850 : items (std::move (items))
851 {}
852
853 // copy constructor with vector clone
854 AttrInputMetaItemContainer (const AttrInputMetaItemContainer &other)
855 {
856 items.reserve (other.items.size ());
857 for (const auto &e : other.items)
858 items.push_back (e->clone_meta_item_inner ());
859 }
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 AttrInputType get_attr_input_type () const final override
886 {
887 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 bool is_meta_item () const override { return true; }
901
902 // TODO: this mutable getter seems dodgy
903 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 AttrInputMetaItemContainer *clone_attr_input_impl () const final override
912 {
913 return clone_attr_input_meta_item_container_impl ();
914 }
915
916 AttrInputMetaItemContainer *clone_attr_input_meta_item_container_impl () const
917 {
918 return new AttrInputMetaItemContainer (*this);
919 }
920 };
921
922 // A token tree with delimiters
923 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 DelimTokenTree *clone_delim_tok_tree_impl () const
931 {
932 return new DelimTokenTree (*this);
933 }
934
935 /* Use covariance to implement clone function as returning a DelimTokenTree
936 * object */
937 DelimTokenTree *clone_attr_input_impl () const final override
938 {
939 return clone_delim_tok_tree_impl ();
940 }
941
942 /* Use covariance to implement clone function as returning a DelimTokenTree
943 * object */
944 DelimTokenTree *clone_token_tree_impl () const final override
945 {
946 return clone_delim_tok_tree_impl ();
947 }
948
949 public:
950 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 : delim_type (delim_type), token_trees (std::move (token_trees)),
955 locus (locus)
956 {}
957
958 // Copy constructor with vector clone
959 DelimTokenTree (DelimTokenTree const &other)
960 : delim_type (other.delim_type), locus (other.locus)
961 {
962 token_trees.clear ();
963 token_trees.reserve (other.token_trees.size ());
964 for (const auto &e : other.token_trees)
965 token_trees.push_back (e->clone_token_tree ());
966 }
967
968 // overloaded assignment operator with vector clone
969 DelimTokenTree &operator= (DelimTokenTree const &other)
970 {
971 delim_type = other.delim_type;
972 locus = other.locus;
973
974 token_trees.clear ();
975 token_trees.reserve (other.token_trees.size ());
976 for (const auto &e : other.token_trees)
977 token_trees.push_back (e->clone_token_tree ());
978
979 return *this;
980 }
981
982 // move constructors
983 DelimTokenTree (DelimTokenTree &&other) = default;
984 DelimTokenTree &operator= (DelimTokenTree &&other) = default;
985
986 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 bool check_cfg_predicate (const Session &) const override
993 {
994 // this should never be called - should be converted first
995 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 bool is_meta_item () const override { return false; }
1009
1010 AttrInputType get_attr_input_type () const final override
1011 {
1012 return AttrInput::AttrInputType::TOKEN_TREE;
1013 }
1014
1015 std::vector<std::unique_ptr<TokenTree>> &get_token_trees ()
1016 {
1017 return token_trees;
1018 }
1019
1020 const std::vector<std::unique_ptr<TokenTree>> &get_token_trees () const
1021 {
1022 return token_trees;
1023 }
1024
1025 DelimType get_delim_type () const { return delim_type; }
1026 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 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 MetaItemInner::Kind get_kind () override
1049 {
1050 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 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 std::unique_ptr<Stmt> clone_stmt () const
1094 {
1095 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 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 virtual bool is_expr () const { return false; }
1113
1114 virtual void add_semicolon () {}
1115
1116 protected:
1117 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 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 std::unique_ptr<Item> clone_item () const
1153 {
1154 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 add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
1161 {}
1162
1163 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 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 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 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 VisItem (Visibility visibility,
1193 std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1194 : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs))
1195 {}
1196
1197 // Visibility copy constructor
1198 VisItem (VisItem const &other)
1199 : visibility (other.visibility), outer_attrs (other.outer_attrs)
1200 {}
1201
1202 // Overload assignment operator to clone
1203 VisItem &operator= (VisItem const &other)
1204 {
1205 visibility = other.visibility;
1206 outer_attrs = other.outer_attrs;
1207
1208 return *this;
1209 }
1210
1211 // move constructors
1212 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 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 Visibility &get_visibility () { return visibility; }
1224 const Visibility &get_visibility () const { return visibility; }
1225
1226 std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1227 const std::vector<Attribute> &get_outer_attrs () const override
1228 {
1229 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 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 std::unique_ptr<Expr> clone_expr () const
1292 {
1293 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 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 virtual NodeId get_node_id () const { return node_id; }
1316
1317 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 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 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 ExprWithoutBlock *clone_expr_impl () const final override
1346 {
1347 return clone_expr_without_block_impl ();
1348 }
1349
1350 bool is_expr_without_block () const final override { return true; };
1351
1352 public:
1353 // Unique pointer custom clone function
1354 std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const
1355 {
1356 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 IdentifierExpr (Identifier ident, std::vector<Attribute> outer_attrs,
1373 location_t locus)
1374 : outer_attrs (std::move (outer_attrs)), ident (std::move (ident)),
1375 locus (locus)
1376 {}
1377
1378 std::string as_string () const override { return ident.as_string (); }
1379
1380 location_t get_locus () const override final { return locus; }
1381
1382 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 void mark_for_strip () override { ident = {""}; }
1394 bool is_marked_for_strip () const override { return ident.empty (); }
1395
1396 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1397 std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1398
1399 void set_outer_attrs (std::vector<Attribute> new_attrs) override
1400 {
1401 outer_attrs = std::move (new_attrs);
1402 }
1403
1404 Expr::Kind get_expr_kind () const override { return Expr::Kind::Identifier; }
1405
1406 protected:
1407 // Clone method implementation
1408 IdentifierExpr *clone_expr_without_block_impl () const final override
1409 {
1410 return clone_identifier_expr_impl ();
1411 }
1412
1413 IdentifierExpr *clone_identifier_expr_impl () const
1414 {
1415 return new IdentifierExpr (*this);
1416 }
1417 };
1418
1419 // Pattern base AST node
1420 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 std::unique_ptr<Pattern> clone_pattern () const
1443 {
1444 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 virtual void mark_for_strip () {}
1457 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 class Type : public Visitable
1472 {
1473 public:
1474 // Unique pointer custom clone function
1475 std::unique_ptr<Type> clone_type () const
1476 {
1477 return std::unique_ptr<Type> (clone_type_impl ());
1478 }
1479
1480 // virtual destructor
1481 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 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 virtual void mark_for_strip () {}
1493 virtual bool is_marked_for_strip () const { return false; }
1494
1495 virtual location_t get_locus () const = 0;
1496
1497 NodeId get_node_id () const { return node_id; }
1498
1499 protected:
1500 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 class TypeNoBounds : public Type
1510 {
1511 public:
1512 // Unique pointer custom clone function
1513 std::unique_ptr<TypeNoBounds> clone_type_no_bounds () const
1514 {
1515 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 TypeNoBounds *clone_type_impl () const final override
1526 {
1527 return clone_type_no_bounds_impl ();
1528 }
1529
1530 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 virtual ~TypeParamBound () {}
1545
1546 // Unique pointer custom clone function
1547 std::unique_ptr<TypeParamBound> clone_type_param_bound () const
1548 {
1549 return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
1550 }
1551
1552 virtual std::string as_string () const = 0;
1553
1554 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 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 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 Lifetime (LifetimeType type, std::string name = std::string (),
1589 location_t locus = UNDEF_LOCATION)
1590 : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()),
1591 lifetime_type (type), lifetime_name (std::move (name)), locus (locus)
1592 {}
1593
1594 Lifetime (NodeId id, LifetimeType type, std::string name = std::string (),
1595 location_t locus = UNDEF_LOCATION)
1596 : TypeParamBound (id), lifetime_type (type),
1597 lifetime_name (std::move (name)), locus (locus)
1598 {}
1599
1600 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 LifetimeType get_lifetime_type () const { return lifetime_type; }
1608
1609 location_t get_locus () const override final { return locus; }
1610
1611 std::string get_lifetime_name () const { return lifetime_name; }
1612
1613 TypeParamBoundType get_bound_type () const override
1614 {
1615 return TypeParamBound::TypeParamBoundType::LIFETIME;
1616 }
1617
1618 protected:
1619 /* Use covariance to implement clone function as returning this object
1620 * rather than base */
1621 Lifetime *clone_type_param_bound_impl () const override
1622 {
1623 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 std::unique_ptr<GenericParam> clone_generic_param () const
1643 {
1644 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 NodeId get_node_id () const { return node_id; }
1654
1655 protected:
1656 GenericParam () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1657 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 Lifetime get_lifetime () const { return lifetime; }
1675
1676 Lifetime &get_lifetime () { return lifetime; }
1677
1678 AST::AttrVec &get_outer_attrs () { return outer_attrs; }
1679
1680 // Returns whether the lifetime param has any lifetime bounds.
1681 bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }
1682
1683 std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
1684
1685 const std::vector<Lifetime> &get_lifetime_bounds () const
1686 {
1687 return lifetime_bounds;
1688 }
1689
1690 // Returns whether the lifetime param has an outer attribute.
1691 bool has_outer_attribute () const { return !outer_attrs.empty (); }
1692
1693 // Constructor
1694 LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
1695 AST::AttrVec outer_attrs, location_t locus)
1696 : lifetime (std::move (lifetime)),
1697 lifetime_bounds (std::move (lifetime_bounds)),
1698 outer_attrs (std::move (outer_attrs)), locus (locus)
1699 {}
1700
1701 std::string as_string () const override;
1702
1703 void accept_vis (ASTVisitor &vis) override;
1704
1705 location_t get_locus () const override final { return locus; }
1706
1707 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 LifetimeParam *clone_generic_param_impl () const override
1713 {
1714 return new LifetimeParam (*this);
1715 }
1716 };
1717
1718 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 std::unique_ptr<AssociatedItem> clone_associated_item () const
1728 {
1729 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 TraitItem (location_t locus)
1745 : node_id (Analysis::Mappings::get ().get_next_node_id ()),
1746 vis (Visibility::create_private ()), locus (locus)
1747 {}
1748
1749 TraitItem (Visibility vis, location_t locus)
1750 : node_id (Analysis::Mappings::get ().get_next_node_id ()), vis (vis),
1751 locus (locus)
1752 {}
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 NodeId get_node_id () const { return node_id; }
1769 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 ExternalItem () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1777
1778 ExternalItem (NodeId node_id) : node_id (node_id) {}
1779
1780 virtual ~ExternalItem () {}
1781
1782 // Unique pointer custom clone function
1783 std::unique_ptr<ExternalItem> clone_external_item () const
1784 {
1785 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 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 MacroInvocData (SimplePath path, DelimTokenTree token_tree)
1819 : path (std::move (path)), token_tree (std::move (token_tree))
1820 {}
1821
1822 // Copy constructor with vector clone
1823 MacroInvocData (const MacroInvocData &other)
1824 : path (other.path), token_tree (other.token_tree),
1825 parsed_to_meta_item (other.parsed_to_meta_item)
1826 {
1827 parsed_items.reserve (other.parsed_items.size ());
1828 for (const auto &e : other.parsed_items)
1829 parsed_items.push_back (e->clone_meta_item_inner ());
1830 }
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 MacroInvocData (MacroInvocData &&other) = default;
1849 MacroInvocData &operator= (MacroInvocData &&other) = default;
1850
1851 // Invalid if path is empty, so base stripping on that.
1852 void mark_for_strip () { path = SimplePath::create_empty (); }
1853 bool is_marked_for_strip () const { return path.is_empty (); }
1854
1855 // Returns whether the macro has been parsed already.
1856 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 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 void set_delim_tok_tree (DelimTokenTree tree) { token_tree = tree; }
1865
1866 // TODO: this mutable getter seems kinda dodgy
1867 SimplePath &get_path () { return path; }
1868 const SimplePath &get_path () const { return path; }
1869
1870 void set_expander (MacroExpander *new_expander) { expander = new_expander; }
1871 MacroExpander *get_expander ()
1872 {
1873 rust_assert (expander);
1874 return expander;
1875 }
1876
1877 void
1878 set_meta_item_output (std::vector<std::unique_ptr<MetaItemInner>> new_items)
1879 {
1880 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 SingleASTNode (std::unique_ptr<Expr> expr)
1919 : kind (EXPRESSION), expr (std::move (expr))
1920 {}
1921
1922 SingleASTNode (std::unique_ptr<Item> item)
1923 : kind (ITEM), item (std::move (item))
1924 {}
1925
1926 SingleASTNode (std::unique_ptr<Stmt> stmt)
1927 : kind (STMT), stmt (std::move (stmt))
1928 {}
1929
1930 SingleASTNode (std::unique_ptr<ExternalItem> item)
1931 : kind (EXTERN), external_item (std::move (item))
1932 {}
1933
1934 SingleASTNode (std::unique_ptr<AssociatedItem> item)
1935 : kind (ASSOC_ITEM), assoc_item (std::move (item))
1936 {}
1937
1938 SingleASTNode (std::unique_ptr<Type> type)
1939 : kind (TYPE), type (std::move (type))
1940 {}
1941
1942 SingleASTNode (SingleASTNode const &other);
1943
1944 SingleASTNode operator= (SingleASTNode const &other);
1945
1946 SingleASTNode (SingleASTNode &&other) = default;
1947 SingleASTNode &operator= (SingleASTNode &&other) = default;
1948
1949 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 std::unique_ptr<Stmt> take_stmt ()
1975 {
1976 rust_assert (!is_error ());
1977 return std::move (stmt);
1978 }
1979
1980 std::unique_ptr<Expr> take_expr ()
1981 {
1982 rust_assert (!is_error ());
1983 return std::move (expr);
1984 }
1985
1986 std::unique_ptr<Item> take_item ()
1987 {
1988 rust_assert (!is_error ());
1989 return std::move (item);
1990 }
1991
1992 std::unique_ptr<ExternalItem> take_external_item ()
1993 {
1994 rust_assert (!is_error ());
1995 return std::move (external_item);
1996 }
1997
1998 std::unique_ptr<AssociatedItem> take_assoc_item ()
1999 {
2000 rust_assert (!is_error ());
2001 return std::move (assoc_item);
2002 }
2003
2004 std::unique_ptr<Type> take_type ()
2005 {
2006 rust_assert (!is_error ());
2007 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 Crate (std::vector<std::unique_ptr<Item>> items,
2031 std::vector<Attribute> inner_attrs)
2032 : inner_attrs (std::move (inner_attrs)), items (std::move (items)),
2033 node_id (Analysis::Mappings::get ().get_next_node_id ())
2034 {}
2035
2036 // Copy constructor with vector clone
2037 Crate (Crate const &other)
2038 : inner_attrs (other.inner_attrs), node_id (other.node_id)
2039 {
2040 items.reserve (other.items.size ());
2041 for (const auto &e : other.items)
2042 items.push_back (e->clone_item ());
2043 }
2044
2045 ~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 void strip_crate ()
2069 {
2070 inner_attrs.clear ();
2071 inner_attrs.shrink_to_fit ();
2072
2073 items.clear ();
2074 items.shrink_to_fit ();
2075 // TODO: is this the best way to do this?
2076 }
2077
2078 NodeId get_node_id () const { return node_id; }
2079 const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
2080 std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
2081
2082 std::vector<std::unique_ptr<AST::Item>> take_items ()
2083 {
2084 return std::move (items);
2085 }
2086
2087 void set_items (std::vector<std::unique_ptr<AST::Item>> &&new_items)
2088 {
2089 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 bool operator() (const Rust::Identifier &lhs,
2100 const Rust::Identifier &rhs) const
2101 {
2102 return lhs.as_string () < rhs.as_string ();
2103 }
2104 };
2105
2106 template <> struct hash<Rust::Identifier>
2107 {
2108 std::size_t operator() (const Rust::Identifier &k) const
2109 {
2110 using std::hash;
2111 using std::size_t;
2112 using std::string;
2113
2114 return hash<string> () (k.as_string ()) ^ (hash<int> () (k.get_locus ()));
2115 }
2116 };
2117
2118 } // namespace std
2119
2120 #endif