]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/rust/ast/rust-pattern.h
69dbd98a1d3224b1cf07fb9e9d4e17bdd7106322
[thirdparty/gcc.git] / gcc / rust / ast / rust-pattern.h
1 // Copyright (C) 2020-2025 Free Software Foundation, Inc.
2
3 // This file is part of GCC.
4
5 // GCC is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 3, or (at your option) any later
8 // version.
9
10 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 // for more details.
14
15 // You should have received a copy of the GNU General Public License
16 // along with GCC; see the file COPYING3. If not see
17 // <http://www.gnu.org/licenses/>.
18
19 #ifndef RUST_AST_PATTERN_H
20 #define RUST_AST_PATTERN_H
21
22 #include "rust-ast.h"
23
24 namespace Rust {
25 namespace AST {
26 // Literal pattern AST node (comparing to a literal)
27 class LiteralPattern : public Pattern
28 {
29 Literal lit;
30 location_t locus;
31 NodeId node_id;
32
33 public:
34 std::string as_string () const override;
35
36 // Constructor for a literal pattern
37 LiteralPattern (Literal lit, location_t locus)
38 : lit (std::move (lit)), locus (locus),
39 node_id (Analysis::Mappings::get ().get_next_node_id ())
40 {}
41
42 LiteralPattern (std::string val, Literal::LitType type, location_t locus,
43 PrimitiveCoreType type_hint)
44 : lit (Literal (std::move (val), type, type_hint)), locus (locus),
45 node_id (Analysis::Mappings::get ().get_next_node_id ())
46 {}
47
48 location_t get_locus () const override final { return locus; }
49
50 void accept_vis (ASTVisitor &vis) override;
51
52 NodeId get_node_id () const override { return node_id; }
53
54 Literal &get_literal () { return lit; }
55
56 const Literal &get_literal () const { return lit; }
57
58 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Literal; }
59
60 protected:
61 /* Use covariance to implement clone function as returning this object rather
62 * than base */
63 virtual LiteralPattern *clone_pattern_impl () const override
64 {
65 return new LiteralPattern (*this);
66 }
67 };
68
69 // Identifier pattern AST node (bind value matched to a variable)
70 class IdentifierPattern : public Pattern
71 {
72 Identifier variable_ident;
73 bool is_ref;
74 bool is_mut;
75
76 // bool has_pattern;
77 std::unique_ptr<Pattern> to_bind;
78 location_t locus;
79 NodeId node_id;
80
81 public:
82 std::string as_string () const override;
83
84 // Returns whether the IdentifierPattern has a pattern to bind.
85 bool has_pattern_to_bind () const { return to_bind != nullptr; }
86
87 // Constructor
88 IdentifierPattern (Identifier ident, location_t locus, bool is_ref = false,
89 bool is_mut = false,
90 std::unique_ptr<Pattern> to_bind = nullptr)
91 : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
92 is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus),
93 node_id (Analysis::Mappings::get ().get_next_node_id ())
94 {}
95
96 IdentifierPattern (NodeId node_id, Identifier ident, location_t locus,
97 bool is_ref = false, bool is_mut = false,
98 std::unique_ptr<Pattern> to_bind = nullptr)
99 : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
100 is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus),
101 node_id (node_id)
102 {}
103
104 // Copy constructor with clone
105 IdentifierPattern (IdentifierPattern const &other)
106 : variable_ident (other.variable_ident), is_ref (other.is_ref),
107 is_mut (other.is_mut), locus (other.locus), node_id (other.node_id)
108 {
109 // fix to get prevent null pointer dereference
110 if (other.to_bind != nullptr)
111 to_bind = other.to_bind->clone_pattern ();
112 }
113
114 // Overload assignment operator to use clone
115 IdentifierPattern &operator= (IdentifierPattern const &other)
116 {
117 variable_ident = other.variable_ident;
118 is_ref = other.is_ref;
119 is_mut = other.is_mut;
120 locus = other.locus;
121 node_id = other.node_id;
122
123 // fix to prevent null pointer dereference
124 if (other.to_bind != nullptr)
125 to_bind = other.to_bind->clone_pattern ();
126 else
127 to_bind = nullptr;
128
129 return *this;
130 }
131
132 // default move semantics
133 IdentifierPattern (IdentifierPattern &&other) = default;
134 IdentifierPattern &operator= (IdentifierPattern &&other) = default;
135
136 location_t get_locus () const override final { return locus; }
137
138 void accept_vis (ASTVisitor &vis) override;
139
140 // TODO: is this better? Or is a "vis_pattern" better?
141 Pattern &get_pattern_to_bind ()
142 {
143 rust_assert (has_pattern_to_bind ());
144 return *to_bind;
145 }
146
147 Identifier get_ident () const { return variable_ident; }
148
149 bool get_is_mut () const { return is_mut; }
150 bool get_is_ref () const { return is_ref; }
151
152 NodeId get_node_id () const override { return node_id; }
153
154 Pattern::Kind get_pattern_kind () override
155 {
156 return Pattern::Kind::Identifier;
157 }
158
159 protected:
160 /* Use covariance to implement clone function as returning this object rather
161 * than base */
162 IdentifierPattern *clone_pattern_impl () const override
163 {
164 return new IdentifierPattern (*this);
165 }
166 };
167
168 // AST node for using the '_' wildcard "match any value" pattern
169 class WildcardPattern : public Pattern
170 {
171 location_t locus;
172 NodeId node_id;
173
174 public:
175 std::string as_string () const override { return std::string (1, '_'); }
176
177 WildcardPattern (location_t locus)
178 : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
179 {}
180
181 location_t get_locus () const override final { return locus; }
182
183 void accept_vis (ASTVisitor &vis) override;
184
185 NodeId get_node_id () const override { return node_id; }
186
187 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Wildcard; }
188
189 protected:
190 /* Use covariance to implement clone function as returning this object rather
191 * than base */
192 WildcardPattern *clone_pattern_impl () const override
193 {
194 return new WildcardPattern (*this);
195 }
196 };
197
198 class RestPattern : public Pattern
199 {
200 location_t locus;
201 NodeId node_id;
202
203 public:
204 std::string as_string () const override { return ".."; }
205
206 RestPattern (location_t locus)
207 : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
208 {}
209
210 location_t get_locus () const override final { return locus; }
211
212 void accept_vis (ASTVisitor &vis) override;
213
214 NodeId get_node_id () const override final { return node_id; }
215
216 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Rest; }
217
218 protected:
219 RestPattern *clone_pattern_impl () const override
220 {
221 return new RestPattern (*this);
222 }
223 };
224
225 // Base range pattern bound (lower or upper limit) - abstract
226 class RangePatternBound
227 {
228 public:
229 enum RangePatternBoundType
230 {
231 LITERAL,
232 PATH,
233 QUALPATH
234 };
235
236 virtual ~RangePatternBound () {}
237
238 // Unique pointer custom clone function
239 std::unique_ptr<RangePatternBound> clone_range_pattern_bound () const
240 {
241 return std::unique_ptr<RangePatternBound> (
242 clone_range_pattern_bound_impl ());
243 }
244
245 virtual std::string as_string () const = 0;
246
247 virtual void accept_vis (ASTVisitor &vis) = 0;
248
249 virtual RangePatternBoundType get_bound_type () const = 0;
250
251 protected:
252 // pure virtual as RangePatternBound is abstract
253 virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0;
254 };
255
256 // Literal-based pattern bound
257 class RangePatternBoundLiteral : public RangePatternBound
258 {
259 Literal literal;
260 /* Can only be a char, byte, int, or float literal - same impl here as
261 * previously */
262
263 // Minus prefixed to literal (if integer or floating-point)
264 bool has_minus;
265
266 location_t locus;
267
268 public:
269 // Constructor
270 RangePatternBoundLiteral (Literal literal, location_t locus,
271 bool has_minus = false)
272 : literal (literal), has_minus (has_minus), locus (locus)
273 {}
274
275 std::string as_string () const override;
276
277 Literal get_literal () const { return literal; }
278
279 bool get_has_minus () const { return has_minus; }
280
281 location_t get_locus () const { return locus; }
282
283 void accept_vis (ASTVisitor &vis) override;
284
285 RangePatternBoundType get_bound_type () const override
286 {
287 return RangePatternBoundType::LITERAL;
288 }
289
290 protected:
291 /* Use covariance to implement clone function as returning this object rather
292 * than base */
293 RangePatternBoundLiteral *clone_range_pattern_bound_impl () const override
294 {
295 return new RangePatternBoundLiteral (*this);
296 }
297 };
298
299 // Path-based pattern bound
300 class RangePatternBoundPath : public RangePatternBound
301 {
302 PathInExpression path;
303
304 /* TODO: should this be refactored so that PathInExpression is a subclass of
305 * RangePatternBound? */
306
307 public:
308 RangePatternBoundPath (PathInExpression path) : path (std::move (path)) {}
309
310 std::string as_string () const override { return path.as_string (); }
311
312 location_t get_locus () const { return path.get_locus (); }
313
314 void accept_vis (ASTVisitor &vis) override;
315
316 // TODO: this mutable getter seems kinda dodgy
317 PathInExpression &get_path () { return path; }
318 const PathInExpression &get_path () const { return path; }
319
320 RangePatternBoundType get_bound_type () const override
321 {
322 return RangePatternBoundType::PATH;
323 }
324
325 protected:
326 /* Use covariance to implement clone function as returning this object rather
327 * than base */
328 RangePatternBoundPath *clone_range_pattern_bound_impl () const override
329 {
330 return new RangePatternBoundPath (*this);
331 }
332 };
333
334 // Qualified path-based pattern bound
335 class RangePatternBoundQualPath : public RangePatternBound
336 {
337 QualifiedPathInExpression path;
338
339 /* TODO: should this be refactored so that QualifiedPathInExpression is a
340 * subclass of RangePatternBound? */
341
342 public:
343 RangePatternBoundQualPath (QualifiedPathInExpression path)
344 : path (std::move (path))
345 {}
346
347 std::string as_string () const override { return path.as_string (); }
348
349 location_t get_locus () const { return path.get_locus (); }
350
351 void accept_vis (ASTVisitor &vis) override;
352
353 // TODO: this mutable getter seems kinda dodgy
354 QualifiedPathInExpression &get_qualified_path () { return path; }
355 const QualifiedPathInExpression &get_qualified_path () const { return path; }
356
357 RangePatternBoundType get_bound_type () const override
358 {
359 return RangePatternBoundType::QUALPATH;
360 }
361
362 protected:
363 /* Use covariance to implement clone function as returning this object rather
364 * than base */
365 RangePatternBoundQualPath *clone_range_pattern_bound_impl () const override
366 {
367 return new RangePatternBoundQualPath (*this);
368 }
369 };
370
371 enum class RangeKind
372 {
373 INCLUDED,
374 ELLIPSIS,
375 EXCLUDED,
376 };
377
378 RangeKind
379 tokenid_to_rangekind (TokenId id);
380 // AST node for matching within a certain range (range pattern)
381 class RangePattern : public Pattern
382 {
383 std::unique_ptr<RangePatternBound> lower;
384 std::unique_ptr<RangePatternBound> upper;
385
386 RangeKind range_kind;
387
388 /* location only stored to avoid a dereference - lower pattern should give
389 * correct location so maybe change in future */
390 location_t locus;
391 NodeId node_id;
392
393 public:
394 std::string as_string () const override;
395
396 // Constructor
397 RangePattern (std::unique_ptr<RangePatternBound> lower,
398 std::unique_ptr<RangePatternBound> upper, RangeKind range_kind,
399 location_t locus)
400 : lower (std::move (lower)), upper (std::move (upper)),
401 range_kind (range_kind), locus (locus),
402 node_id (Analysis::Mappings::get ().get_next_node_id ())
403 {}
404
405 // Copy constructor with clone
406 RangePattern (RangePattern const &other)
407 : lower (other.lower->clone_range_pattern_bound ()),
408 upper (other.upper->clone_range_pattern_bound ()),
409 range_kind (other.range_kind), locus (other.locus),
410 node_id (other.node_id)
411 {}
412
413 // Overloaded assignment operator to clone
414 RangePattern &operator= (RangePattern const &other)
415 {
416 lower = other.lower->clone_range_pattern_bound ();
417 upper = other.upper->clone_range_pattern_bound ();
418 range_kind = other.range_kind;
419 locus = other.locus;
420 node_id = other.node_id;
421
422 return *this;
423 }
424
425 // default move semantics
426 RangePattern (RangePattern &&other) = default;
427 RangePattern &operator= (RangePattern &&other) = default;
428
429 location_t get_locus () const override final { return locus; }
430
431 bool get_has_ellipsis_syntax () const
432 {
433 return range_kind == RangeKind::ELLIPSIS;
434 }
435
436 RangeKind get_range_kind () const { return range_kind; }
437
438 bool get_has_lower_bound () const { return lower != nullptr; }
439
440 bool get_has_upper_bound () const { return upper != nullptr; }
441
442 void accept_vis (ASTVisitor &vis) override;
443
444 // TODO: is this better? or is a "vis_bound" better?
445 RangePatternBound &get_lower_bound ()
446 {
447 rust_assert (lower != nullptr);
448 return *lower;
449 }
450
451 RangePatternBound &get_upper_bound ()
452 {
453 rust_assert (upper != nullptr);
454 return *upper;
455 }
456
457 NodeId get_node_id () const override { return node_id; }
458
459 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Range; }
460
461 protected:
462 /* Use covariance to implement clone function as returning this object rather
463 * than base */
464 RangePattern *clone_pattern_impl () const override
465 {
466 return new RangePattern (*this);
467 }
468 };
469
470 // AST node for pattern based on dereferencing the pointers given
471 class ReferencePattern : public Pattern
472 {
473 bool has_two_amps;
474 bool is_mut;
475 std::unique_ptr<Pattern> pattern;
476 location_t locus;
477 NodeId node_id;
478
479 public:
480 std::string as_string () const override;
481
482 ReferencePattern (std::unique_ptr<Pattern> pattern, bool is_mut_reference,
483 bool ref_has_two_amps, location_t locus)
484 : has_two_amps (ref_has_two_amps), is_mut (is_mut_reference),
485 pattern (std::move (pattern)), locus (locus),
486 node_id (Analysis::Mappings::get ().get_next_node_id ())
487 {}
488
489 // Copy constructor requires clone
490 ReferencePattern (ReferencePattern const &other)
491 : has_two_amps (other.has_two_amps), is_mut (other.is_mut),
492 pattern (other.pattern->clone_pattern ()), locus (other.locus),
493 node_id (other.node_id)
494 {}
495
496 // Overload assignment operator to clone
497 ReferencePattern &operator= (ReferencePattern const &other)
498 {
499 pattern = other.pattern->clone_pattern ();
500 is_mut = other.is_mut;
501 has_two_amps = other.has_two_amps;
502 locus = other.locus;
503 node_id = other.node_id;
504
505 return *this;
506 }
507
508 // default move semantics
509 ReferencePattern (ReferencePattern &&other) = default;
510 ReferencePattern &operator= (ReferencePattern &&other) = default;
511
512 location_t get_locus () const override final { return locus; }
513
514 void accept_vis (ASTVisitor &vis) override;
515
516 // TODO: is this better? Or is a "vis_pattern" better?
517 Pattern &get_referenced_pattern ()
518 {
519 rust_assert (pattern != nullptr);
520 return *pattern;
521 }
522
523 bool is_double_reference () const { return has_two_amps; }
524
525 bool get_is_mut () const { return is_mut; }
526
527 NodeId get_node_id () const override { return node_id; }
528
529 Pattern::Kind get_pattern_kind () override
530 {
531 return Pattern::Kind::Reference;
532 }
533
534 protected:
535 /* Use covariance to implement clone function as returning this object rather
536 * than base */
537 ReferencePattern *clone_pattern_impl () const override
538 {
539 return new ReferencePattern (*this);
540 }
541 };
542
543 #if 0
544 // aka StructPatternEtCetera; potential element in struct pattern
545 struct StructPatternEtc
546 {
547 private:
548 std::vector<Attribute> outer_attrs;
549
550 // should this store location data?
551
552 public:
553 StructPatternEtc (std::vector<Attribute> outer_attribs)
554 : outer_attrs (std::move (outer_attribs))
555 {}
556
557 // Creates an empty StructPatternEtc
558 static StructPatternEtc create_empty ()
559 {
560 return StructPatternEtc (std::vector<Attribute> ());
561 }
562 };
563 #endif
564
565 // Base class for a single field in a struct pattern - abstract
566 class StructPatternField
567 {
568 std::vector<Attribute> outer_attrs;
569 location_t locus;
570
571 protected:
572 NodeId node_id;
573
574 public:
575 enum ItemType
576 {
577 TUPLE_PAT,
578 IDENT_PAT,
579 IDENT
580 };
581
582 virtual ~StructPatternField () {}
583
584 // Unique pointer custom clone function
585 std::unique_ptr<StructPatternField> clone_struct_pattern_field () const
586 {
587 return std::unique_ptr<StructPatternField> (
588 clone_struct_pattern_field_impl ());
589 }
590
591 virtual std::string as_string () const;
592
593 location_t get_locus () const { return locus; }
594
595 virtual void accept_vis (ASTVisitor &vis) = 0;
596
597 virtual void mark_for_strip () = 0;
598 virtual bool is_marked_for_strip () const = 0;
599 virtual ItemType get_item_type () const = 0;
600
601 NodeId get_node_id () const { return node_id; }
602
603 // TODO: seems kinda dodgy. Think of better way.
604 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
605 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
606
607 protected:
608 StructPatternField (std::vector<Attribute> outer_attribs, location_t locus,
609 NodeId node_id)
610 : outer_attrs (std::move (outer_attribs)), locus (locus), node_id (node_id)
611 {}
612
613 // Clone function implementation as pure virtual method
614 virtual StructPatternField *clone_struct_pattern_field_impl () const = 0;
615 };
616
617 // Tuple pattern single field in a struct pattern
618 class StructPatternFieldTuplePat : public StructPatternField
619 {
620 TupleIndex index;
621 std::unique_ptr<Pattern> tuple_pattern;
622
623 public:
624 StructPatternFieldTuplePat (TupleIndex index,
625 std::unique_ptr<Pattern> tuple_pattern,
626 std::vector<Attribute> outer_attribs,
627 location_t locus)
628 : StructPatternField (std::move (outer_attribs), locus,
629 Analysis::Mappings::get ().get_next_node_id ()),
630 index (index), tuple_pattern (std::move (tuple_pattern))
631 {}
632
633 // Copy constructor requires clone
634 StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other)
635 : StructPatternField (other), index (other.index)
636 {
637 // guard to prevent null dereference (only required if error state)
638 node_id = other.get_node_id ();
639 if (other.tuple_pattern != nullptr)
640 tuple_pattern = other.tuple_pattern->clone_pattern ();
641 }
642
643 // Overload assignment operator to perform clone
644 StructPatternFieldTuplePat &
645 operator= (StructPatternFieldTuplePat const &other)
646 {
647 StructPatternField::operator= (other);
648 index = other.index;
649 // outer_attrs = other.outer_attrs;
650 node_id = other.get_node_id ();
651
652 // guard to prevent null dereference (only required if error state)
653 if (other.tuple_pattern != nullptr)
654 tuple_pattern = other.tuple_pattern->clone_pattern ();
655 else
656 tuple_pattern = nullptr;
657
658 return *this;
659 }
660
661 // default move semantics
662 StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default;
663 StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other)
664 = default;
665
666 std::string as_string () const override;
667
668 void accept_vis (ASTVisitor &vis) override;
669
670 // based on idea of tuple pattern no longer existing
671 void mark_for_strip () override { tuple_pattern = nullptr; }
672 bool is_marked_for_strip () const override
673 {
674 return tuple_pattern == nullptr;
675 }
676
677 TupleIndex get_index () { return index; }
678
679 // TODO: is this better? Or is a "vis_pattern" better?
680 Pattern &get_index_pattern ()
681 {
682 rust_assert (tuple_pattern != nullptr);
683 return *tuple_pattern;
684 }
685
686 ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; }
687
688 protected:
689 /* Use covariance to implement clone function as returning this object rather
690 * than base */
691 StructPatternFieldTuplePat *clone_struct_pattern_field_impl () const override
692 {
693 return new StructPatternFieldTuplePat (*this);
694 }
695 };
696
697 // Identifier pattern single field in a struct pattern
698 class StructPatternFieldIdentPat : public StructPatternField
699 {
700 Identifier ident;
701 std::unique_ptr<Pattern> ident_pattern;
702
703 public:
704 StructPatternFieldIdentPat (Identifier ident,
705 std::unique_ptr<Pattern> ident_pattern,
706 std::vector<Attribute> outer_attrs,
707 location_t locus)
708 : StructPatternField (std::move (outer_attrs), locus,
709 Analysis::Mappings::get ().get_next_node_id ()),
710 ident (std::move (ident)), ident_pattern (std::move (ident_pattern))
711 {}
712
713 // Copy constructor requires clone
714 StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other)
715 : StructPatternField (other), ident (other.ident)
716 {
717 // guard to prevent null dereference (only required if error state)
718 node_id = other.get_node_id ();
719 if (other.ident_pattern != nullptr)
720 ident_pattern = other.ident_pattern->clone_pattern ();
721 }
722
723 // Overload assignment operator to clone
724 StructPatternFieldIdentPat &
725 operator= (StructPatternFieldIdentPat const &other)
726 {
727 StructPatternField::operator= (other);
728 ident = other.ident;
729 // outer_attrs = other.outer_attrs;
730 node_id = other.get_node_id ();
731
732 // guard to prevent null dereference (only required if error state)
733 if (other.ident_pattern != nullptr)
734 ident_pattern = other.ident_pattern->clone_pattern ();
735 else
736 ident_pattern = nullptr;
737
738 return *this;
739 }
740
741 // default move semantics
742 StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default;
743 StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other)
744 = default;
745
746 std::string as_string () const override;
747
748 void accept_vis (ASTVisitor &vis) override;
749
750 // based on idea of identifier pattern no longer existing
751 void mark_for_strip () override { ident_pattern = nullptr; }
752 bool is_marked_for_strip () const override
753 {
754 return ident_pattern == nullptr;
755 }
756
757 const Identifier &get_identifier () const { return ident; }
758
759 // TODO: is this better? Or is a "vis_pattern" better?
760 Pattern &get_ident_pattern ()
761 {
762 rust_assert (ident_pattern != nullptr);
763 return *ident_pattern;
764 }
765
766 ItemType get_item_type () const override final { return ItemType::IDENT_PAT; }
767
768 protected:
769 /* Use covariance to implement clone function as returning this object rather
770 * than base */
771 StructPatternFieldIdentPat *clone_struct_pattern_field_impl () const override
772 {
773 return new StructPatternFieldIdentPat (*this);
774 }
775 };
776
777 // Identifier only (with no pattern) single field in a struct pattern
778 class StructPatternFieldIdent : public StructPatternField
779 {
780 bool has_ref;
781 bool has_mut;
782 Identifier ident;
783
784 public:
785 StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut,
786 std::vector<Attribute> outer_attrs, location_t locus)
787 : StructPatternField (std::move (outer_attrs), locus,
788 Analysis::Mappings::get ().get_next_node_id ()),
789 has_ref (is_ref), has_mut (is_mut), ident (std::move (ident))
790 {}
791
792 std::string as_string () const override;
793
794 void accept_vis (ASTVisitor &vis) override;
795
796 // based on idea of identifier no longer existing
797 void mark_for_strip () override { ident = {""}; }
798 bool is_marked_for_strip () const override { return ident.empty (); }
799
800 const Identifier &get_identifier () const { return ident; }
801
802 ItemType get_item_type () const override final { return ItemType::IDENT; }
803
804 bool is_ref () const { return has_ref; }
805
806 bool is_mut () const { return has_mut; }
807
808 protected:
809 /* Use covariance to implement clone function as returning this object rather
810 * than base */
811 StructPatternFieldIdent *clone_struct_pattern_field_impl () const override
812 {
813 return new StructPatternFieldIdent (*this);
814 }
815 };
816
817 // Elements of a struct pattern
818 class StructPatternElements
819 {
820 // bool has_struct_pattern_fields;
821 std::vector<std::unique_ptr<StructPatternField>> fields;
822
823 bool has_struct_pattern_etc;
824 std::vector<Attribute> struct_pattern_etc_attrs;
825 // StructPatternEtc etc;
826
827 // must have at least one of the two and maybe both
828
829 // should this store location data?
830
831 public:
832 // Returns whether there are any struct pattern fields
833 bool has_struct_pattern_fields () const { return !fields.empty (); }
834
835 /* Returns whether the struct pattern elements is entirely empty (no fields,
836 * no etc). */
837 bool is_empty () const
838 {
839 return !has_struct_pattern_fields () && !has_struct_pattern_etc;
840 }
841
842 bool has_etc () const { return has_struct_pattern_etc; }
843
844 // Constructor for StructPatternElements with both (potentially)
845 StructPatternElements (
846 std::vector<std::unique_ptr<StructPatternField>> fields,
847 std::vector<Attribute> etc_attrs)
848 : fields (std::move (fields)), has_struct_pattern_etc (true),
849 struct_pattern_etc_attrs (std::move (etc_attrs))
850 {}
851
852 // Constructor for StructPatternElements with no StructPatternEtc
853 StructPatternElements (
854 std::vector<std::unique_ptr<StructPatternField>> fields)
855 : fields (std::move (fields)), has_struct_pattern_etc (false),
856 struct_pattern_etc_attrs ()
857 {}
858
859 // Copy constructor with vector clone
860 StructPatternElements (StructPatternElements const &other)
861 : has_struct_pattern_etc (other.has_struct_pattern_etc),
862 struct_pattern_etc_attrs (other.struct_pattern_etc_attrs)
863 {
864 fields.reserve (other.fields.size ());
865 for (const auto &e : other.fields)
866 fields.push_back (e->clone_struct_pattern_field ());
867 }
868
869 // Overloaded assignment operator with vector clone
870 StructPatternElements &operator= (StructPatternElements const &other)
871 {
872 struct_pattern_etc_attrs = other.struct_pattern_etc_attrs;
873 has_struct_pattern_etc = other.has_struct_pattern_etc;
874
875 fields.clear ();
876 fields.reserve (other.fields.size ());
877 for (const auto &e : other.fields)
878 fields.push_back (e->clone_struct_pattern_field ());
879
880 return *this;
881 }
882
883 // move constructors
884 StructPatternElements (StructPatternElements &&other) = default;
885 StructPatternElements &operator= (StructPatternElements &&other) = default;
886
887 // Creates an empty StructPatternElements
888 static StructPatternElements create_empty ()
889 {
890 return StructPatternElements (
891 std::vector<std::unique_ptr<StructPatternField>> ());
892 }
893
894 std::string as_string () const;
895
896 // TODO: seems kinda dodgy. Think of better way.
897 std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields ()
898 {
899 return fields;
900 }
901 const std::vector<std::unique_ptr<StructPatternField>> &
902 get_struct_pattern_fields () const
903 {
904 return fields;
905 }
906
907 std::vector<Attribute> &get_etc_outer_attrs ()
908 {
909 return struct_pattern_etc_attrs;
910 }
911 const std::vector<Attribute> &get_etc_outer_attrs () const
912 {
913 return struct_pattern_etc_attrs;
914 }
915
916 void strip_etc ()
917 {
918 has_struct_pattern_etc = false;
919 struct_pattern_etc_attrs.clear ();
920 struct_pattern_etc_attrs.shrink_to_fit ();
921 }
922 };
923
924 // Struct pattern AST node representation
925 class StructPattern : public Pattern
926 {
927 PathInExpression path;
928
929 // bool has_struct_pattern_elements;
930 StructPatternElements elems;
931
932 NodeId node_id;
933 location_t locus;
934
935 public:
936 std::string as_string () const override;
937
938 // Constructs a struct pattern from specified StructPatternElements
939 StructPattern (PathInExpression struct_path, location_t locus,
940 StructPatternElements elems
941 = StructPatternElements::create_empty ())
942 : path (std::move (struct_path)), elems (std::move (elems)),
943 node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
944 {}
945
946 /* TODO: constructor to construct via elements included in
947 * StructPatternElements */
948
949 /* Returns whether struct pattern has any struct pattern elements (if not, it
950 * is empty). */
951 bool has_struct_pattern_elems () const { return !elems.is_empty (); }
952
953 location_t get_locus () const override { return path.get_locus (); }
954
955 void accept_vis (ASTVisitor &vis) override;
956
957 // TODO: seems kinda dodgy. Think of better way.
958 StructPatternElements &get_struct_pattern_elems () { return elems; }
959 const StructPatternElements &get_struct_pattern_elems () const
960 {
961 return elems;
962 }
963
964 PathInExpression &get_path () { return path; }
965 const PathInExpression &get_path () const { return path; }
966
967 NodeId get_node_id () const override { return node_id; }
968
969 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Struct; }
970
971 protected:
972 /* Use covariance to implement clone function as returning this object rather
973 * than base */
974 StructPattern *clone_pattern_impl () const override
975 {
976 return new StructPattern (*this);
977 }
978 };
979
980 // Base abstract class for patterns used in TupleStructPattern
981 class TupleStructItems
982 {
983 public:
984 enum ItemType
985 {
986 RANGE,
987 NO_RANGE
988 };
989
990 virtual ~TupleStructItems () {}
991
992 // TODO: should this store location data?
993
994 // Unique pointer custom clone function
995 std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
996 {
997 return std::unique_ptr<TupleStructItems> (clone_tuple_struct_items_impl ());
998 }
999
1000 virtual std::string as_string () const = 0;
1001
1002 virtual void accept_vis (ASTVisitor &vis) = 0;
1003
1004 virtual ItemType get_item_type () const = 0;
1005
1006 protected:
1007 // pure virtual clone implementation
1008 virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0;
1009 };
1010
1011 // Class for non-ranged tuple struct pattern patterns
1012 class TupleStructItemsNoRange : public TupleStructItems
1013 {
1014 std::vector<std::unique_ptr<Pattern>> patterns;
1015
1016 public:
1017 TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns)
1018 : patterns (std::move (patterns))
1019 {}
1020
1021 // Copy constructor with vector clone
1022 TupleStructItemsNoRange (TupleStructItemsNoRange const &other)
1023 {
1024 patterns.reserve (other.patterns.size ());
1025 for (const auto &e : other.patterns)
1026 patterns.push_back (e->clone_pattern ());
1027 }
1028
1029 // Overloaded assignment operator with vector clone
1030 TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other)
1031 {
1032 patterns.clear ();
1033 patterns.reserve (other.patterns.size ());
1034 for (const auto &e : other.patterns)
1035 patterns.push_back (e->clone_pattern ());
1036
1037 return *this;
1038 }
1039
1040 // move constructors
1041 TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default;
1042 TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other)
1043 = default;
1044
1045 std::string as_string () const override;
1046
1047 void accept_vis (ASTVisitor &vis) override;
1048
1049 // TODO: seems kinda dodgy. Think of better way.
1050 std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
1051 const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
1052 {
1053 return patterns;
1054 }
1055
1056 ItemType get_item_type () const override final { return ItemType::NO_RANGE; }
1057
1058 protected:
1059 /* Use covariance to implement clone function as returning this object rather
1060 * than base */
1061 TupleStructItemsNoRange *clone_tuple_struct_items_impl () const override
1062 {
1063 return new TupleStructItemsNoRange (*this);
1064 }
1065 };
1066
1067 // Class for ranged tuple struct pattern patterns
1068 class TupleStructItemsRange : public TupleStructItems
1069 {
1070 std::vector<std::unique_ptr<Pattern>> lower_patterns;
1071 std::vector<std::unique_ptr<Pattern>> upper_patterns;
1072
1073 public:
1074 TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns,
1075 std::vector<std::unique_ptr<Pattern>> upper_patterns)
1076 : lower_patterns (std::move (lower_patterns)),
1077 upper_patterns (std::move (upper_patterns))
1078 {}
1079
1080 // Copy constructor with vector clone
1081 TupleStructItemsRange (TupleStructItemsRange const &other)
1082 {
1083 lower_patterns.reserve (other.lower_patterns.size ());
1084 for (const auto &e : other.lower_patterns)
1085 lower_patterns.push_back (e->clone_pattern ());
1086
1087 upper_patterns.reserve (other.upper_patterns.size ());
1088 for (const auto &e : other.upper_patterns)
1089 upper_patterns.push_back (e->clone_pattern ());
1090 }
1091
1092 // Overloaded assignment operator to clone
1093 TupleStructItemsRange &operator= (TupleStructItemsRange const &other)
1094 {
1095 lower_patterns.clear ();
1096 lower_patterns.reserve (other.lower_patterns.size ());
1097 for (const auto &e : other.lower_patterns)
1098 lower_patterns.push_back (e->clone_pattern ());
1099
1100 upper_patterns.clear ();
1101 upper_patterns.reserve (other.upper_patterns.size ());
1102 for (const auto &e : other.upper_patterns)
1103 upper_patterns.push_back (e->clone_pattern ());
1104
1105 return *this;
1106 }
1107
1108 // move constructors
1109 TupleStructItemsRange (TupleStructItemsRange &&other) = default;
1110 TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default;
1111
1112 std::string as_string () const override;
1113
1114 void accept_vis (ASTVisitor &vis) override;
1115
1116 // TODO: seems kinda dodgy. Think of better way.
1117 std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
1118 {
1119 return lower_patterns;
1120 }
1121 const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
1122 {
1123 return lower_patterns;
1124 }
1125
1126 // TODO: seems kinda dodgy. Think of better way.
1127 std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
1128 {
1129 return upper_patterns;
1130 }
1131 const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
1132 {
1133 return upper_patterns;
1134 }
1135
1136 ItemType get_item_type () const override final { return ItemType::RANGE; }
1137
1138 protected:
1139 /* Use covariance to implement clone function as returning this object rather
1140 * than base */
1141 TupleStructItemsRange *clone_tuple_struct_items_impl () const override
1142 {
1143 return new TupleStructItemsRange (*this);
1144 }
1145 };
1146
1147 // AST node representing a tuple struct pattern
1148 class TupleStructPattern : public Pattern
1149 {
1150 PathInExpression path;
1151 std::unique_ptr<TupleStructItems> items;
1152 NodeId node_id;
1153
1154 /* TOOD: should this store location data? current accessor uses path location
1155 * data */
1156
1157 public:
1158 std::string as_string () const override;
1159
1160 TupleStructPattern (PathInExpression tuple_struct_path,
1161 std::unique_ptr<TupleStructItems> items)
1162 : path (std::move (tuple_struct_path)), items (std::move (items)),
1163 node_id (Analysis::Mappings::get ().get_next_node_id ())
1164 {
1165 rust_assert (this->items != nullptr);
1166 }
1167
1168 // Copy constructor required to clone
1169 TupleStructPattern (TupleStructPattern const &other) : path (other.path)
1170 {
1171 // guard to protect from null dereference
1172 rust_assert (other.items != nullptr);
1173
1174 node_id = other.node_id;
1175 items = other.items->clone_tuple_struct_items ();
1176 }
1177
1178 // Operator overload assignment operator to clone
1179 TupleStructPattern &operator= (TupleStructPattern const &other)
1180 {
1181 path = other.path;
1182 node_id = other.node_id;
1183
1184 // guard to protect from null dereference
1185 rust_assert (other.items != nullptr);
1186
1187 items = other.items->clone_tuple_struct_items ();
1188
1189 return *this;
1190 }
1191
1192 // move constructors
1193 TupleStructPattern (TupleStructPattern &&other) = default;
1194 TupleStructPattern &operator= (TupleStructPattern &&other) = default;
1195
1196 location_t get_locus () const override { return path.get_locus (); }
1197
1198 void accept_vis (ASTVisitor &vis) override;
1199
1200 TupleStructItems &get_items ()
1201 {
1202 rust_assert (items != nullptr);
1203 return *items;
1204 }
1205
1206 PathInExpression &get_path () { return path; }
1207 const PathInExpression &get_path () const { return path; }
1208
1209 NodeId get_node_id () const override { return node_id; }
1210
1211 Pattern::Kind get_pattern_kind () override
1212 {
1213 return Pattern::Kind::TupleStruct;
1214 }
1215
1216 protected:
1217 /* Use covariance to implement clone function as returning this object rather
1218 * than base */
1219 TupleStructPattern *clone_pattern_impl () const override
1220 {
1221 return new TupleStructPattern (*this);
1222 }
1223 };
1224
1225 // Base abstract class representing TuplePattern patterns
1226 class TuplePatternItems
1227 {
1228 public:
1229 enum TuplePatternItemType
1230 {
1231 MULTIPLE,
1232 RANGED,
1233 };
1234
1235 virtual ~TuplePatternItems () {}
1236
1237 // TODO: should this store location data?
1238
1239 // Unique pointer custom clone function
1240 std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const
1241 {
1242 return std::unique_ptr<TuplePatternItems> (
1243 clone_tuple_pattern_items_impl ());
1244 }
1245
1246 virtual std::string as_string () const = 0;
1247
1248 virtual void accept_vis (ASTVisitor &vis) = 0;
1249
1250 virtual TuplePatternItemType get_pattern_type () const = 0;
1251
1252 protected:
1253 // pure virtual clone implementation
1254 virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0;
1255 };
1256
1257 // Class representing TuplePattern patterns where there are multiple patterns
1258 class TuplePatternItemsMultiple : public TuplePatternItems
1259 {
1260 std::vector<std::unique_ptr<Pattern>> patterns;
1261
1262 public:
1263 TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns)
1264 : patterns (std::move (patterns))
1265 {}
1266
1267 // Copy constructor with vector clone
1268 TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other)
1269 {
1270 patterns.reserve (other.patterns.size ());
1271 for (const auto &e : other.patterns)
1272 patterns.push_back (e->clone_pattern ());
1273 }
1274
1275 // Overloaded assignment operator to vector clone
1276 TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other)
1277 {
1278 patterns.clear ();
1279 patterns.reserve (other.patterns.size ());
1280 for (const auto &e : other.patterns)
1281 patterns.push_back (e->clone_pattern ());
1282
1283 return *this;
1284 }
1285
1286 // move constructors
1287 TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default;
1288 TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other)
1289 = default;
1290
1291 std::string as_string () const override;
1292
1293 void accept_vis (ASTVisitor &vis) override;
1294
1295 // TODO: seems kinda dodgy. Think of better way.
1296 std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
1297 const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
1298 {
1299 return patterns;
1300 }
1301
1302 TuplePatternItemType get_pattern_type () const override
1303 {
1304 return TuplePatternItemType::MULTIPLE;
1305 }
1306
1307 protected:
1308 /* Use covariance to implement clone function as returning this object rather
1309 * than base */
1310 TuplePatternItemsMultiple *clone_tuple_pattern_items_impl () const override
1311 {
1312 return new TuplePatternItemsMultiple (*this);
1313 }
1314 };
1315
1316 // Class representing TuplePattern patterns where there are a range of patterns
1317 class TuplePatternItemsRanged : public TuplePatternItems
1318 {
1319 std::vector<std::unique_ptr<Pattern>> lower_patterns;
1320 std::vector<std::unique_ptr<Pattern>> upper_patterns;
1321
1322 public:
1323 TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns,
1324 std::vector<std::unique_ptr<Pattern>> upper_patterns)
1325 : lower_patterns (std::move (lower_patterns)),
1326 upper_patterns (std::move (upper_patterns))
1327 {}
1328
1329 // Copy constructor with vector clone
1330 TuplePatternItemsRanged (TuplePatternItemsRanged const &other)
1331 {
1332 lower_patterns.reserve (other.lower_patterns.size ());
1333 for (const auto &e : other.lower_patterns)
1334 lower_patterns.push_back (e->clone_pattern ());
1335
1336 upper_patterns.reserve (other.upper_patterns.size ());
1337 for (const auto &e : other.upper_patterns)
1338 upper_patterns.push_back (e->clone_pattern ());
1339 }
1340
1341 // Overloaded assignment operator to clone
1342 TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other)
1343 {
1344 lower_patterns.clear ();
1345 lower_patterns.reserve (other.lower_patterns.size ());
1346 for (const auto &e : other.lower_patterns)
1347 lower_patterns.push_back (e->clone_pattern ());
1348
1349 upper_patterns.clear ();
1350 upper_patterns.reserve (other.upper_patterns.size ());
1351 for (const auto &e : other.upper_patterns)
1352 upper_patterns.push_back (e->clone_pattern ());
1353
1354 return *this;
1355 }
1356
1357 // move constructors
1358 TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default;
1359 TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other)
1360 = default;
1361
1362 std::string as_string () const override;
1363
1364 void accept_vis (ASTVisitor &vis) override;
1365
1366 // TODO: seems kinda dodgy. Think of better way.
1367 std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
1368 {
1369 return lower_patterns;
1370 }
1371 const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
1372 {
1373 return lower_patterns;
1374 }
1375
1376 // TODO: seems kinda dodgy. Think of better way.
1377 std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
1378 {
1379 return upper_patterns;
1380 }
1381 const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
1382 {
1383 return upper_patterns;
1384 }
1385
1386 TuplePatternItemType get_pattern_type () const override
1387 {
1388 return TuplePatternItemType::RANGED;
1389 }
1390
1391 protected:
1392 /* Use covariance to implement clone function as returning this object rather
1393 * than base */
1394 TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override
1395 {
1396 return new TuplePatternItemsRanged (*this);
1397 }
1398 };
1399
1400 // AST node representing a tuple pattern
1401 class TuplePattern : public Pattern
1402 {
1403 std::unique_ptr<TuplePatternItems> items;
1404 location_t locus;
1405 NodeId node_id;
1406
1407 public:
1408 std::string as_string () const override;
1409
1410 TuplePattern (std::unique_ptr<TuplePatternItems> items, location_t locus)
1411 : items (std::move (items)), locus (locus),
1412 node_id (Analysis::Mappings::get ().get_next_node_id ())
1413 {
1414 rust_assert (this->items != nullptr);
1415 }
1416
1417 // Copy constructor requires clone
1418 TuplePattern (TuplePattern const &other) : locus (other.locus)
1419 {
1420 // guard to prevent null dereference
1421 rust_assert (other.items != nullptr);
1422
1423 node_id = other.node_id;
1424 items = other.items->clone_tuple_pattern_items ();
1425 }
1426
1427 // Overload assignment operator to clone
1428 TuplePattern &operator= (TuplePattern const &other)
1429 {
1430 locus = other.locus;
1431 node_id = other.node_id;
1432
1433 // guard to prevent null dereference
1434 rust_assert (other.items != nullptr);
1435
1436 items = other.items->clone_tuple_pattern_items ();
1437 return *this;
1438 }
1439
1440 location_t get_locus () const override final { return locus; }
1441
1442 void accept_vis (ASTVisitor &vis) override;
1443
1444 // TODO: seems kinda dodgy. Think of better way.
1445 TuplePatternItems &get_items ()
1446 {
1447 rust_assert (items != nullptr);
1448 return *items;
1449 }
1450
1451 NodeId get_node_id () const override { return node_id; }
1452
1453 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Tuple; }
1454
1455 protected:
1456 /* Use covariance to implement clone function as returning this object rather
1457 * than base */
1458 TuplePattern *clone_pattern_impl () const override
1459 {
1460 return new TuplePattern (*this);
1461 }
1462 };
1463
1464 // AST node representing a pattern in parentheses, used to control precedence
1465 class GroupedPattern : public Pattern
1466 {
1467 std::unique_ptr<Pattern> pattern_in_parens;
1468 location_t locus;
1469 NodeId node_id;
1470
1471 public:
1472 std::string as_string () const override
1473 {
1474 return "(" + pattern_in_parens->as_string () + ")";
1475 }
1476
1477 GroupedPattern (std::unique_ptr<Pattern> pattern_in_parens, location_t locus)
1478 : pattern_in_parens (std::move (pattern_in_parens)), locus (locus),
1479 node_id (Analysis::Mappings::get ().get_next_node_id ())
1480 {}
1481
1482 // Copy constructor uses clone
1483 GroupedPattern (GroupedPattern const &other)
1484 : pattern_in_parens (other.pattern_in_parens->clone_pattern ()),
1485 locus (other.locus), node_id (other.node_id)
1486 {}
1487
1488 // Overload assignment operator to clone
1489 GroupedPattern &operator= (GroupedPattern const &other)
1490 {
1491 pattern_in_parens = other.pattern_in_parens->clone_pattern ();
1492 locus = other.locus;
1493 node_id = other.node_id;
1494
1495 return *this;
1496 }
1497
1498 // default move semantics
1499 GroupedPattern (GroupedPattern &&other) = default;
1500 GroupedPattern &operator= (GroupedPattern &&other) = default;
1501
1502 location_t get_locus () const override final { return locus; }
1503
1504 void accept_vis (ASTVisitor &vis) override;
1505
1506 // TODO: seems kinda dodgy. Think of better way.
1507 Pattern &get_pattern_in_parens ()
1508 {
1509 rust_assert (pattern_in_parens != nullptr);
1510 return *pattern_in_parens;
1511 }
1512
1513 NodeId get_node_id () const override { return node_id; }
1514
1515 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Grouped; }
1516
1517 protected:
1518 /* Use covariance to implement clone function as returning this object rather
1519 * than base */
1520 GroupedPattern *clone_pattern_impl () const override
1521 {
1522 return new GroupedPattern (*this);
1523 }
1524 };
1525
1526 // AST node representing patterns that can match slices and arrays
1527 class SlicePattern : public Pattern
1528 {
1529 std::vector<std::unique_ptr<Pattern>> items;
1530 location_t locus;
1531 NodeId node_id;
1532
1533 public:
1534 std::string as_string () const override;
1535
1536 SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus)
1537 : items (std::move (items)), locus (locus),
1538 node_id (Analysis::Mappings::get ().get_next_node_id ())
1539 {}
1540
1541 // Copy constructor with vector clone
1542 SlicePattern (SlicePattern const &other) : locus (other.locus)
1543 {
1544 node_id = other.node_id;
1545 items.reserve (other.items.size ());
1546 for (const auto &e : other.items)
1547 items.push_back (e->clone_pattern ());
1548 }
1549
1550 // Overloaded assignment operator to vector clone
1551 SlicePattern &operator= (SlicePattern const &other)
1552 {
1553 locus = other.locus;
1554 node_id = other.node_id;
1555
1556 items.clear ();
1557 items.reserve (other.items.size ());
1558 for (const auto &e : other.items)
1559 items.push_back (e->clone_pattern ());
1560
1561 return *this;
1562 }
1563
1564 // move constructors
1565 SlicePattern (SlicePattern &&other) = default;
1566 SlicePattern &operator= (SlicePattern &&other) = default;
1567
1568 location_t get_locus () const override final { return locus; }
1569
1570 void accept_vis (ASTVisitor &vis) override;
1571
1572 // TODO: seems kinda dodgy. Think of better way.
1573 std::vector<std::unique_ptr<Pattern>> &get_items () { return items; }
1574 const std::vector<std::unique_ptr<Pattern>> &get_items () const
1575 {
1576 return items;
1577 }
1578
1579 NodeId get_node_id () const override { return node_id; }
1580
1581 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Slice; }
1582
1583 protected:
1584 /* Use covariance to implement clone function as returning this object rather
1585 * than base */
1586 SlicePattern *clone_pattern_impl () const override
1587 {
1588 return new SlicePattern (*this);
1589 }
1590 };
1591
1592 // AST node for alternate patterns
1593 // joins together what are technically 'PatternNoTopAlt's
1594 class AltPattern : public Pattern
1595 {
1596 std::vector<std::unique_ptr<Pattern>> alts;
1597 location_t locus;
1598 NodeId node_id;
1599
1600 public:
1601 std::string as_string () const override;
1602
1603 AltPattern (std::vector<std::unique_ptr<Pattern>> alts, location_t locus)
1604 : alts (std::move (alts)), locus (locus),
1605 node_id (Analysis::Mappings::get ().get_next_node_id ())
1606 {}
1607
1608 // Copy constructor with vector clone
1609 AltPattern (AltPattern const &other) : locus (other.locus)
1610 {
1611 node_id = other.node_id;
1612 alts.reserve (other.alts.size ());
1613 for (const auto &e : other.alts)
1614 alts.push_back (e->clone_pattern ());
1615 }
1616
1617 // Overloaded assignment operator to vector clone
1618 AltPattern &operator= (AltPattern const &other)
1619 {
1620 locus = other.locus;
1621 node_id = other.node_id;
1622
1623 alts.clear ();
1624 alts.reserve (other.alts.size ());
1625 for (const auto &e : other.alts)
1626 alts.push_back (e->clone_pattern ());
1627
1628 return *this;
1629 }
1630
1631 // move constructors
1632 AltPattern (AltPattern &&other) = default;
1633 AltPattern &operator= (AltPattern &&other) = default;
1634
1635 location_t get_locus () const override final { return locus; }
1636
1637 void accept_vis (ASTVisitor &vis) override;
1638
1639 // TODO: seems kinda dodgy. Think of better way.
1640 std::vector<std::unique_ptr<Pattern>> &get_alts () { return alts; }
1641 const std::vector<std::unique_ptr<Pattern>> &get_alts () const
1642 {
1643 return alts;
1644 }
1645
1646 NodeId get_node_id () const override { return node_id; }
1647
1648 Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Alt; }
1649
1650 protected:
1651 /* Use covariance to implement clone function as returning this object rather
1652 * than base */
1653 AltPattern *clone_pattern_impl () const override
1654 {
1655 return new AltPattern (*this);
1656 }
1657 };
1658
1659 // Moved definition to rust-path.h
1660 class Path;
1661
1662 // Forward decls for paths (defined in rust-path.h)
1663 class PathInExpression;
1664 class QualifiedPathInExpression;
1665
1666 // Replaced with forward decl - defined in rust-macro.h
1667 class MacroInvocation;
1668 } // namespace AST
1669 } // namespace Rust
1670
1671 #endif