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