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