| // Copyright (C) 2020-2023 Free Software Foundation, Inc. |
| |
| // This file is part of GCC. |
| |
| // GCC is free software; you can redistribute it and/or modify it under |
| // the terms of the GNU General Public License as published by the Free |
| // Software Foundation; either version 3, or (at your option) any later |
| // version. |
| |
| // GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
| // WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| // for more details. |
| |
| // You should have received a copy of the GNU General Public License |
| // along with GCC; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| |
| #ifndef RUST_AST_PATTERN_H |
| #define RUST_AST_PATTERN_H |
| |
| #include "rust-ast.h" |
| |
| namespace Rust { |
| namespace AST { |
| // Literal pattern AST node (comparing to a literal) |
| class LiteralPattern : public Pattern |
| { |
| Literal lit; |
| Location locus; |
| NodeId node_id; |
| |
| public: |
| std::string as_string () const override; |
| |
| // Constructor for a literal pattern |
| LiteralPattern (Literal lit, Location locus) |
| : lit (std::move (lit)), locus (locus), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| LiteralPattern (std::string val, Literal::LitType type, Location locus) |
| : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)), |
| locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| Location get_locus () const override final { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| Literal &get_literal () { return lit; } |
| |
| const Literal &get_literal () const { return lit; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| virtual LiteralPattern *clone_pattern_impl () const override |
| { |
| return new LiteralPattern (*this); |
| } |
| }; |
| |
| // Identifier pattern AST node (bind value matched to a variable) |
| class IdentifierPattern : public Pattern |
| { |
| Identifier variable_ident; |
| bool is_ref; |
| bool is_mut; |
| |
| // bool has_pattern; |
| std::unique_ptr<Pattern> to_bind; |
| Location locus; |
| NodeId node_id; |
| |
| public: |
| std::string as_string () const override; |
| |
| // Returns whether the IdentifierPattern has a pattern to bind. |
| bool has_pattern_to_bind () const { return to_bind != nullptr; } |
| |
| // Constructor |
| IdentifierPattern (Identifier ident, Location locus, bool is_ref = false, |
| bool is_mut = false, |
| std::unique_ptr<Pattern> to_bind = nullptr) |
| : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), |
| is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| IdentifierPattern (NodeId node_id, Identifier ident, Location locus, |
| bool is_ref = false, bool is_mut = false, |
| std::unique_ptr<Pattern> to_bind = nullptr) |
| : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), |
| is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), |
| node_id (node_id) |
| {} |
| |
| // Copy constructor with clone |
| IdentifierPattern (IdentifierPattern const &other) |
| : variable_ident (other.variable_ident), is_ref (other.is_ref), |
| is_mut (other.is_mut), locus (other.locus), node_id (other.node_id) |
| { |
| // fix to get prevent null pointer dereference |
| if (other.to_bind != nullptr) |
| to_bind = other.to_bind->clone_pattern (); |
| } |
| |
| // Overload assignment operator to use clone |
| IdentifierPattern &operator= (IdentifierPattern const &other) |
| { |
| variable_ident = other.variable_ident; |
| is_ref = other.is_ref; |
| is_mut = other.is_mut; |
| locus = other.locus; |
| node_id = other.node_id; |
| |
| // fix to prevent null pointer dereference |
| if (other.to_bind != nullptr) |
| to_bind = other.to_bind->clone_pattern (); |
| else |
| to_bind = nullptr; |
| |
| return *this; |
| } |
| |
| // default move semantics |
| IdentifierPattern (IdentifierPattern &&other) = default; |
| IdentifierPattern &operator= (IdentifierPattern &&other) = default; |
| |
| Location get_locus () const override final { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: is this better? Or is a "vis_pattern" better? |
| std::unique_ptr<Pattern> &get_pattern_to_bind () |
| { |
| rust_assert (has_pattern_to_bind ()); |
| return to_bind; |
| } |
| |
| Identifier get_ident () const { return variable_ident; } |
| |
| bool get_is_mut () const { return is_mut; } |
| bool get_is_ref () const { return is_ref; } |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| IdentifierPattern *clone_pattern_impl () const override |
| { |
| return new IdentifierPattern (*this); |
| } |
| }; |
| |
| // AST node for using the '_' wildcard "match any value" pattern |
| class WildcardPattern : public Pattern |
| { |
| Location locus; |
| NodeId node_id; |
| |
| public: |
| std::string as_string () const override { return std::string (1, '_'); } |
| |
| WildcardPattern (Location locus) |
| : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| Location get_locus () const override final { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| WildcardPattern *clone_pattern_impl () const override |
| { |
| return new WildcardPattern (*this); |
| } |
| }; |
| |
| // Base range pattern bound (lower or upper limit) - abstract |
| class RangePatternBound |
| { |
| public: |
| enum RangePatternBoundType |
| { |
| LITERAL, |
| PATH, |
| QUALPATH |
| }; |
| |
| virtual ~RangePatternBound () {} |
| |
| // Unique pointer custom clone function |
| std::unique_ptr<RangePatternBound> clone_range_pattern_bound () const |
| { |
| return std::unique_ptr<RangePatternBound> ( |
| clone_range_pattern_bound_impl ()); |
| } |
| |
| virtual std::string as_string () const = 0; |
| |
| virtual void accept_vis (ASTVisitor &vis) = 0; |
| |
| virtual RangePatternBoundType get_bound_type () const = 0; |
| |
| protected: |
| // pure virtual as RangePatternBound is abstract |
| virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0; |
| }; |
| |
| // Literal-based pattern bound |
| class RangePatternBoundLiteral : public RangePatternBound |
| { |
| Literal literal; |
| /* Can only be a char, byte, int, or float literal - same impl here as |
| * previously */ |
| |
| // Minus prefixed to literal (if integer or floating-point) |
| bool has_minus; |
| |
| Location locus; |
| |
| public: |
| // Constructor |
| RangePatternBoundLiteral (Literal literal, Location locus, |
| bool has_minus = false) |
| : literal (literal), has_minus (has_minus), locus (locus) |
| {} |
| |
| std::string as_string () const override; |
| |
| Literal get_literal () const { return literal; } |
| |
| bool get_has_minus () const { return has_minus; } |
| |
| Location get_locus () const { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| RangePatternBoundType get_bound_type () const override |
| { |
| return RangePatternBoundType::LITERAL; |
| } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| RangePatternBoundLiteral *clone_range_pattern_bound_impl () const override |
| { |
| return new RangePatternBoundLiteral (*this); |
| } |
| }; |
| |
| // Path-based pattern bound |
| class RangePatternBoundPath : public RangePatternBound |
| { |
| PathInExpression path; |
| |
| /* TODO: should this be refactored so that PathInExpression is a subclass of |
| * RangePatternBound? */ |
| |
| public: |
| RangePatternBoundPath (PathInExpression path) : path (std::move (path)) {} |
| |
| std::string as_string () const override { return path.as_string (); } |
| |
| Location get_locus () const { return path.get_locus (); } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: this mutable getter seems kinda dodgy |
| PathInExpression &get_path () { return path; } |
| const PathInExpression &get_path () const { return path; } |
| |
| RangePatternBoundType get_bound_type () const override |
| { |
| return RangePatternBoundType::PATH; |
| } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| RangePatternBoundPath *clone_range_pattern_bound_impl () const override |
| { |
| return new RangePatternBoundPath (*this); |
| } |
| }; |
| |
| // Qualified path-based pattern bound |
| class RangePatternBoundQualPath : public RangePatternBound |
| { |
| QualifiedPathInExpression path; |
| |
| /* TODO: should this be refactored so that QualifiedPathInExpression is a |
| * subclass of RangePatternBound? */ |
| |
| public: |
| RangePatternBoundQualPath (QualifiedPathInExpression path) |
| : path (std::move (path)) |
| {} |
| |
| std::string as_string () const override { return path.as_string (); } |
| |
| Location get_locus () const { return path.get_locus (); } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: this mutable getter seems kinda dodgy |
| QualifiedPathInExpression &get_qualified_path () { return path; } |
| const QualifiedPathInExpression &get_qualified_path () const { return path; } |
| |
| RangePatternBoundType get_bound_type () const override |
| { |
| return RangePatternBoundType::QUALPATH; |
| } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| RangePatternBoundQualPath *clone_range_pattern_bound_impl () const override |
| { |
| return new RangePatternBoundQualPath (*this); |
| } |
| }; |
| |
| // AST node for matching within a certain range (range pattern) |
| class RangePattern : public Pattern |
| { |
| std::unique_ptr<RangePatternBound> lower; |
| std::unique_ptr<RangePatternBound> upper; |
| |
| bool has_ellipsis_syntax; |
| |
| /* location only stored to avoid a dereference - lower pattern should give |
| * correct location so maybe change in future */ |
| Location locus; |
| NodeId node_id; |
| |
| public: |
| std::string as_string () const override; |
| |
| // Constructor |
| RangePattern (std::unique_ptr<RangePatternBound> lower, |
| std::unique_ptr<RangePatternBound> upper, Location locus, |
| bool has_ellipsis_syntax = false) |
| : lower (std::move (lower)), upper (std::move (upper)), |
| has_ellipsis_syntax (has_ellipsis_syntax), locus (locus), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| // Copy constructor with clone |
| RangePattern (RangePattern const &other) |
| : lower (other.lower->clone_range_pattern_bound ()), |
| upper (other.upper->clone_range_pattern_bound ()), |
| has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus), |
| node_id (other.node_id) |
| {} |
| |
| // Overloaded assignment operator to clone |
| RangePattern &operator= (RangePattern const &other) |
| { |
| lower = other.lower->clone_range_pattern_bound (); |
| upper = other.upper->clone_range_pattern_bound (); |
| has_ellipsis_syntax = other.has_ellipsis_syntax; |
| locus = other.locus; |
| node_id = other.node_id; |
| |
| return *this; |
| } |
| |
| // default move semantics |
| RangePattern (RangePattern &&other) = default; |
| RangePattern &operator= (RangePattern &&other) = default; |
| |
| Location get_locus () const override final { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: is this better? or is a "vis_bound" better? |
| std::unique_ptr<RangePatternBound> &get_lower_bound () |
| { |
| rust_assert (lower != nullptr); |
| return lower; |
| } |
| |
| std::unique_ptr<RangePatternBound> &get_upper_bound () |
| { |
| rust_assert (upper != nullptr); |
| return upper; |
| } |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| RangePattern *clone_pattern_impl () const override |
| { |
| return new RangePattern (*this); |
| } |
| }; |
| |
| // AST node for pattern based on dereferencing the pointers given |
| class ReferencePattern : public Pattern |
| { |
| bool has_two_amps; |
| bool is_mut; |
| std::unique_ptr<Pattern> pattern; |
| Location locus; |
| NodeId node_id; |
| |
| public: |
| std::string as_string () const override; |
| |
| ReferencePattern (std::unique_ptr<Pattern> pattern, bool is_mut_reference, |
| bool ref_has_two_amps, Location locus) |
| : has_two_amps (ref_has_two_amps), is_mut (is_mut_reference), |
| pattern (std::move (pattern)), locus (locus), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| // Copy constructor requires clone |
| ReferencePattern (ReferencePattern const &other) |
| : has_two_amps (other.has_two_amps), is_mut (other.is_mut), |
| pattern (other.pattern->clone_pattern ()), locus (other.locus), |
| node_id (other.node_id) |
| {} |
| |
| // Overload assignment operator to clone |
| ReferencePattern &operator= (ReferencePattern const &other) |
| { |
| pattern = other.pattern->clone_pattern (); |
| is_mut = other.is_mut; |
| has_two_amps = other.has_two_amps; |
| locus = other.locus; |
| node_id = other.node_id; |
| |
| return *this; |
| } |
| |
| // default move semantics |
| ReferencePattern (ReferencePattern &&other) = default; |
| ReferencePattern &operator= (ReferencePattern &&other) = default; |
| |
| Location get_locus () const override final { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: is this better? Or is a "vis_pattern" better? |
| std::unique_ptr<Pattern> &get_referenced_pattern () |
| { |
| rust_assert (pattern != nullptr); |
| return pattern; |
| } |
| |
| bool is_double_reference () const { return has_two_amps; } |
| |
| bool get_is_mut () const { return is_mut; } |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| ReferencePattern *clone_pattern_impl () const override |
| { |
| return new ReferencePattern (*this); |
| } |
| }; |
| |
| #if 0 |
| // aka StructPatternEtCetera; potential element in struct pattern |
| struct StructPatternEtc |
| { |
| private: |
| std::vector<Attribute> outer_attrs; |
| |
| // should this store location data? |
| |
| public: |
| StructPatternEtc (std::vector<Attribute> outer_attribs) |
| : outer_attrs (std::move (outer_attribs)) |
| {} |
| |
| // Creates an empty StructPatternEtc |
| static StructPatternEtc create_empty () |
| { |
| return StructPatternEtc (std::vector<Attribute> ()); |
| } |
| }; |
| #endif |
| |
| // Base class for a single field in a struct pattern - abstract |
| class StructPatternField |
| { |
| std::vector<Attribute> outer_attrs; |
| Location locus; |
| |
| protected: |
| NodeId node_id; |
| |
| public: |
| enum ItemType |
| { |
| TUPLE_PAT, |
| IDENT_PAT, |
| IDENT |
| }; |
| |
| virtual ~StructPatternField () {} |
| |
| // Unique pointer custom clone function |
| std::unique_ptr<StructPatternField> clone_struct_pattern_field () const |
| { |
| return std::unique_ptr<StructPatternField> ( |
| clone_struct_pattern_field_impl ()); |
| } |
| |
| virtual std::string as_string () const; |
| |
| Location get_locus () const { return locus; } |
| |
| virtual void accept_vis (ASTVisitor &vis) = 0; |
| |
| virtual void mark_for_strip () = 0; |
| virtual bool is_marked_for_strip () const = 0; |
| virtual ItemType get_item_type () const = 0; |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } |
| const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } |
| |
| protected: |
| StructPatternField (std::vector<Attribute> outer_attribs, Location locus, |
| NodeId node_id) |
| : outer_attrs (std::move (outer_attribs)), locus (locus), node_id (node_id) |
| {} |
| |
| // Clone function implementation as pure virtual method |
| virtual StructPatternField *clone_struct_pattern_field_impl () const = 0; |
| }; |
| |
| // Tuple pattern single field in a struct pattern |
| class StructPatternFieldTuplePat : public StructPatternField |
| { |
| TupleIndex index; |
| std::unique_ptr<Pattern> tuple_pattern; |
| |
| public: |
| StructPatternFieldTuplePat (TupleIndex index, |
| std::unique_ptr<Pattern> tuple_pattern, |
| std::vector<Attribute> outer_attribs, |
| Location locus) |
| : StructPatternField (std::move (outer_attribs), locus, |
| Analysis::Mappings::get ()->get_next_node_id ()), |
| index (index), tuple_pattern (std::move (tuple_pattern)) |
| {} |
| |
| // Copy constructor requires clone |
| StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other) |
| : StructPatternField (other), index (other.index) |
| { |
| // guard to prevent null dereference (only required if error state) |
| node_id = other.get_node_id (); |
| if (other.tuple_pattern != nullptr) |
| tuple_pattern = other.tuple_pattern->clone_pattern (); |
| } |
| |
| // Overload assignment operator to perform clone |
| StructPatternFieldTuplePat & |
| operator= (StructPatternFieldTuplePat const &other) |
| { |
| StructPatternField::operator= (other); |
| index = other.index; |
| // outer_attrs = other.outer_attrs; |
| node_id = other.get_node_id (); |
| |
| // guard to prevent null dereference (only required if error state) |
| if (other.tuple_pattern != nullptr) |
| tuple_pattern = other.tuple_pattern->clone_pattern (); |
| else |
| tuple_pattern = nullptr; |
| |
| return *this; |
| } |
| |
| // default move semantics |
| StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default; |
| StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other) |
| = default; |
| |
| std::string as_string () const override; |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // based on idea of tuple pattern no longer existing |
| void mark_for_strip () override { tuple_pattern = nullptr; } |
| bool is_marked_for_strip () const override |
| { |
| return tuple_pattern == nullptr; |
| } |
| |
| // TODO: is this better? Or is a "vis_pattern" better? |
| std::unique_ptr<Pattern> &get_index_pattern () |
| { |
| rust_assert (tuple_pattern != nullptr); |
| return tuple_pattern; |
| } |
| |
| ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| StructPatternFieldTuplePat *clone_struct_pattern_field_impl () const override |
| { |
| return new StructPatternFieldTuplePat (*this); |
| } |
| }; |
| |
| // Identifier pattern single field in a struct pattern |
| class StructPatternFieldIdentPat : public StructPatternField |
| { |
| Identifier ident; |
| std::unique_ptr<Pattern> ident_pattern; |
| |
| public: |
| StructPatternFieldIdentPat (Identifier ident, |
| std::unique_ptr<Pattern> ident_pattern, |
| std::vector<Attribute> outer_attrs, |
| Location locus) |
| : StructPatternField (std::move (outer_attrs), locus, |
| Analysis::Mappings::get ()->get_next_node_id ()), |
| ident (std::move (ident)), ident_pattern (std::move (ident_pattern)) |
| {} |
| |
| // Copy constructor requires clone |
| StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other) |
| : StructPatternField (other), ident (other.ident) |
| { |
| // guard to prevent null dereference (only required if error state) |
| node_id = other.get_node_id (); |
| if (other.ident_pattern != nullptr) |
| ident_pattern = other.ident_pattern->clone_pattern (); |
| } |
| |
| // Overload assignment operator to clone |
| StructPatternFieldIdentPat & |
| operator= (StructPatternFieldIdentPat const &other) |
| { |
| StructPatternField::operator= (other); |
| ident = other.ident; |
| // outer_attrs = other.outer_attrs; |
| node_id = other.get_node_id (); |
| |
| // guard to prevent null dereference (only required if error state) |
| if (other.ident_pattern != nullptr) |
| ident_pattern = other.ident_pattern->clone_pattern (); |
| else |
| ident_pattern = nullptr; |
| |
| return *this; |
| } |
| |
| // default move semantics |
| StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default; |
| StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other) |
| = default; |
| |
| std::string as_string () const override; |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // based on idea of identifier pattern no longer existing |
| void mark_for_strip () override { ident_pattern = nullptr; } |
| bool is_marked_for_strip () const override |
| { |
| return ident_pattern == nullptr; |
| } |
| |
| const Identifier &get_identifier () const { return ident; } |
| |
| // TODO: is this better? Or is a "vis_pattern" better? |
| std::unique_ptr<Pattern> &get_ident_pattern () |
| { |
| rust_assert (ident_pattern != nullptr); |
| return ident_pattern; |
| } |
| |
| ItemType get_item_type () const override final { return ItemType::IDENT_PAT; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| StructPatternFieldIdentPat *clone_struct_pattern_field_impl () const override |
| { |
| return new StructPatternFieldIdentPat (*this); |
| } |
| }; |
| |
| // Identifier only (with no pattern) single field in a struct pattern |
| class StructPatternFieldIdent : public StructPatternField |
| { |
| bool has_ref; |
| bool has_mut; |
| Identifier ident; |
| |
| public: |
| StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut, |
| std::vector<Attribute> outer_attrs, Location locus) |
| : StructPatternField (std::move (outer_attrs), locus, |
| Analysis::Mappings::get ()->get_next_node_id ()), |
| has_ref (is_ref), has_mut (is_mut), ident (std::move (ident)) |
| {} |
| |
| std::string as_string () const override; |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // based on idea of identifier no longer existing |
| void mark_for_strip () override { ident = {}; } |
| bool is_marked_for_strip () const override { return ident.empty (); } |
| |
| const Identifier &get_identifier () const { return ident; } |
| |
| ItemType get_item_type () const override final { return ItemType::IDENT; } |
| |
| bool is_ref () const { return has_ref; } |
| |
| bool is_mut () const { return has_mut; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| StructPatternFieldIdent *clone_struct_pattern_field_impl () const override |
| { |
| return new StructPatternFieldIdent (*this); |
| } |
| }; |
| |
| // Elements of a struct pattern |
| struct StructPatternElements |
| { |
| private: |
| // bool has_struct_pattern_fields; |
| std::vector<std::unique_ptr<StructPatternField>> fields; |
| |
| bool has_struct_pattern_etc; |
| std::vector<Attribute> struct_pattern_etc_attrs; |
| // StructPatternEtc etc; |
| |
| // must have at least one of the two and maybe both |
| |
| // should this store location data? |
| |
| public: |
| // Returns whether there are any struct pattern fields |
| bool has_struct_pattern_fields () const { return !fields.empty (); } |
| |
| /* Returns whether the struct pattern elements is entirely empty (no fields, |
| * no etc). */ |
| bool is_empty () const |
| { |
| return !has_struct_pattern_fields () && !has_struct_pattern_etc; |
| } |
| |
| bool has_etc () const { return has_struct_pattern_etc; } |
| |
| // Constructor for StructPatternElements with both (potentially) |
| StructPatternElements ( |
| std::vector<std::unique_ptr<StructPatternField>> fields, |
| std::vector<Attribute> etc_attrs) |
| : fields (std::move (fields)), has_struct_pattern_etc (true), |
| struct_pattern_etc_attrs (std::move (etc_attrs)) |
| {} |
| |
| // Constructor for StructPatternElements with no StructPatternEtc |
| StructPatternElements ( |
| std::vector<std::unique_ptr<StructPatternField>> fields) |
| : fields (std::move (fields)), has_struct_pattern_etc (false), |
| struct_pattern_etc_attrs () |
| {} |
| |
| // Copy constructor with vector clone |
| StructPatternElements (StructPatternElements const &other) |
| : has_struct_pattern_etc (other.has_struct_pattern_etc), |
| struct_pattern_etc_attrs (other.struct_pattern_etc_attrs) |
| { |
| fields.reserve (other.fields.size ()); |
| for (const auto &e : other.fields) |
| fields.push_back (e->clone_struct_pattern_field ()); |
| } |
| |
| // Overloaded assignment operator with vector clone |
| StructPatternElements &operator= (StructPatternElements const &other) |
| { |
| struct_pattern_etc_attrs = other.struct_pattern_etc_attrs; |
| has_struct_pattern_etc = other.has_struct_pattern_etc; |
| |
| fields.reserve (other.fields.size ()); |
| for (const auto &e : other.fields) |
| fields.push_back (e->clone_struct_pattern_field ()); |
| |
| return *this; |
| } |
| |
| // move constructors |
| StructPatternElements (StructPatternElements &&other) = default; |
| StructPatternElements &operator= (StructPatternElements &&other) = default; |
| |
| // Creates an empty StructPatternElements |
| static StructPatternElements create_empty () |
| { |
| return StructPatternElements ( |
| std::vector<std::unique_ptr<StructPatternField>> ()); |
| } |
| |
| std::string as_string () const; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields () |
| { |
| return fields; |
| } |
| const std::vector<std::unique_ptr<StructPatternField>> & |
| get_struct_pattern_fields () const |
| { |
| return fields; |
| } |
| |
| std::vector<Attribute> &get_etc_outer_attrs () |
| { |
| return struct_pattern_etc_attrs; |
| } |
| const std::vector<Attribute> &get_etc_outer_attrs () const |
| { |
| return struct_pattern_etc_attrs; |
| } |
| |
| void strip_etc () |
| { |
| has_struct_pattern_etc = false; |
| struct_pattern_etc_attrs.clear (); |
| struct_pattern_etc_attrs.shrink_to_fit (); |
| } |
| }; |
| |
| // Struct pattern AST node representation |
| class StructPattern : public Pattern |
| { |
| PathInExpression path; |
| |
| // bool has_struct_pattern_elements; |
| StructPatternElements elems; |
| |
| NodeId node_id; |
| Location locus; |
| |
| public: |
| std::string as_string () const override; |
| |
| // Constructs a struct pattern from specified StructPatternElements |
| StructPattern (PathInExpression struct_path, Location locus, |
| StructPatternElements elems |
| = StructPatternElements::create_empty ()) |
| : path (std::move (struct_path)), elems (std::move (elems)), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) |
| {} |
| |
| /* TODO: constructor to construct via elements included in |
| * StructPatternElements */ |
| |
| /* Returns whether struct pattern has any struct pattern elements (if not, it |
| * is empty). */ |
| bool has_struct_pattern_elems () const { return !elems.is_empty (); } |
| |
| Location get_locus () const { return path.get_locus (); } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| StructPatternElements &get_struct_pattern_elems () { return elems; } |
| const StructPatternElements &get_struct_pattern_elems () const |
| { |
| return elems; |
| } |
| |
| PathInExpression &get_path () { return path; } |
| const PathInExpression &get_path () const { return path; } |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| StructPattern *clone_pattern_impl () const override |
| { |
| return new StructPattern (*this); |
| } |
| }; |
| |
| // Base abstract class for patterns used in TupleStructPattern |
| class TupleStructItems |
| { |
| public: |
| enum ItemType |
| { |
| RANGE, |
| NO_RANGE |
| }; |
| |
| virtual ~TupleStructItems () {} |
| |
| // TODO: should this store location data? |
| |
| // Unique pointer custom clone function |
| std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const |
| { |
| return std::unique_ptr<TupleStructItems> (clone_tuple_struct_items_impl ()); |
| } |
| |
| virtual std::string as_string () const = 0; |
| |
| virtual void accept_vis (ASTVisitor &vis) = 0; |
| |
| virtual ItemType get_item_type () const = 0; |
| |
| protected: |
| // pure virtual clone implementation |
| virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0; |
| }; |
| |
| // Class for non-ranged tuple struct pattern patterns |
| class TupleStructItemsNoRange : public TupleStructItems |
| { |
| std::vector<std::unique_ptr<Pattern>> patterns; |
| |
| public: |
| TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns) |
| : patterns (std::move (patterns)) |
| {} |
| |
| // Copy constructor with vector clone |
| TupleStructItemsNoRange (TupleStructItemsNoRange const &other) |
| { |
| patterns.reserve (other.patterns.size ()); |
| for (const auto &e : other.patterns) |
| patterns.push_back (e->clone_pattern ()); |
| } |
| |
| // Overloaded assignment operator with vector clone |
| TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other) |
| { |
| patterns.reserve (other.patterns.size ()); |
| for (const auto &e : other.patterns) |
| patterns.push_back (e->clone_pattern ()); |
| |
| return *this; |
| } |
| |
| // move constructors |
| TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default; |
| TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other) |
| = default; |
| |
| std::string as_string () const override; |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; } |
| const std::vector<std::unique_ptr<Pattern>> &get_patterns () const |
| { |
| return patterns; |
| } |
| |
| ItemType get_item_type () const override final { return ItemType::NO_RANGE; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| TupleStructItemsNoRange *clone_tuple_struct_items_impl () const override |
| { |
| return new TupleStructItemsNoRange (*this); |
| } |
| }; |
| |
| // Class for ranged tuple struct pattern patterns |
| class TupleStructItemsRange : public TupleStructItems |
| { |
| std::vector<std::unique_ptr<Pattern>> lower_patterns; |
| std::vector<std::unique_ptr<Pattern>> upper_patterns; |
| |
| public: |
| TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns, |
| std::vector<std::unique_ptr<Pattern>> upper_patterns) |
| : lower_patterns (std::move (lower_patterns)), |
| upper_patterns (std::move (upper_patterns)) |
| {} |
| |
| // Copy constructor with vector clone |
| TupleStructItemsRange (TupleStructItemsRange const &other) |
| { |
| lower_patterns.reserve (other.lower_patterns.size ()); |
| for (const auto &e : other.lower_patterns) |
| lower_patterns.push_back (e->clone_pattern ()); |
| |
| upper_patterns.reserve (other.upper_patterns.size ()); |
| for (const auto &e : other.upper_patterns) |
| upper_patterns.push_back (e->clone_pattern ()); |
| } |
| |
| // Overloaded assignment operator to clone |
| TupleStructItemsRange &operator= (TupleStructItemsRange const &other) |
| { |
| lower_patterns.reserve (other.lower_patterns.size ()); |
| for (const auto &e : other.lower_patterns) |
| lower_patterns.push_back (e->clone_pattern ()); |
| |
| upper_patterns.reserve (other.upper_patterns.size ()); |
| for (const auto &e : other.upper_patterns) |
| upper_patterns.push_back (e->clone_pattern ()); |
| |
| return *this; |
| } |
| |
| // move constructors |
| TupleStructItemsRange (TupleStructItemsRange &&other) = default; |
| TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default; |
| |
| std::string as_string () const override; |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () |
| { |
| return lower_patterns; |
| } |
| const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const |
| { |
| return lower_patterns; |
| } |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () |
| { |
| return upper_patterns; |
| } |
| const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const |
| { |
| return upper_patterns; |
| } |
| |
| ItemType get_item_type () const override final { return ItemType::RANGE; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| TupleStructItemsRange *clone_tuple_struct_items_impl () const override |
| { |
| return new TupleStructItemsRange (*this); |
| } |
| }; |
| |
| // AST node representing a tuple struct pattern |
| class TupleStructPattern : public Pattern |
| { |
| PathInExpression path; |
| std::unique_ptr<TupleStructItems> items; |
| NodeId node_id; |
| |
| /* TOOD: should this store location data? current accessor uses path location |
| * data */ |
| |
| public: |
| std::string as_string () const override; |
| |
| // Returns whether the pattern has tuple struct items. |
| bool has_items () const { return items != nullptr; } |
| |
| TupleStructPattern (PathInExpression tuple_struct_path, |
| std::unique_ptr<TupleStructItems> items) |
| : path (std::move (tuple_struct_path)), items (std::move (items)), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| // Copy constructor required to clone |
| TupleStructPattern (TupleStructPattern const &other) : path (other.path) |
| { |
| // guard to protect from null dereference |
| node_id = other.node_id; |
| if (other.items != nullptr) |
| items = other.items->clone_tuple_struct_items (); |
| } |
| |
| // Operator overload assignment operator to clone |
| TupleStructPattern &operator= (TupleStructPattern const &other) |
| { |
| path = other.path; |
| node_id = other.node_id; |
| |
| // guard to protect from null dereference |
| if (other.items != nullptr) |
| items = other.items->clone_tuple_struct_items (); |
| else |
| items = nullptr; |
| |
| return *this; |
| } |
| |
| // move constructors |
| TupleStructPattern (TupleStructPattern &&other) = default; |
| TupleStructPattern &operator= (TupleStructPattern &&other) = default; |
| |
| Location get_locus () const override { return path.get_locus (); } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::unique_ptr<TupleStructItems> &get_items () |
| { |
| rust_assert (has_items ()); |
| return items; |
| } |
| |
| PathInExpression &get_path () { return path; } |
| const PathInExpression &get_path () const { return path; } |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| TupleStructPattern *clone_pattern_impl () const override |
| { |
| return new TupleStructPattern (*this); |
| } |
| }; |
| |
| // Base abstract class representing TuplePattern patterns |
| class TuplePatternItems |
| { |
| public: |
| enum TuplePatternItemType |
| { |
| MULTIPLE, |
| RANGED, |
| }; |
| |
| virtual ~TuplePatternItems () {} |
| |
| // TODO: should this store location data? |
| |
| // Unique pointer custom clone function |
| std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const |
| { |
| return std::unique_ptr<TuplePatternItems> ( |
| clone_tuple_pattern_items_impl ()); |
| } |
| |
| virtual std::string as_string () const = 0; |
| |
| virtual void accept_vis (ASTVisitor &vis) = 0; |
| |
| virtual TuplePatternItemType get_pattern_type () const = 0; |
| |
| protected: |
| // pure virtual clone implementation |
| virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0; |
| }; |
| |
| // Class representing TuplePattern patterns where there is only a single pattern |
| /*class TuplePatternItemsSingle : public TuplePatternItems { |
| // Pattern pattern; |
| std::unique_ptr<Pattern> pattern; |
| |
| public: |
| TuplePatternItemsSingle(Pattern* pattern) : pattern(pattern) {} |
| |
| // Copy constructor uses clone |
| TuplePatternItemsSingle(TuplePatternItemsSingle const& other) : |
| pattern(other.pattern->clone_pattern()) {} |
| |
| // Destructor - define here if required |
| |
| // Overload assignment operator to clone |
| TuplePatternItemsSingle& operator=(TuplePatternItemsSingle const& other) { |
| pattern = other.pattern->clone_pattern(); |
| |
| return *this; |
| } |
| |
| // move constructors |
| TuplePatternItemsSingle(TuplePatternItemsSingle&& other) = default; |
| TuplePatternItemsSingle& operator=(TuplePatternItemsSingle&& other) = |
| default; |
| |
| protected: |
| // Use covariance to implement clone function as returning this object |
| rather than base virtual TuplePatternItemsSingle* |
| clone_tuple_pattern_items_impl() const override { return new |
| TuplePatternItemsSingle(*this); |
| } |
| };*/ |
| // removed in favour of single-element TuplePatternItemsMultiple |
| |
| // Class representing TuplePattern patterns where there are multiple patterns |
| class TuplePatternItemsMultiple : public TuplePatternItems |
| { |
| std::vector<std::unique_ptr<Pattern>> patterns; |
| |
| public: |
| TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns) |
| : patterns (std::move (patterns)) |
| {} |
| |
| // Copy constructor with vector clone |
| TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other) |
| { |
| patterns.reserve (other.patterns.size ()); |
| for (const auto &e : other.patterns) |
| patterns.push_back (e->clone_pattern ()); |
| } |
| |
| // Overloaded assignment operator to vector clone |
| TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other) |
| { |
| patterns.reserve (other.patterns.size ()); |
| for (const auto &e : other.patterns) |
| patterns.push_back (e->clone_pattern ()); |
| |
| return *this; |
| } |
| |
| // move constructors |
| TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default; |
| TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other) |
| = default; |
| |
| std::string as_string () const override; |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; } |
| const std::vector<std::unique_ptr<Pattern>> &get_patterns () const |
| { |
| return patterns; |
| } |
| |
| TuplePatternItemType get_pattern_type () const override |
| { |
| return TuplePatternItemType::MULTIPLE; |
| } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| TuplePatternItemsMultiple *clone_tuple_pattern_items_impl () const override |
| { |
| return new TuplePatternItemsMultiple (*this); |
| } |
| }; |
| |
| // Class representing TuplePattern patterns where there are a range of patterns |
| class TuplePatternItemsRanged : public TuplePatternItems |
| { |
| std::vector<std::unique_ptr<Pattern>> lower_patterns; |
| std::vector<std::unique_ptr<Pattern>> upper_patterns; |
| |
| public: |
| TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns, |
| std::vector<std::unique_ptr<Pattern>> upper_patterns) |
| : lower_patterns (std::move (lower_patterns)), |
| upper_patterns (std::move (upper_patterns)) |
| {} |
| |
| // Copy constructor with vector clone |
| TuplePatternItemsRanged (TuplePatternItemsRanged const &other) |
| { |
| lower_patterns.reserve (other.lower_patterns.size ()); |
| for (const auto &e : other.lower_patterns) |
| lower_patterns.push_back (e->clone_pattern ()); |
| |
| upper_patterns.reserve (other.upper_patterns.size ()); |
| for (const auto &e : other.upper_patterns) |
| upper_patterns.push_back (e->clone_pattern ()); |
| } |
| |
| // Overloaded assignment operator to clone |
| TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other) |
| { |
| lower_patterns.reserve (other.lower_patterns.size ()); |
| for (const auto &e : other.lower_patterns) |
| lower_patterns.push_back (e->clone_pattern ()); |
| |
| upper_patterns.reserve (other.upper_patterns.size ()); |
| for (const auto &e : other.upper_patterns) |
| upper_patterns.push_back (e->clone_pattern ()); |
| |
| return *this; |
| } |
| |
| // move constructors |
| TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default; |
| TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other) |
| = default; |
| |
| std::string as_string () const override; |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () |
| { |
| return lower_patterns; |
| } |
| const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const |
| { |
| return lower_patterns; |
| } |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () |
| { |
| return upper_patterns; |
| } |
| const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const |
| { |
| return upper_patterns; |
| } |
| |
| TuplePatternItemType get_pattern_type () const override |
| { |
| return TuplePatternItemType::RANGED; |
| } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override |
| { |
| return new TuplePatternItemsRanged (*this); |
| } |
| }; |
| |
| // AST node representing a tuple pattern |
| class TuplePattern : public Pattern |
| { |
| // bool has_tuple_pattern_items; |
| std::unique_ptr<TuplePatternItems> items; |
| Location locus; |
| NodeId node_id; |
| |
| public: |
| std::string as_string () const override; |
| |
| // Returns true if the tuple pattern has items |
| bool has_tuple_pattern_items () const { return items != nullptr; } |
| |
| TuplePattern (std::unique_ptr<TuplePatternItems> items, Location locus) |
| : items (std::move (items)), locus (locus), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| // Copy constructor requires clone |
| TuplePattern (TuplePattern const &other) : locus (other.locus) |
| { |
| // guard to prevent null dereference |
| node_id = other.node_id; |
| if (other.items != nullptr) |
| items = other.items->clone_tuple_pattern_items (); |
| } |
| |
| // Overload assignment operator to clone |
| TuplePattern &operator= (TuplePattern const &other) |
| { |
| locus = other.locus; |
| node_id = other.node_id; |
| |
| // guard to prevent null dereference |
| if (other.items != nullptr) |
| items = other.items->clone_tuple_pattern_items (); |
| else |
| items = nullptr; |
| |
| return *this; |
| } |
| |
| Location get_locus () const override final { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::unique_ptr<TuplePatternItems> &get_items () |
| { |
| rust_assert (has_tuple_pattern_items ()); |
| return items; |
| } |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| TuplePattern *clone_pattern_impl () const override |
| { |
| return new TuplePattern (*this); |
| } |
| }; |
| |
| // AST node representing a pattern in parentheses, used to control precedence |
| class GroupedPattern : public Pattern |
| { |
| std::unique_ptr<Pattern> pattern_in_parens; |
| Location locus; |
| NodeId node_id; |
| |
| public: |
| std::string as_string () const override |
| { |
| return "(" + pattern_in_parens->as_string () + ")"; |
| } |
| |
| GroupedPattern (std::unique_ptr<Pattern> pattern_in_parens, Location locus) |
| : pattern_in_parens (std::move (pattern_in_parens)), locus (locus), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| // Copy constructor uses clone |
| GroupedPattern (GroupedPattern const &other) |
| : pattern_in_parens (other.pattern_in_parens->clone_pattern ()), |
| locus (other.locus), node_id (other.node_id) |
| {} |
| |
| // Overload assignment operator to clone |
| GroupedPattern &operator= (GroupedPattern const &other) |
| { |
| pattern_in_parens = other.pattern_in_parens->clone_pattern (); |
| locus = other.locus; |
| node_id = other.node_id; |
| |
| return *this; |
| } |
| |
| // default move semantics |
| GroupedPattern (GroupedPattern &&other) = default; |
| GroupedPattern &operator= (GroupedPattern &&other) = default; |
| |
| Location get_locus () const override final { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::unique_ptr<Pattern> &get_pattern_in_parens () |
| { |
| rust_assert (pattern_in_parens != nullptr); |
| return pattern_in_parens; |
| } |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| GroupedPattern *clone_pattern_impl () const override |
| { |
| return new GroupedPattern (*this); |
| } |
| }; |
| |
| // AST node representing patterns that can match slices and arrays |
| class SlicePattern : public Pattern |
| { |
| std::vector<std::unique_ptr<Pattern>> items; |
| Location locus; |
| NodeId node_id; |
| |
| public: |
| std::string as_string () const override; |
| |
| SlicePattern (std::vector<std::unique_ptr<Pattern>> items, Location locus) |
| : items (std::move (items)), locus (locus), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| // Copy constructor with vector clone |
| SlicePattern (SlicePattern const &other) : locus (other.locus) |
| { |
| node_id = other.node_id; |
| items.reserve (other.items.size ()); |
| for (const auto &e : other.items) |
| items.push_back (e->clone_pattern ()); |
| } |
| |
| // Overloaded assignment operator to vector clone |
| SlicePattern &operator= (SlicePattern const &other) |
| { |
| locus = other.locus; |
| node_id = other.node_id; |
| |
| items.reserve (other.items.size ()); |
| for (const auto &e : other.items) |
| items.push_back (e->clone_pattern ()); |
| |
| return *this; |
| } |
| |
| // move constructors |
| SlicePattern (SlicePattern &&other) = default; |
| SlicePattern &operator= (SlicePattern &&other) = default; |
| |
| Location get_locus () const override final { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<std::unique_ptr<Pattern>> &get_items () { return items; } |
| const std::vector<std::unique_ptr<Pattern>> &get_items () const |
| { |
| return items; |
| } |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| SlicePattern *clone_pattern_impl () const override |
| { |
| return new SlicePattern (*this); |
| } |
| }; |
| |
| // AST node for alternate patterns |
| // joins together what are technically 'PatternNoTopAlt's |
| class AltPattern : public Pattern |
| { |
| std::vector<std::unique_ptr<Pattern>> alts; |
| Location locus; |
| NodeId node_id; |
| |
| public: |
| std::string as_string () const override; |
| |
| AltPattern (std::vector<std::unique_ptr<Pattern>> alts, Location locus) |
| : alts (std::move (alts)), locus (locus), |
| node_id (Analysis::Mappings::get ()->get_next_node_id ()) |
| {} |
| |
| // Copy constructor with vector clone |
| AltPattern (AltPattern const &other) : locus (other.locus) |
| { |
| node_id = other.node_id; |
| alts.reserve (other.alts.size ()); |
| for (const auto &e : other.alts) |
| alts.push_back (e->clone_pattern ()); |
| } |
| |
| // Overloaded assignment operator to vector clone |
| AltPattern &operator= (AltPattern const &other) |
| { |
| locus = other.locus; |
| node_id = other.node_id; |
| |
| alts.reserve (other.alts.size ()); |
| for (const auto &e : other.alts) |
| alts.push_back (e->clone_pattern ()); |
| |
| return *this; |
| } |
| |
| // move constructors |
| AltPattern (AltPattern &&other) = default; |
| AltPattern &operator= (AltPattern &&other) = default; |
| |
| Location get_locus () const override final { return locus; } |
| |
| void accept_vis (ASTVisitor &vis) override; |
| |
| // TODO: seems kinda dodgy. Think of better way. |
| std::vector<std::unique_ptr<Pattern>> &get_alts () { return alts; } |
| const std::vector<std::unique_ptr<Pattern>> &get_alts () const |
| { |
| return alts; |
| } |
| |
| NodeId get_node_id () const { return node_id; } |
| |
| NodeId get_pattern_node_id () const override final { return node_id; } |
| |
| protected: |
| /* Use covariance to implement clone function as returning this object rather |
| * than base */ |
| AltPattern *clone_pattern_impl () const override |
| { |
| return new AltPattern (*this); |
| } |
| }; |
| |
| // Moved definition to rust-path.h |
| class PathPattern; |
| |
| // Forward decls for paths (defined in rust-path.h) |
| class PathInExpression; |
| class QualifiedPathInExpression; |
| |
| // Replaced with forward decl - defined in rust-macro.h |
| class MacroInvocation; |
| } // namespace AST |
| } // namespace Rust |
| |
| #endif |