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