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