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 : #include "rust-cloneable.h"
25 :
26 : namespace Rust {
27 : namespace AST {
28 : // Literal pattern AST node (comparing to a literal)
29 : class LiteralPattern : public Pattern
30 : {
31 : Literal lit;
32 : location_t locus;
33 : NodeId node_id;
34 : bool has_minus;
35 :
36 : public:
37 : std::string as_string () const override;
38 :
39 : // Constructor for a literal pattern
40 : LiteralPattern (Literal lit, location_t locus)
41 : : lit (std::move (lit)), locus (locus),
42 : node_id (Analysis::Mappings::get ().get_next_node_id ()),
43 : has_minus (false)
44 : {}
45 :
46 : LiteralPattern (Literal lit, location_t locus, bool has_minus)
47 : : lit (std::move (lit)), locus (locus),
48 : node_id (Analysis::Mappings::get ().get_next_node_id ()),
49 : has_minus (has_minus)
50 : {}
51 :
52 58 : LiteralPattern (std::string val, Literal::LitType type, location_t locus,
53 : PrimitiveCoreType type_hint)
54 58 : : lit (Literal (std::move (val), type, type_hint)), locus (locus),
55 58 : node_id (Analysis::Mappings::get ().get_next_node_id ()),
56 58 : has_minus (false)
57 58 : {}
58 :
59 45505 : LiteralPattern (std::string val, Literal::LitType type, location_t locus,
60 : PrimitiveCoreType type_hint, bool has_minus)
61 45505 : : lit (Literal (std::move (val), type, type_hint)), locus (locus),
62 45505 : node_id (Analysis::Mappings::get ().get_next_node_id ()),
63 45505 : has_minus (has_minus)
64 45505 : {}
65 :
66 1328 : location_t get_locus () const override final { return locus; }
67 :
68 457 : bool get_has_minus () const { return has_minus; }
69 :
70 : void accept_vis (ASTVisitor &vis) override;
71 :
72 1515728 : NodeId get_node_id () const override { return node_id; }
73 :
74 871 : Literal &get_literal () { return lit; }
75 :
76 : const Literal &get_literal () const { return lit; }
77 :
78 1515471 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Literal; }
79 :
80 : protected:
81 : /* Use covariance to implement clone function as returning this object rather
82 : * than base */
83 359388 : virtual LiteralPattern *clone_pattern_impl () const override
84 : {
85 359388 : return new LiteralPattern (*this);
86 : }
87 : };
88 :
89 : // Identifier pattern AST node (bind value matched to a variable)
90 : class IdentifierPattern : public Pattern
91 : {
92 : Identifier variable_ident;
93 : bool is_ref;
94 : bool is_mut;
95 :
96 : // bool has_pattern;
97 : Cloneable<std::unique_ptr<Pattern>> subpattern;
98 : location_t locus;
99 : NodeId node_id;
100 :
101 : public:
102 : std::string as_string () const override;
103 :
104 : // Returns whether the IdentifierPattern has a pattern to bind.
105 6417491 : bool has_subpattern () const { return subpattern != nullptr; }
106 :
107 : // Constructor
108 53425 : IdentifierPattern (Identifier ident, location_t locus, bool is_ref = false,
109 : bool is_mut = false,
110 : std::unique_ptr<Pattern> subpattern = nullptr)
111 53425 : : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
112 53425 : is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus),
113 53425 : node_id (Analysis::Mappings::get ().get_next_node_id ())
114 53425 : {}
115 :
116 : IdentifierPattern (NodeId node_id, Identifier ident, location_t locus,
117 : bool is_ref = false, bool is_mut = false,
118 : std::unique_ptr<Pattern> subpattern = nullptr)
119 : : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
120 : is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus),
121 : node_id (node_id)
122 : {}
123 :
124 90522 : location_t get_locus () const override final { return locus; }
125 :
126 : void accept_vis (ASTVisitor &vis) override;
127 :
128 3976 : Pattern &get_subpattern ()
129 : {
130 3976 : rust_assert (has_subpattern ());
131 3976 : return *subpattern.get ();
132 : }
133 :
134 1033 : std::unique_ptr<Pattern> &get_subpattern_ptr ()
135 : {
136 1033 : rust_assert (has_subpattern ());
137 1033 : return subpattern.get ();
138 : }
139 :
140 797654 : Identifier get_ident () const { return variable_ident; }
141 :
142 820587 : bool get_is_mut () const { return is_mut; }
143 827761 : bool get_is_ref () const { return is_ref; }
144 :
145 1537841 : NodeId get_node_id () const override { return node_id; }
146 :
147 745917 : Pattern::Kind get_pattern_kind () override
148 : {
149 745917 : return Pattern::Kind::Identifier;
150 : }
151 :
152 : protected:
153 : /* Use covariance to implement clone function as returning this object rather
154 : * than base */
155 146753 : IdentifierPattern *clone_pattern_impl () const override
156 : {
157 146753 : return new IdentifierPattern (*this);
158 : }
159 : };
160 :
161 : // AST node for using the '_' wildcard "match any value" pattern
162 35808 : class WildcardPattern : public Pattern
163 : {
164 : location_t locus;
165 : NodeId node_id;
166 :
167 : public:
168 0 : std::string as_string () const override { return std::string (1, '_'); }
169 :
170 5682 : WildcardPattern (location_t locus)
171 5682 : : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
172 5682 : {}
173 :
174 3316 : location_t get_locus () const override final { return locus; }
175 :
176 : void accept_vis (ASTVisitor &vis) override;
177 :
178 145118 : NodeId get_node_id () const override { return node_id; }
179 :
180 144076 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Wildcard; }
181 :
182 : protected:
183 : /* Use covariance to implement clone function as returning this object rather
184 : * than base */
185 35808 : WildcardPattern *clone_pattern_impl () const override
186 : {
187 35808 : return new WildcardPattern (*this);
188 : }
189 : };
190 :
191 75 : class RestPattern : public Pattern
192 : {
193 : location_t locus;
194 : NodeId node_id;
195 :
196 : public:
197 0 : std::string as_string () const override { return ".."; }
198 :
199 63 : RestPattern (location_t locus)
200 63 : : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
201 63 : {}
202 :
203 44 : location_t get_locus () const override final { return locus; }
204 :
205 : void accept_vis (ASTVisitor &vis) override;
206 :
207 238 : NodeId get_node_id () const override final { return node_id; }
208 :
209 624 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Rest; }
210 :
211 : protected:
212 75 : RestPattern *clone_pattern_impl () const override
213 : {
214 75 : return new RestPattern (*this);
215 : }
216 : };
217 :
218 : // Base range pattern bound (lower or upper limit) - abstract
219 1231 : class RangePatternBound
220 : {
221 : public:
222 : enum RangePatternBoundType
223 : {
224 : LITERAL,
225 : PATH,
226 : QUALPATH
227 : };
228 :
229 : virtual ~RangePatternBound () {}
230 :
231 : // Unique pointer custom clone function
232 879 : std::unique_ptr<RangePatternBound> clone_range_pattern_bound () const
233 : {
234 879 : return std::unique_ptr<RangePatternBound> (
235 879 : clone_range_pattern_bound_impl ());
236 : }
237 :
238 : virtual std::string as_string () const = 0;
239 :
240 : virtual void accept_vis (ASTVisitor &vis) = 0;
241 :
242 : virtual RangePatternBoundType get_bound_type () const = 0;
243 :
244 : protected:
245 : // pure virtual as RangePatternBound is abstract
246 : virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0;
247 : };
248 :
249 : // Literal-based pattern bound
250 1714 : class RangePatternBoundLiteral : public RangePatternBound
251 : {
252 : Literal literal;
253 : /* Can only be a char, byte, int, or float literal - same impl here as
254 : * previously */
255 :
256 : // Minus prefixed to literal (if integer or floating-point)
257 : bool has_minus;
258 :
259 : location_t locus;
260 :
261 : public:
262 : // Constructor
263 328 : RangePatternBoundLiteral (Literal literal, location_t locus,
264 : bool has_minus = false)
265 328 : : literal (literal), has_minus (has_minus), locus (locus)
266 : {}
267 :
268 : std::string as_string () const override;
269 :
270 132 : Literal get_literal () const { return literal; }
271 :
272 132 : bool get_has_minus () const { return has_minus; }
273 :
274 95 : location_t get_locus () const { return locus; }
275 :
276 : void accept_vis (ASTVisitor &vis) override;
277 :
278 71 : RangePatternBoundType get_bound_type () const override
279 : {
280 71 : return RangePatternBoundType::LITERAL;
281 : }
282 :
283 : protected:
284 : /* Use covariance to implement clone function as returning this object rather
285 : * than base */
286 857 : RangePatternBoundLiteral *clone_range_pattern_bound_impl () const override
287 : {
288 857 : return new RangePatternBoundLiteral (*this);
289 : }
290 : };
291 :
292 : // Path-based pattern bound
293 22 : class RangePatternBoundPath : public RangePatternBound
294 : {
295 : PathInExpression path;
296 :
297 : /* TODO: should this be refactored so that PathInExpression is a subclass of
298 : * RangePatternBound? */
299 :
300 : public:
301 24 : RangePatternBoundPath (PathInExpression path) : path (std::move (path)) {}
302 :
303 0 : std::string as_string () const override { return path.as_string (); }
304 :
305 : location_t get_locus () const { return path.get_locus (); }
306 :
307 : void accept_vis (ASTVisitor &vis) override;
308 :
309 : // TODO: this mutable getter seems kinda dodgy
310 441 : PathInExpression &get_path () { return path; }
311 : const PathInExpression &get_path () const { return path; }
312 :
313 21 : RangePatternBoundType get_bound_type () const override
314 : {
315 21 : return RangePatternBoundType::PATH;
316 : }
317 :
318 : protected:
319 : /* Use covariance to implement clone function as returning this object rather
320 : * than base */
321 22 : RangePatternBoundPath *clone_range_pattern_bound_impl () const override
322 : {
323 22 : return new RangePatternBoundPath (*this);
324 : }
325 : };
326 :
327 : // Qualified path-based pattern bound
328 0 : class RangePatternBoundQualPath : public RangePatternBound
329 : {
330 : QualifiedPathInExpression path;
331 :
332 : /* TODO: should this be refactored so that QualifiedPathInExpression is a
333 : * subclass of RangePatternBound? */
334 :
335 : public:
336 0 : RangePatternBoundQualPath (QualifiedPathInExpression path)
337 0 : : path (std::move (path))
338 : {}
339 :
340 0 : std::string as_string () const override { return path.as_string (); }
341 :
342 : location_t get_locus () const { return path.get_locus (); }
343 :
344 : void accept_vis (ASTVisitor &vis) override;
345 :
346 : // TODO: this mutable getter seems kinda dodgy
347 0 : QualifiedPathInExpression &get_qualified_path () { return path; }
348 : const QualifiedPathInExpression &get_qualified_path () const { return path; }
349 :
350 0 : RangePatternBoundType get_bound_type () const override
351 : {
352 0 : return RangePatternBoundType::QUALPATH;
353 : }
354 :
355 : protected:
356 : /* Use covariance to implement clone function as returning this object rather
357 : * than base */
358 0 : RangePatternBoundQualPath *clone_range_pattern_bound_impl () const override
359 : {
360 0 : return new RangePatternBoundQualPath (*this);
361 : }
362 : };
363 :
364 : enum class RangeKind
365 : {
366 : INCLUDED,
367 : ELLIPSIS,
368 : EXCLUDED,
369 : };
370 :
371 : RangeKind tokenid_to_rangekind (TokenId id);
372 : // AST node for matching within a certain range (range pattern)
373 : class RangePattern : public Pattern
374 : {
375 : Cloneable<std::unique_ptr<RangePatternBound>> lower;
376 : Cloneable<std::unique_ptr<RangePatternBound>> upper;
377 :
378 : RangeKind range_kind;
379 :
380 : /* location only stored to avoid a dereference - lower pattern should give
381 : * correct location so maybe change in future */
382 : location_t locus;
383 : NodeId node_id;
384 :
385 : public:
386 : std::string as_string () const override;
387 :
388 : // Constructor
389 176 : RangePattern (std::unique_ptr<RangePatternBound> lower,
390 : std::unique_ptr<RangePatternBound> upper, RangeKind range_kind,
391 : location_t locus)
392 176 : : lower (std::move (lower)), upper (std::move (upper)),
393 176 : range_kind (range_kind), locus (locus),
394 176 : node_id (Analysis::Mappings::get ().get_next_node_id ())
395 176 : {}
396 :
397 155 : location_t get_locus () const override final { return locus; }
398 :
399 41 : bool get_has_ellipsis_syntax () const
400 : {
401 41 : return range_kind == RangeKind::ELLIPSIS;
402 : }
403 :
404 176 : RangeKind get_range_kind () const { return range_kind; }
405 :
406 23797 : bool get_has_lower_bound () const { return lower != nullptr; }
407 :
408 23797 : bool get_has_upper_bound () const { return upper != nullptr; }
409 :
410 : void accept_vis (ASTVisitor &vis) override;
411 :
412 : // TODO: is this better? or is a "vis_bound" better?
413 23843 : RangePatternBound &get_lower_bound ()
414 : {
415 23843 : rust_assert (lower != nullptr);
416 23843 : return *lower.get ();
417 : }
418 :
419 23843 : RangePatternBound &get_upper_bound ()
420 : {
421 23843 : rust_assert (upper != nullptr);
422 23843 : return *upper.get ();
423 : }
424 :
425 2685 : NodeId get_node_id () const override { return node_id; }
426 :
427 2640 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Range; }
428 :
429 : protected:
430 : /* Use covariance to implement clone function as returning this object rather
431 : * than base */
432 440 : RangePattern *clone_pattern_impl () const override
433 : {
434 440 : return new RangePattern (*this);
435 : }
436 : };
437 :
438 : // AST node for pattern based on dereferencing the pointers given
439 : class ReferencePattern : public Pattern
440 : {
441 : bool has_two_amps;
442 : bool is_mut;
443 : Cloneable<std::unique_ptr<Pattern>> pattern;
444 : location_t locus;
445 : NodeId node_id;
446 :
447 : public:
448 : std::string as_string () const override;
449 :
450 404 : ReferencePattern (std::unique_ptr<Pattern> pattern, bool is_mut_reference,
451 : bool ref_has_two_amps, location_t locus)
452 404 : : has_two_amps (ref_has_two_amps), is_mut (is_mut_reference),
453 404 : pattern (std::move (pattern)), locus (locus),
454 404 : node_id (Analysis::Mappings::get ().get_next_node_id ())
455 404 : {}
456 :
457 454 : location_t get_locus () const override final { return locus; }
458 :
459 : void accept_vis (ASTVisitor &vis) override;
460 :
461 : // TODO: is this better? Or is a "vis_pattern" better?
462 67224 : Pattern &get_referenced_pattern ()
463 : {
464 67224 : rust_assert (pattern != nullptr);
465 67224 : return *pattern.get ();
466 : }
467 :
468 14857 : std::unique_ptr<Pattern> &get_referenced_pattern_ptr ()
469 : {
470 14857 : rust_assert (pattern != nullptr);
471 14857 : return pattern.get ();
472 : }
473 :
474 395 : bool is_double_reference () const { return has_two_amps; }
475 :
476 395 : bool get_is_mut () const { return is_mut; }
477 :
478 7573 : NodeId get_node_id () const override { return node_id; }
479 :
480 7110 : Pattern::Kind get_pattern_kind () override
481 : {
482 7110 : return Pattern::Kind::Reference;
483 : }
484 :
485 : protected:
486 : /* Use covariance to implement clone function as returning this object rather
487 : * than base */
488 880 : ReferencePattern *clone_pattern_impl () const override
489 : {
490 880 : return new ReferencePattern (*this);
491 : }
492 : };
493 :
494 : #if 0
495 : // aka StructPatternEtCetera; potential element in struct pattern
496 : struct StructPatternEtc
497 : {
498 : private:
499 : std::vector<Attribute> outer_attrs;
500 :
501 : // should this store location data?
502 :
503 : public:
504 : StructPatternEtc (std::vector<Attribute> outer_attribs)
505 : : outer_attrs (std::move (outer_attribs))
506 : {}
507 :
508 : // Creates an empty StructPatternEtc
509 : static StructPatternEtc create_empty ()
510 : {
511 : return StructPatternEtc (std::vector<Attribute> ());
512 : }
513 : };
514 : #endif
515 :
516 : // Base class for a single field in a struct pattern - abstract
517 : class StructPatternField
518 : {
519 : std::vector<Attribute> outer_attrs;
520 : location_t locus;
521 :
522 : protected:
523 : NodeId node_id;
524 :
525 : public:
526 : enum ItemType
527 : {
528 : TUPLE_PAT,
529 : IDENT_PAT,
530 : IDENT
531 : };
532 :
533 : virtual ~StructPatternField () {}
534 :
535 : // Unique pointer custom clone function
536 897 : std::unique_ptr<StructPatternField> clone_struct_pattern_field () const
537 : {
538 897 : return std::unique_ptr<StructPatternField> (
539 897 : clone_struct_pattern_field_impl ());
540 : }
541 :
542 : virtual std::string as_string () const;
543 :
544 476 : location_t get_locus () const { return locus; }
545 :
546 : virtual void accept_vis (ASTVisitor &vis) = 0;
547 :
548 : virtual void mark_for_strip () = 0;
549 : virtual bool is_marked_for_strip () const = 0;
550 : virtual ItemType get_item_type () const = 0;
551 :
552 297 : NodeId get_node_id () const { return node_id; }
553 :
554 : // TODO: seems kinda dodgy. Think of better way.
555 23207 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
556 : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
557 :
558 : protected:
559 351 : StructPatternField (std::vector<Attribute> outer_attribs, location_t locus,
560 : NodeId node_id)
561 351 : : outer_attrs (std::move (outer_attribs)), locus (locus), node_id (node_id)
562 : {}
563 :
564 : // Clone function implementation as pure virtual method
565 : virtual StructPatternField *clone_struct_pattern_field_impl () const = 0;
566 : };
567 :
568 : // Tuple pattern single field in a struct pattern
569 : class StructPatternFieldTuplePat : public StructPatternField
570 : {
571 : TupleIndex index;
572 : Cloneable<std::unique_ptr<Pattern>> tuple_pattern;
573 :
574 : public:
575 26 : StructPatternFieldTuplePat (TupleIndex index,
576 : std::unique_ptr<Pattern> tuple_pattern,
577 : std::vector<Attribute> outer_attribs,
578 : location_t locus)
579 : : StructPatternField (std::move (outer_attribs), locus,
580 26 : Analysis::Mappings::get ().get_next_node_id ()),
581 26 : index (index), tuple_pattern (std::move (tuple_pattern))
582 26 : {}
583 :
584 : std::string as_string () const override;
585 :
586 : void accept_vis (ASTVisitor &vis) override;
587 :
588 : // based on idea of tuple pattern no longer existing
589 0 : void mark_for_strip () override { tuple_pattern = nullptr; }
590 78 : bool is_marked_for_strip () const override
591 : {
592 78 : return tuple_pattern == nullptr;
593 : }
594 :
595 42 : TupleIndex get_index () { return index; }
596 :
597 : // TODO: is this better? Or is a "vis_pattern" better?
598 510 : Pattern &get_index_pattern ()
599 : {
600 510 : rust_assert (tuple_pattern != nullptr);
601 510 : return *tuple_pattern.get ();
602 : }
603 :
604 120 : std::unique_ptr<Pattern> &get_index_pattern_ptr ()
605 : {
606 120 : rust_assert (tuple_pattern != nullptr);
607 120 : return tuple_pattern.get ();
608 : }
609 :
610 24 : ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; }
611 :
612 : protected:
613 : /* Use covariance to implement clone function as returning this object rather
614 : * than base */
615 42 : StructPatternFieldTuplePat *clone_struct_pattern_field_impl () const override
616 : {
617 42 : return new StructPatternFieldTuplePat (*this);
618 : }
619 : };
620 :
621 : // Identifier pattern single field in a struct pattern
622 : class StructPatternFieldIdentPat : public StructPatternField
623 : {
624 : Identifier ident;
625 : Cloneable<std::unique_ptr<Pattern>> ident_pattern;
626 :
627 : public:
628 207 : StructPatternFieldIdentPat (Identifier ident,
629 : std::unique_ptr<Pattern> ident_pattern,
630 : std::vector<Attribute> outer_attrs,
631 : location_t locus)
632 : : StructPatternField (std::move (outer_attrs), locus,
633 207 : Analysis::Mappings::get ().get_next_node_id ()),
634 207 : ident (std::move (ident)), ident_pattern (std::move (ident_pattern))
635 207 : {}
636 :
637 : std::string as_string () const override;
638 :
639 : void accept_vis (ASTVisitor &vis) override;
640 :
641 : // based on idea of identifier pattern no longer existing
642 0 : void mark_for_strip () override { ident_pattern = nullptr; }
643 3456 : bool is_marked_for_strip () const override
644 : {
645 3456 : return ident_pattern == nullptr;
646 : }
647 :
648 167 : const Identifier &get_identifier () const { return ident; }
649 :
650 : // TODO: is this better? Or is a "vis_pattern" better?
651 13639 : Pattern &get_ident_pattern ()
652 : {
653 13639 : rust_assert (ident_pattern != nullptr);
654 13639 : return *ident_pattern.get ();
655 : }
656 :
657 3707 : std::unique_ptr<Pattern> &get_ident_pattern_ptr ()
658 : {
659 3707 : rust_assert (ident_pattern != nullptr);
660 3707 : return ident_pattern.get ();
661 : }
662 :
663 167 : ItemType get_item_type () const override final { return ItemType::IDENT_PAT; }
664 :
665 : protected:
666 : /* Use covariance to implement clone function as returning this object rather
667 : * than base */
668 604 : StructPatternFieldIdentPat *clone_struct_pattern_field_impl () const override
669 : {
670 604 : return new StructPatternFieldIdentPat (*this);
671 : }
672 : };
673 :
674 : // Identifier only (with no pattern) single field in a struct pattern
675 : class StructPatternFieldIdent : public StructPatternField
676 : {
677 : bool has_ref;
678 : bool has_mut;
679 : Identifier ident;
680 :
681 : public:
682 118 : StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut,
683 : std::vector<Attribute> outer_attrs, location_t locus)
684 : : StructPatternField (std::move (outer_attrs), locus,
685 118 : Analysis::Mappings::get ().get_next_node_id ()),
686 118 : has_ref (is_ref), has_mut (is_mut), ident (std::move (ident))
687 118 : {}
688 :
689 : std::string as_string () const override;
690 :
691 : void accept_vis (ASTVisitor &vis) override;
692 :
693 : // based on idea of identifier no longer existing
694 0 : void mark_for_strip () override { ident = {""}; }
695 1676 : bool is_marked_for_strip () const override { return ident.empty (); }
696 :
697 224 : const Identifier &get_identifier () const { return ident; }
698 :
699 106 : ItemType get_item_type () const override final { return ItemType::IDENT; }
700 :
701 315 : bool is_ref () const { return has_ref; }
702 :
703 315 : bool is_mut () const { return has_mut; }
704 :
705 : protected:
706 : /* Use covariance to implement clone function as returning this object rather
707 : * than base */
708 251 : StructPatternFieldIdent *clone_struct_pattern_field_impl () const override
709 : {
710 251 : return new StructPatternFieldIdent (*this);
711 : }
712 : };
713 :
714 : // Elements of a struct pattern
715 392 : class StructPatternElements
716 : {
717 : // bool has_struct_pattern_fields;
718 : Cloneable<std::vector<std::unique_ptr<StructPatternField>>> fields;
719 :
720 : bool has_rest_pattern;
721 : std::vector<Attribute> struct_pattern_etc_attrs;
722 : // StructPatternEtc etc;
723 :
724 : // must have at least one of the two and maybe both
725 :
726 : // should this store location data?
727 :
728 : public:
729 : // Returns whether there are any struct pattern fields
730 3845 : bool has_struct_pattern_fields () const { return !fields.get ().empty (); }
731 :
732 : /* Returns whether the struct pattern elements is entirely empty (no fields,
733 : * no etc). */
734 3704 : bool is_empty () const
735 : {
736 4 : return !has_struct_pattern_fields () && !has_rest_pattern;
737 : }
738 :
739 4018 : bool has_rest () const { return has_rest_pattern; }
740 :
741 : // Constructor for StructPatternElements with both (potentially)
742 6 : StructPatternElements (
743 : std::vector<std::unique_ptr<StructPatternField>> fields,
744 : std::vector<Attribute> etc_attrs)
745 6 : : fields (std::move (fields)), has_rest_pattern (true),
746 6 : struct_pattern_etc_attrs (std::move (etc_attrs))
747 : {}
748 :
749 : // Constructor for StructPatternElements with no StructPatternEtc
750 212 : StructPatternElements (
751 : std::vector<std::unique_ptr<StructPatternField>> fields)
752 189 : : fields (std::move (fields)), has_rest_pattern (false),
753 189 : struct_pattern_etc_attrs ()
754 : {}
755 :
756 : // Creates an empty StructPatternElements
757 0 : static StructPatternElements create_empty ()
758 : {
759 0 : return StructPatternElements (
760 0 : std::vector<std::unique_ptr<StructPatternField>> ());
761 : }
762 :
763 : std::string as_string () const;
764 :
765 : // TODO: seems kinda dodgy. Think of better way.
766 3842 : std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields ()
767 : {
768 14533 : return fields.get ();
769 : }
770 : const std::vector<std::unique_ptr<StructPatternField>> &
771 : get_struct_pattern_fields () const
772 : {
773 : return fields.get ();
774 : }
775 :
776 84 : std::vector<Attribute> &get_etc_outer_attrs ()
777 : {
778 10599 : return struct_pattern_etc_attrs;
779 : }
780 : const std::vector<Attribute> &get_etc_outer_attrs () const
781 : {
782 : return struct_pattern_etc_attrs;
783 : }
784 :
785 0 : void strip_etc ()
786 : {
787 0 : has_rest_pattern = false;
788 0 : struct_pattern_etc_attrs.clear ();
789 0 : struct_pattern_etc_attrs.shrink_to_fit ();
790 : }
791 : };
792 :
793 : // Struct pattern AST node representation
794 : class StructPattern : public Pattern
795 : {
796 : PathInExpression path;
797 :
798 : // bool has_struct_pattern_elements;
799 : StructPatternElements elems;
800 :
801 : NodeId node_id;
802 : location_t locus;
803 :
804 : public:
805 : std::string as_string () const override;
806 :
807 : // Constructs a struct pattern from specified StructPatternElements
808 218 : StructPattern (PathInExpression struct_path, location_t locus,
809 : StructPatternElements elems
810 : = StructPatternElements::create_empty ())
811 218 : : path (std::move (struct_path)), elems (std::move (elems)),
812 436 : node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
813 218 : {}
814 :
815 : /* TODO: constructor to construct via elements included in
816 : * StructPatternElements */
817 :
818 : /* Returns whether struct pattern has any struct pattern elements (if not, it
819 : * is empty). */
820 3706 : bool has_struct_pattern_elems () const { return !elems.is_empty (); }
821 :
822 317 : location_t get_locus () const override { return locus; }
823 :
824 : void accept_vis (ASTVisitor &vis) override;
825 :
826 : // TODO: seems kinda dodgy. Think of better way.
827 14534 : StructPatternElements &get_struct_pattern_elems () { return elems; }
828 : const StructPatternElements &get_struct_pattern_elems () const
829 : {
830 : return elems;
831 : }
832 :
833 14536 : PathInExpression &get_path () { return path; }
834 : const PathInExpression &get_path () const { return path; }
835 :
836 1996 : NodeId get_node_id () const override { return node_id; }
837 :
838 1770 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Struct; }
839 :
840 : protected:
841 : /* Use covariance to implement clone function as returning this object rather
842 : * than base */
843 485 : StructPattern *clone_pattern_impl () const override
844 : {
845 485 : return new StructPattern (*this);
846 : }
847 : };
848 :
849 : // Base abstract class for TupleStructItems, TuplePatternItems &
850 : // SlicePatternItems
851 32389 : class PatternItems
852 : {
853 : public:
854 : enum ItemType
855 : {
856 : NO_REST,
857 : HAS_REST,
858 : };
859 :
860 : virtual ~PatternItems () {}
861 :
862 : // TODO: should this store location data?
863 :
864 : // Unique pointer custom clone function
865 : std::unique_ptr<PatternItems> clone_pattern_items () const
866 : {
867 : return std::unique_ptr<PatternItems> (clone_pattern_items_impl ());
868 : }
869 :
870 : virtual std::string as_string () const = 0;
871 : virtual ItemType get_item_type () const = 0;
872 : virtual void accept_vis (ASTVisitor &vis) = 0;
873 :
874 : protected:
875 : virtual PatternItems *clone_pattern_items_impl () const = 0;
876 : };
877 :
878 : // Base abstract class for patterns used in TupleStructPattern
879 9895 : class TupleStructItems : public PatternItems
880 : {
881 : public:
882 : // Unique pointer custom clone function
883 7530 : std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
884 : {
885 7530 : return std::unique_ptr<TupleStructItems> (clone_pattern_items_impl ());
886 : }
887 :
888 : protected:
889 : // pure virtual clone implementation
890 : virtual TupleStructItems *clone_pattern_items_impl () const = 0;
891 : };
892 :
893 : // Class for non-ranged tuple struct pattern patterns
894 7466 : class TupleStructItemsNoRest : public TupleStructItems
895 : {
896 : Cloneable<std::vector<std::unique_ptr<Pattern>>> patterns;
897 :
898 : public:
899 2377 : TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
900 2377 : : patterns (std::move (patterns))
901 : {}
902 :
903 : std::string as_string () const override;
904 :
905 : void accept_vis (ASTVisitor &vis) override;
906 :
907 : // TODO: seems kinda dodgy. Think of better way.
908 936 : std::vector<std::unique_ptr<Pattern>> &get_patterns ()
909 : {
910 325920 : return patterns.get ();
911 : }
912 : const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
913 : {
914 : return patterns.get ();
915 : }
916 :
917 980 : ItemType get_item_type () const override final { return ItemType::NO_REST; }
918 :
919 : protected:
920 : /* Use covariance to implement clone function as returning this object rather
921 : * than base */
922 7466 : TupleStructItemsNoRest *clone_pattern_items_impl () const override
923 : {
924 7466 : return new TupleStructItemsNoRest (*this);
925 : }
926 : };
927 :
928 : // Class for ranged tuple struct pattern patterns
929 : class TupleStructItemsHasRest : public TupleStructItems
930 : {
931 : Cloneable<std::vector<std::unique_ptr<Pattern>>> lower_patterns;
932 : Cloneable<std::vector<std::unique_ptr<Pattern>>> upper_patterns;
933 :
934 : public:
935 52 : TupleStructItemsHasRest (std::vector<std::unique_ptr<Pattern>> lower_patterns,
936 : std::vector<std::unique_ptr<Pattern>> upper_patterns)
937 52 : : lower_patterns (std::move (lower_patterns)),
938 52 : upper_patterns (std::move (upper_patterns))
939 : {}
940 :
941 : std::string as_string () const override;
942 :
943 : void accept_vis (ASTVisitor &vis) override;
944 :
945 : // TODO: seems kinda dodgy. Think of better way.
946 : std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
947 : {
948 3850 : return lower_patterns.get ();
949 : }
950 : const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
951 : {
952 : return lower_patterns.get ();
953 : }
954 :
955 : // TODO: seems kinda dodgy. Think of better way.
956 : std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
957 : {
958 3778 : return upper_patterns.get ();
959 : }
960 : const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
961 : {
962 : return upper_patterns.get ();
963 : }
964 :
965 45 : ItemType get_item_type () const override final { return ItemType::HAS_REST; }
966 :
967 : protected:
968 : /* Use covariance to implement clone function as returning this object rather
969 : * than base */
970 64 : TupleStructItemsHasRest *clone_pattern_items_impl () const override
971 : {
972 64 : return new TupleStructItemsHasRest (*this);
973 : }
974 : };
975 :
976 : // AST node representing a tuple struct pattern
977 : class TupleStructPattern : public Pattern
978 : {
979 : PathInExpression path;
980 : Cloneable<std::unique_ptr<TupleStructItems>> items;
981 : NodeId node_id;
982 :
983 : /* TOOD: should this store location data? current accessor uses path location
984 : * data */
985 :
986 : public:
987 : std::string as_string () const override;
988 :
989 2429 : TupleStructPattern (PathInExpression tuple_struct_path,
990 : std::unique_ptr<TupleStructItems> items)
991 2429 : : path (std::move (tuple_struct_path)), items (std::move (items)),
992 2429 : node_id (Analysis::Mappings::get ().get_next_node_id ())
993 : {
994 2429 : rust_assert (this->items != nullptr);
995 2429 : }
996 :
997 2392 : location_t get_locus () const override { return path.get_locus (); }
998 :
999 : void accept_vis (ASTVisitor &vis) override;
1000 :
1001 246989 : TupleStructItems &get_items ()
1002 : {
1003 246989 : rust_assert (items != nullptr);
1004 246989 : return *items.get ();
1005 : }
1006 :
1007 328709 : PathInExpression &get_path () { return path; }
1008 : const PathInExpression &get_path () const { return path; }
1009 :
1010 28043 : NodeId get_node_id () const override { return node_id; }
1011 :
1012 29708 : Pattern::Kind get_pattern_kind () override
1013 : {
1014 29708 : return Pattern::Kind::TupleStruct;
1015 : }
1016 :
1017 : protected:
1018 : /* Use covariance to implement clone function as returning this object rather
1019 : * than base */
1020 7530 : TupleStructPattern *clone_pattern_impl () const override
1021 : {
1022 7530 : return new TupleStructPattern (*this);
1023 : }
1024 : };
1025 :
1026 : // Base abstract class representing TuplePattern patterns
1027 22494 : class TuplePatternItems : public PatternItems
1028 : {
1029 : public:
1030 : // Unique pointer custom clone function
1031 19454 : std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const
1032 : {
1033 19454 : return std::unique_ptr<TuplePatternItems> (clone_pattern_items_impl ());
1034 : }
1035 :
1036 : protected:
1037 : // pure virtual clone implementation
1038 : virtual TuplePatternItems *clone_pattern_items_impl () const = 0;
1039 : };
1040 :
1041 : // Class representing TuplePattern patterns which contains no rest pattern
1042 19416 : class TuplePatternItemsNoRest : public TuplePatternItems
1043 : {
1044 : Cloneable<std::vector<std::unique_ptr<Pattern>>> patterns;
1045 :
1046 : public:
1047 3040 : TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
1048 3040 : : patterns (std::move (patterns))
1049 : {}
1050 :
1051 : std::string as_string () const override;
1052 :
1053 : void accept_vis (ASTVisitor &vis) override;
1054 :
1055 : // TODO: seems kinda dodgy. Think of better way.
1056 412 : std::vector<std::unique_ptr<Pattern>> &get_patterns ()
1057 : {
1058 884121 : return patterns.get ();
1059 : }
1060 : const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
1061 : {
1062 : return patterns.get ();
1063 : }
1064 :
1065 424 : ItemType get_item_type () const override { return ItemType::NO_REST; }
1066 :
1067 : protected:
1068 : /* Use covariance to implement clone function as returning this object rather
1069 : * than base */
1070 19416 : TuplePatternItemsNoRest *clone_pattern_items_impl () const override
1071 : {
1072 19416 : return new TuplePatternItemsNoRest (*this);
1073 : }
1074 : };
1075 :
1076 : // Class representing TuplePattern patterns which contains a rest pattern
1077 : class TuplePatternItemsHasRest : public TuplePatternItems
1078 : {
1079 : Cloneable<std::vector<std::unique_ptr<Pattern>>> lower_patterns;
1080 : Cloneable<std::vector<std::unique_ptr<Pattern>>> upper_patterns;
1081 :
1082 : public:
1083 38 : TuplePatternItemsHasRest (
1084 : std::vector<std::unique_ptr<Pattern>> lower_patterns,
1085 : std::vector<std::unique_ptr<Pattern>> upper_patterns)
1086 38 : : lower_patterns (std::move (lower_patterns)),
1087 38 : upper_patterns (std::move (upper_patterns))
1088 : {}
1089 :
1090 : std::string as_string () const override;
1091 :
1092 : void accept_vis (ASTVisitor &vis) override;
1093 :
1094 : // TODO: seems kinda dodgy. Think of better way.
1095 : std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
1096 : {
1097 1110 : return lower_patterns.get ();
1098 : }
1099 : const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
1100 : {
1101 : return lower_patterns.get ();
1102 : }
1103 :
1104 : // TODO: seems kinda dodgy. Think of better way.
1105 : std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
1106 : {
1107 1048 : return upper_patterns.get ();
1108 : }
1109 : const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
1110 : {
1111 : return upper_patterns.get ();
1112 : }
1113 :
1114 38 : ItemType get_item_type () const override { return ItemType::HAS_REST; }
1115 :
1116 : protected:
1117 : /* Use covariance to implement clone function as returning this object rather
1118 : * than base */
1119 38 : TuplePatternItemsHasRest *clone_pattern_items_impl () const override
1120 : {
1121 38 : return new TuplePatternItemsHasRest (*this);
1122 : }
1123 : };
1124 :
1125 : // AST node representing a tuple pattern
1126 38908 : class TuplePattern : public Pattern
1127 : {
1128 : Cloneable<std::unique_ptr<TuplePatternItems>> items;
1129 : location_t locus;
1130 : NodeId node_id;
1131 :
1132 : public:
1133 : std::string as_string () const override;
1134 :
1135 3078 : TuplePattern (std::unique_ptr<TuplePatternItems> items, location_t locus)
1136 3078 : : items (std::move (items)), locus (locus),
1137 3078 : node_id (Analysis::Mappings::get ().get_next_node_id ())
1138 : {
1139 3078 : rust_assert (this->items != nullptr);
1140 3078 : }
1141 :
1142 1390 : location_t get_locus () const override final { return locus; }
1143 :
1144 : void accept_vis (ASTVisitor &vis) override;
1145 :
1146 : // TODO: seems kinda dodgy. Think of better way.
1147 669275 : TuplePatternItems &get_items ()
1148 : {
1149 669275 : rust_assert (items != nullptr);
1150 669275 : return *items.get ();
1151 : }
1152 :
1153 86499 : NodeId get_node_id () const override { return node_id; }
1154 :
1155 86234 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Tuple; }
1156 :
1157 : protected:
1158 : /* Use covariance to implement clone function as returning this object rather
1159 : * than base */
1160 19454 : TuplePattern *clone_pattern_impl () const override
1161 : {
1162 19454 : return new TuplePattern (*this);
1163 : }
1164 : };
1165 :
1166 : // AST node representing a pattern in parentheses, used to control precedence
1167 96 : class GroupedPattern : public Pattern
1168 : {
1169 : Cloneable<std::unique_ptr<Pattern>> pattern_in_parens;
1170 : location_t locus;
1171 : NodeId node_id;
1172 :
1173 : public:
1174 0 : std::string as_string () const override
1175 : {
1176 0 : return "(" + pattern_in_parens.get ()->as_string () + ")";
1177 : }
1178 :
1179 48 : GroupedPattern (std::unique_ptr<Pattern> pattern_in_parens, location_t locus)
1180 48 : : pattern_in_parens (std::move (pattern_in_parens)), locus (locus),
1181 48 : node_id (Analysis::Mappings::get ().get_next_node_id ())
1182 48 : {}
1183 :
1184 7 : location_t get_locus () const override final { return locus; }
1185 :
1186 : void accept_vis (ASTVisitor &vis) override;
1187 :
1188 : // TODO: seems kinda dodgy. Think of better way.
1189 1015 : Pattern &get_pattern_in_parens ()
1190 : {
1191 1015 : rust_assert (pattern_in_parens != nullptr);
1192 1015 : return *pattern_in_parens.get ();
1193 : }
1194 :
1195 240 : std::unique_ptr<Pattern> &get_pattern_in_parens_ptr ()
1196 : {
1197 240 : rust_assert (pattern_in_parens != nullptr);
1198 240 : return pattern_in_parens.get ();
1199 : }
1200 :
1201 96 : NodeId get_node_id () const override { return node_id; }
1202 :
1203 99 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Grouped; }
1204 :
1205 : protected:
1206 : /* Use covariance to implement clone function as returning this object rather
1207 : * than base */
1208 48 : GroupedPattern *clone_pattern_impl () const override
1209 : {
1210 48 : return new GroupedPattern (*this);
1211 : }
1212 : };
1213 :
1214 : // AST node representing patterns that can match slices and arrays
1215 236 : class SlicePattern : public Pattern
1216 : {
1217 : Cloneable<std::vector<std::unique_ptr<Pattern>>> patterns;
1218 : location_t locus;
1219 : NodeId node_id;
1220 :
1221 : public:
1222 : std::string as_string () const override;
1223 :
1224 104 : SlicePattern (std::vector<std::unique_ptr<Pattern>> patterns,
1225 : location_t locus)
1226 104 : : patterns (std::move (patterns)), locus (locus),
1227 104 : node_id (Analysis::Mappings::get ().get_next_node_id ())
1228 104 : {}
1229 :
1230 241 : location_t get_locus () const override final { return locus; }
1231 :
1232 : void accept_vis (ASTVisitor &vis) override;
1233 :
1234 : // TODO: seems kinda dodgy. Think of better way.
1235 75 : std::vector<std::unique_ptr<Pattern>> &get_patterns ()
1236 : {
1237 7191 : return patterns.get ();
1238 : }
1239 :
1240 531 : NodeId get_node_id () const override { return node_id; }
1241 :
1242 731 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Slice; }
1243 :
1244 : protected:
1245 : /* Use covariance to implement clone function as returning this object rather
1246 : * than base */
1247 118 : SlicePattern *clone_pattern_impl () const override
1248 : {
1249 118 : return new SlicePattern (*this);
1250 : }
1251 : };
1252 :
1253 : // AST node for alternate patterns
1254 : // joins together what are technically 'PatternNoTopAlt's
1255 1442 : class AltPattern : public Pattern
1256 : {
1257 : Cloneable<std::vector<std::unique_ptr<Pattern>>> alts;
1258 : location_t locus;
1259 : NodeId node_id;
1260 :
1261 : public:
1262 : std::string as_string () const override;
1263 :
1264 248 : AltPattern (std::vector<std::unique_ptr<Pattern>> alts, location_t locus)
1265 248 : : alts (std::move (alts)), locus (locus),
1266 248 : node_id (Analysis::Mappings::get ().get_next_node_id ())
1267 248 : {}
1268 :
1269 298 : location_t get_locus () const override final { return locus; }
1270 :
1271 : void accept_vis (ASTVisitor &vis) override;
1272 :
1273 : // TODO: seems kinda dodgy. Think of better way.
1274 18580 : std::vector<std::unique_ptr<Pattern>> &get_alts () { return alts.get (); }
1275 : const std::vector<std::unique_ptr<Pattern>> &get_alts () const
1276 : {
1277 : return alts.get ();
1278 : }
1279 :
1280 1803 : NodeId get_node_id () const override { return node_id; }
1281 :
1282 1687 : Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Alt; }
1283 :
1284 : protected:
1285 : /* Use covariance to implement clone function as returning this object rather
1286 : * than base */
1287 721 : AltPattern *clone_pattern_impl () const override
1288 : {
1289 721 : return new AltPattern (*this);
1290 : }
1291 : };
1292 :
1293 : // Moved definition to rust-path.h
1294 : class Path;
1295 :
1296 : // Forward decls for paths (defined in rust-path.h)
1297 : class PathInExpression;
1298 : class QualifiedPathInExpression;
1299 :
1300 : // Replaced with forward decl - defined in rust-macro.h
1301 : class MacroInvocation;
1302 : } // namespace AST
1303 :
1304 : template <> struct CloneableDelegate<std::unique_ptr<AST::RangePatternBound>>
1305 : {
1306 : static std::unique_ptr<AST::RangePatternBound>
1307 880 : clone (const std::unique_ptr<AST::RangePatternBound> &other)
1308 : {
1309 880 : if (other == nullptr)
1310 1 : return nullptr;
1311 : else
1312 879 : return other->clone_range_pattern_bound ();
1313 : }
1314 : };
1315 :
1316 : template <> struct CloneableDelegate<std::unique_ptr<AST::TupleStructItems>>
1317 : {
1318 : static std::unique_ptr<AST::TupleStructItems>
1319 7530 : clone (const std::unique_ptr<AST::TupleStructItems> &other)
1320 : {
1321 7530 : if (other == nullptr)
1322 0 : return nullptr;
1323 : else
1324 7530 : return other->clone_tuple_struct_items ();
1325 : }
1326 : };
1327 :
1328 : template <> struct CloneableDelegate<std::unique_ptr<AST::TuplePatternItems>>
1329 : {
1330 : static std::unique_ptr<AST::TuplePatternItems>
1331 19454 : clone (const std::unique_ptr<AST::TuplePatternItems> &other)
1332 : {
1333 19454 : if (other == nullptr)
1334 0 : return nullptr;
1335 : else
1336 19454 : return other->clone_tuple_pattern_items ();
1337 : }
1338 : };
1339 :
1340 : template <> struct CloneableDelegate<std::unique_ptr<AST::StructPatternField>>
1341 : {
1342 : static std::unique_ptr<AST::StructPatternField>
1343 897 : clone (const std::unique_ptr<AST::StructPatternField> &other)
1344 : {
1345 897 : if (other == nullptr)
1346 0 : return nullptr;
1347 : else
1348 897 : return other->clone_struct_pattern_field ();
1349 : }
1350 : };
1351 :
1352 : } // namespace Rust
1353 :
1354 : #endif
|