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