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