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