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