(root)/
gcc-13.2.0/
gcc/
rust/
ast/
rust-pattern.h
       1  // Copyright (C) 2020-2023 Free Software Foundation, Inc.
       2  
       3  // This file is part of GCC.
       4  
       5  // GCC is free software; you can redistribute it and/or modify it under
       6  // the terms of the GNU General Public License as published by the Free
       7  // Software Foundation; either version 3, or (at your option) any later
       8  // version.
       9  
      10  // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11  // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13  // for more details.
      14  
      15  // You should have received a copy of the GNU General Public License
      16  // along with GCC; see the file COPYING3.  If not see
      17  // <http://www.gnu.org/licenses/>.
      18  
      19  #ifndef RUST_AST_PATTERN_H
      20  #define RUST_AST_PATTERN_H
      21  
      22  #include "rust-ast.h"
      23  
      24  namespace Rust {
      25  namespace AST {
      26  // Literal pattern AST node (comparing to a literal)
      27  class LiteralPattern : public Pattern
      28  {
      29    Literal lit;
      30    Location 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    bool is_double_reference () const { return has_two_amps; }
     473  
     474    bool get_is_mut () const { return is_mut; }
     475  
     476    NodeId get_node_id () const { return node_id; }
     477  
     478    NodeId get_pattern_node_id () const override final { return node_id; }
     479  
     480  protected:
     481    /* Use covariance to implement clone function as returning this object rather
     482     * than base */
     483    ReferencePattern *clone_pattern_impl () const override
     484    {
     485      return new ReferencePattern (*this);
     486    }
     487  };
     488  
     489  #if 0
     490  // aka StructPatternEtCetera; potential element in struct pattern
     491  struct StructPatternEtc
     492  {
     493  private:
     494    std::vector<Attribute> outer_attrs;
     495  
     496    // should this store location data?
     497  
     498  public:
     499    StructPatternEtc (std::vector<Attribute> outer_attribs)
     500      : outer_attrs (std::move (outer_attribs))
     501    {}
     502  
     503    // Creates an empty StructPatternEtc
     504    static StructPatternEtc create_empty ()
     505    {
     506      return StructPatternEtc (std::vector<Attribute> ());
     507    }
     508  };
     509  #endif
     510  
     511  // Base class for a single field in a struct pattern - abstract
     512  class StructPatternField
     513  {
     514    std::vector<Attribute> outer_attrs;
     515    Location locus;
     516  
     517  protected:
     518    NodeId node_id;
     519  
     520  public:
     521    enum ItemType
     522    {
     523      TUPLE_PAT,
     524      IDENT_PAT,
     525      IDENT
     526    };
     527  
     528    virtual ~StructPatternField () {}
     529  
     530    // Unique pointer custom clone function
     531    std::unique_ptr<StructPatternField> clone_struct_pattern_field () const
     532    {
     533      return std::unique_ptr<StructPatternField> (
     534        clone_struct_pattern_field_impl ());
     535    }
     536  
     537    virtual std::string as_string () const;
     538  
     539    Location get_locus () const { return locus; }
     540  
     541    virtual void accept_vis (ASTVisitor &vis) = 0;
     542  
     543    virtual void mark_for_strip () = 0;
     544    virtual bool is_marked_for_strip () const = 0;
     545    virtual ItemType get_item_type () const = 0;
     546  
     547    NodeId get_node_id () const { return node_id; }
     548  
     549    // TODO: seems kinda dodgy. Think of better way.
     550    std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
     551    const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
     552  
     553  protected:
     554    StructPatternField (std::vector<Attribute> outer_attribs, Location locus,
     555  		      NodeId node_id)
     556      : outer_attrs (std::move (outer_attribs)), locus (locus), node_id (node_id)
     557    {}
     558  
     559    // Clone function implementation as pure virtual method
     560    virtual StructPatternField *clone_struct_pattern_field_impl () const = 0;
     561  };
     562  
     563  // Tuple pattern single field in a struct pattern
     564  class StructPatternFieldTuplePat : public StructPatternField
     565  {
     566    TupleIndex index;
     567    std::unique_ptr<Pattern> tuple_pattern;
     568  
     569  public:
     570    StructPatternFieldTuplePat (TupleIndex index,
     571  			      std::unique_ptr<Pattern> tuple_pattern,
     572  			      std::vector<Attribute> outer_attribs,
     573  			      Location locus)
     574      : StructPatternField (std::move (outer_attribs), locus,
     575  			  Analysis::Mappings::get ()->get_next_node_id ()),
     576        index (index), tuple_pattern (std::move (tuple_pattern))
     577    {}
     578  
     579    // Copy constructor requires clone
     580    StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other)
     581      : StructPatternField (other), index (other.index)
     582    {
     583      // guard to prevent null dereference (only required if error state)
     584      node_id = other.get_node_id ();
     585      if (other.tuple_pattern != nullptr)
     586        tuple_pattern = other.tuple_pattern->clone_pattern ();
     587    }
     588  
     589    // Overload assignment operator to perform clone
     590    StructPatternFieldTuplePat &
     591    operator= (StructPatternFieldTuplePat const &other)
     592    {
     593      StructPatternField::operator= (other);
     594      index = other.index;
     595      // outer_attrs = other.outer_attrs;
     596      node_id = other.get_node_id ();
     597  
     598      // guard to prevent null dereference (only required if error state)
     599      if (other.tuple_pattern != nullptr)
     600        tuple_pattern = other.tuple_pattern->clone_pattern ();
     601      else
     602        tuple_pattern = nullptr;
     603  
     604      return *this;
     605    }
     606  
     607    // default move semantics
     608    StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default;
     609    StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other)
     610      = default;
     611  
     612    std::string as_string () const override;
     613  
     614    void accept_vis (ASTVisitor &vis) override;
     615  
     616    // based on idea of tuple pattern no longer existing
     617    void mark_for_strip () override { tuple_pattern = nullptr; }
     618    bool is_marked_for_strip () const override
     619    {
     620      return tuple_pattern == nullptr;
     621    }
     622  
     623    // TODO: is this better? Or is a "vis_pattern" better?
     624    std::unique_ptr<Pattern> &get_index_pattern ()
     625    {
     626      rust_assert (tuple_pattern != nullptr);
     627      return tuple_pattern;
     628    }
     629  
     630    ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; }
     631  
     632  protected:
     633    /* Use covariance to implement clone function as returning this object rather
     634     * than base */
     635    StructPatternFieldTuplePat *clone_struct_pattern_field_impl () const override
     636    {
     637      return new StructPatternFieldTuplePat (*this);
     638    }
     639  };
     640  
     641  // Identifier pattern single field in a struct pattern
     642  class StructPatternFieldIdentPat : public StructPatternField
     643  {
     644    Identifier ident;
     645    std::unique_ptr<Pattern> ident_pattern;
     646  
     647  public:
     648    StructPatternFieldIdentPat (Identifier ident,
     649  			      std::unique_ptr<Pattern> ident_pattern,
     650  			      std::vector<Attribute> outer_attrs,
     651  			      Location locus)
     652      : StructPatternField (std::move (outer_attrs), locus,
     653  			  Analysis::Mappings::get ()->get_next_node_id ()),
     654        ident (std::move (ident)), ident_pattern (std::move (ident_pattern))
     655    {}
     656  
     657    // Copy constructor requires clone
     658    StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other)
     659      : StructPatternField (other), ident (other.ident)
     660    {
     661      // guard to prevent null dereference (only required if error state)
     662      node_id = other.get_node_id ();
     663      if (other.ident_pattern != nullptr)
     664        ident_pattern = other.ident_pattern->clone_pattern ();
     665    }
     666  
     667    // Overload assignment operator to clone
     668    StructPatternFieldIdentPat &
     669    operator= (StructPatternFieldIdentPat const &other)
     670    {
     671      StructPatternField::operator= (other);
     672      ident = other.ident;
     673      // outer_attrs = other.outer_attrs;
     674      node_id = other.get_node_id ();
     675  
     676      // guard to prevent null dereference (only required if error state)
     677      if (other.ident_pattern != nullptr)
     678        ident_pattern = other.ident_pattern->clone_pattern ();
     679      else
     680        ident_pattern = nullptr;
     681  
     682      return *this;
     683    }
     684  
     685    // default move semantics
     686    StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default;
     687    StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other)
     688      = default;
     689  
     690    std::string as_string () const override;
     691  
     692    void accept_vis (ASTVisitor &vis) override;
     693  
     694    // based on idea of identifier pattern no longer existing
     695    void mark_for_strip () override { ident_pattern = nullptr; }
     696    bool is_marked_for_strip () const override
     697    {
     698      return ident_pattern == nullptr;
     699    }
     700  
     701    const Identifier &get_identifier () const { return ident; }
     702  
     703    // TODO: is this better? Or is a "vis_pattern" better?
     704    std::unique_ptr<Pattern> &get_ident_pattern ()
     705    {
     706      rust_assert (ident_pattern != nullptr);
     707      return ident_pattern;
     708    }
     709  
     710    ItemType get_item_type () const override final { return ItemType::IDENT_PAT; }
     711  
     712  protected:
     713    /* Use covariance to implement clone function as returning this object rather
     714     * than base */
     715    StructPatternFieldIdentPat *clone_struct_pattern_field_impl () const override
     716    {
     717      return new StructPatternFieldIdentPat (*this);
     718    }
     719  };
     720  
     721  // Identifier only (with no pattern) single field in a struct pattern
     722  class StructPatternFieldIdent : public StructPatternField
     723  {
     724    bool has_ref;
     725    bool has_mut;
     726    Identifier ident;
     727  
     728  public:
     729    StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut,
     730  			   std::vector<Attribute> outer_attrs, Location locus)
     731      : StructPatternField (std::move (outer_attrs), locus,
     732  			  Analysis::Mappings::get ()->get_next_node_id ()),
     733        has_ref (is_ref), has_mut (is_mut), ident (std::move (ident))
     734    {}
     735  
     736    std::string as_string () const override;
     737  
     738    void accept_vis (ASTVisitor &vis) override;
     739  
     740    // based on idea of identifier no longer existing
     741    void mark_for_strip () override { ident = {}; }
     742    bool is_marked_for_strip () const override { return ident.empty (); }
     743  
     744    const Identifier &get_identifier () const { return ident; }
     745  
     746    ItemType get_item_type () const override final { return ItemType::IDENT; }
     747  
     748    bool is_ref () const { return has_ref; }
     749  
     750    bool is_mut () const { return has_mut; }
     751  
     752  protected:
     753    /* Use covariance to implement clone function as returning this object rather
     754     * than base */
     755    StructPatternFieldIdent *clone_struct_pattern_field_impl () const override
     756    {
     757      return new StructPatternFieldIdent (*this);
     758    }
     759  };
     760  
     761  // Elements of a struct pattern
     762  struct StructPatternElements
     763  {
     764  private:
     765    // bool has_struct_pattern_fields;
     766    std::vector<std::unique_ptr<StructPatternField>> fields;
     767  
     768    bool has_struct_pattern_etc;
     769    std::vector<Attribute> struct_pattern_etc_attrs;
     770    // StructPatternEtc etc;
     771  
     772    // must have at least one of the two and maybe both
     773  
     774    // should this store location data?
     775  
     776  public:
     777    // Returns whether there are any struct pattern fields
     778    bool has_struct_pattern_fields () const { return !fields.empty (); }
     779  
     780    /* Returns whether the struct pattern elements is entirely empty (no fields,
     781     * no etc). */
     782    bool is_empty () const
     783    {
     784      return !has_struct_pattern_fields () && !has_struct_pattern_etc;
     785    }
     786  
     787    bool has_etc () const { return has_struct_pattern_etc; }
     788  
     789    // Constructor for StructPatternElements with both (potentially)
     790    StructPatternElements (
     791      std::vector<std::unique_ptr<StructPatternField>> fields,
     792      std::vector<Attribute> etc_attrs)
     793      : fields (std::move (fields)), has_struct_pattern_etc (true),
     794        struct_pattern_etc_attrs (std::move (etc_attrs))
     795    {}
     796  
     797    // Constructor for StructPatternElements with no StructPatternEtc
     798    StructPatternElements (
     799      std::vector<std::unique_ptr<StructPatternField>> fields)
     800      : fields (std::move (fields)), has_struct_pattern_etc (false),
     801        struct_pattern_etc_attrs ()
     802    {}
     803  
     804    // Copy constructor with vector clone
     805    StructPatternElements (StructPatternElements const &other)
     806      : has_struct_pattern_etc (other.has_struct_pattern_etc),
     807        struct_pattern_etc_attrs (other.struct_pattern_etc_attrs)
     808    {
     809      fields.reserve (other.fields.size ());
     810      for (const auto &e : other.fields)
     811        fields.push_back (e->clone_struct_pattern_field ());
     812    }
     813  
     814    // Overloaded assignment operator with vector clone
     815    StructPatternElements &operator= (StructPatternElements const &other)
     816    {
     817      struct_pattern_etc_attrs = other.struct_pattern_etc_attrs;
     818      has_struct_pattern_etc = other.has_struct_pattern_etc;
     819  
     820      fields.reserve (other.fields.size ());
     821      for (const auto &e : other.fields)
     822        fields.push_back (e->clone_struct_pattern_field ());
     823  
     824      return *this;
     825    }
     826  
     827    // move constructors
     828    StructPatternElements (StructPatternElements &&other) = default;
     829    StructPatternElements &operator= (StructPatternElements &&other) = default;
     830  
     831    // Creates an empty StructPatternElements
     832    static StructPatternElements create_empty ()
     833    {
     834      return StructPatternElements (
     835        std::vector<std::unique_ptr<StructPatternField>> ());
     836    }
     837  
     838    std::string as_string () const;
     839  
     840    // TODO: seems kinda dodgy. Think of better way.
     841    std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields ()
     842    {
     843      return fields;
     844    }
     845    const std::vector<std::unique_ptr<StructPatternField>> &
     846    get_struct_pattern_fields () const
     847    {
     848      return fields;
     849    }
     850  
     851    std::vector<Attribute> &get_etc_outer_attrs ()
     852    {
     853      return struct_pattern_etc_attrs;
     854    }
     855    const std::vector<Attribute> &get_etc_outer_attrs () const
     856    {
     857      return struct_pattern_etc_attrs;
     858    }
     859  
     860    void strip_etc ()
     861    {
     862      has_struct_pattern_etc = false;
     863      struct_pattern_etc_attrs.clear ();
     864      struct_pattern_etc_attrs.shrink_to_fit ();
     865    }
     866  };
     867  
     868  // Struct pattern AST node representation
     869  class StructPattern : public Pattern
     870  {
     871    PathInExpression path;
     872  
     873    // bool has_struct_pattern_elements;
     874    StructPatternElements elems;
     875  
     876    NodeId node_id;
     877    Location locus;
     878  
     879  public:
     880    std::string as_string () const override;
     881  
     882    // Constructs a struct pattern from specified StructPatternElements
     883    StructPattern (PathInExpression struct_path, Location locus,
     884  		 StructPatternElements elems
     885  		 = StructPatternElements::create_empty ())
     886      : path (std::move (struct_path)), elems (std::move (elems)),
     887        node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
     888    {}
     889  
     890    /* TODO: constructor to construct via elements included in
     891     * StructPatternElements */
     892  
     893    /* Returns whether struct pattern has any struct pattern elements (if not, it
     894     * is empty). */
     895    bool has_struct_pattern_elems () const { return !elems.is_empty (); }
     896  
     897    Location get_locus () const { return path.get_locus (); }
     898  
     899    void accept_vis (ASTVisitor &vis) override;
     900  
     901    // TODO: seems kinda dodgy. Think of better way.
     902    StructPatternElements &get_struct_pattern_elems () { return elems; }
     903    const StructPatternElements &get_struct_pattern_elems () const
     904    {
     905      return elems;
     906    }
     907  
     908    PathInExpression &get_path () { return path; }
     909    const PathInExpression &get_path () const { return path; }
     910  
     911    NodeId get_node_id () const { return node_id; }
     912  
     913    NodeId get_pattern_node_id () const override final { return node_id; }
     914  
     915  protected:
     916    /* Use covariance to implement clone function as returning this object rather
     917     * than base */
     918    StructPattern *clone_pattern_impl () const override
     919    {
     920      return new StructPattern (*this);
     921    }
     922  };
     923  
     924  // Base abstract class for patterns used in TupleStructPattern
     925  class TupleStructItems
     926  {
     927  public:
     928    enum ItemType
     929    {
     930      RANGE,
     931      NO_RANGE
     932    };
     933  
     934    virtual ~TupleStructItems () {}
     935  
     936    // TODO: should this store location data?
     937  
     938    // Unique pointer custom clone function
     939    std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
     940    {
     941      return std::unique_ptr<TupleStructItems> (clone_tuple_struct_items_impl ());
     942    }
     943  
     944    virtual std::string as_string () const = 0;
     945  
     946    virtual void accept_vis (ASTVisitor &vis) = 0;
     947  
     948    virtual ItemType get_item_type () const = 0;
     949  
     950  protected:
     951    // pure virtual clone implementation
     952    virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0;
     953  };
     954  
     955  // Class for non-ranged tuple struct pattern patterns
     956  class TupleStructItemsNoRange : public TupleStructItems
     957  {
     958    std::vector<std::unique_ptr<Pattern>> patterns;
     959  
     960  public:
     961    TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns)
     962      : patterns (std::move (patterns))
     963    {}
     964  
     965    // Copy constructor with vector clone
     966    TupleStructItemsNoRange (TupleStructItemsNoRange const &other)
     967    {
     968      patterns.reserve (other.patterns.size ());
     969      for (const auto &e : other.patterns)
     970        patterns.push_back (e->clone_pattern ());
     971    }
     972  
     973    // Overloaded assignment operator with vector clone
     974    TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other)
     975    {
     976      patterns.reserve (other.patterns.size ());
     977      for (const auto &e : other.patterns)
     978        patterns.push_back (e->clone_pattern ());
     979  
     980      return *this;
     981    }
     982  
     983    // move constructors
     984    TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default;
     985    TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other)
     986      = default;
     987  
     988    std::string as_string () const override;
     989  
     990    void accept_vis (ASTVisitor &vis) override;
     991  
     992    // TODO: seems kinda dodgy. Think of better way.
     993    std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
     994    const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
     995    {
     996      return patterns;
     997    }
     998  
     999    ItemType get_item_type () const override final { return ItemType::NO_RANGE; }
    1000  
    1001  protected:
    1002    /* Use covariance to implement clone function as returning this object rather
    1003     * than base */
    1004    TupleStructItemsNoRange *clone_tuple_struct_items_impl () const override
    1005    {
    1006      return new TupleStructItemsNoRange (*this);
    1007    }
    1008  };
    1009  
    1010  // Class for ranged tuple struct pattern patterns
    1011  class TupleStructItemsRange : public TupleStructItems
    1012  {
    1013    std::vector<std::unique_ptr<Pattern>> lower_patterns;
    1014    std::vector<std::unique_ptr<Pattern>> upper_patterns;
    1015  
    1016  public:
    1017    TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns,
    1018  			 std::vector<std::unique_ptr<Pattern>> upper_patterns)
    1019      : lower_patterns (std::move (lower_patterns)),
    1020        upper_patterns (std::move (upper_patterns))
    1021    {}
    1022  
    1023    // Copy constructor with vector clone
    1024    TupleStructItemsRange (TupleStructItemsRange const &other)
    1025    {
    1026      lower_patterns.reserve (other.lower_patterns.size ());
    1027      for (const auto &e : other.lower_patterns)
    1028        lower_patterns.push_back (e->clone_pattern ());
    1029  
    1030      upper_patterns.reserve (other.upper_patterns.size ());
    1031      for (const auto &e : other.upper_patterns)
    1032        upper_patterns.push_back (e->clone_pattern ());
    1033    }
    1034  
    1035    // Overloaded assignment operator to clone
    1036    TupleStructItemsRange &operator= (TupleStructItemsRange const &other)
    1037    {
    1038      lower_patterns.reserve (other.lower_patterns.size ());
    1039      for (const auto &e : other.lower_patterns)
    1040        lower_patterns.push_back (e->clone_pattern ());
    1041  
    1042      upper_patterns.reserve (other.upper_patterns.size ());
    1043      for (const auto &e : other.upper_patterns)
    1044        upper_patterns.push_back (e->clone_pattern ());
    1045  
    1046      return *this;
    1047    }
    1048  
    1049    // move constructors
    1050    TupleStructItemsRange (TupleStructItemsRange &&other) = default;
    1051    TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default;
    1052  
    1053    std::string as_string () const override;
    1054  
    1055    void accept_vis (ASTVisitor &vis) override;
    1056  
    1057    // TODO: seems kinda dodgy. Think of better way.
    1058    std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
    1059    {
    1060      return lower_patterns;
    1061    }
    1062    const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
    1063    {
    1064      return lower_patterns;
    1065    }
    1066  
    1067    // TODO: seems kinda dodgy. Think of better way.
    1068    std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
    1069    {
    1070      return upper_patterns;
    1071    }
    1072    const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
    1073    {
    1074      return upper_patterns;
    1075    }
    1076  
    1077    ItemType get_item_type () const override final { return ItemType::RANGE; }
    1078  
    1079  protected:
    1080    /* Use covariance to implement clone function as returning this object rather
    1081     * than base */
    1082    TupleStructItemsRange *clone_tuple_struct_items_impl () const override
    1083    {
    1084      return new TupleStructItemsRange (*this);
    1085    }
    1086  };
    1087  
    1088  // AST node representing a tuple struct pattern
    1089  class TupleStructPattern : public Pattern
    1090  {
    1091    PathInExpression path;
    1092    std::unique_ptr<TupleStructItems> items;
    1093    NodeId node_id;
    1094  
    1095    /* TOOD: should this store location data? current accessor uses path location
    1096     * data */
    1097  
    1098  public:
    1099    std::string as_string () const override;
    1100  
    1101    // Returns whether the pattern has tuple struct items.
    1102    bool has_items () const { return items != nullptr; }
    1103  
    1104    TupleStructPattern (PathInExpression tuple_struct_path,
    1105  		      std::unique_ptr<TupleStructItems> items)
    1106      : path (std::move (tuple_struct_path)), items (std::move (items)),
    1107        node_id (Analysis::Mappings::get ()->get_next_node_id ())
    1108    {}
    1109  
    1110    // Copy constructor required to clone
    1111    TupleStructPattern (TupleStructPattern const &other) : path (other.path)
    1112    {
    1113      // guard to protect from null dereference
    1114      node_id = other.node_id;
    1115      if (other.items != nullptr)
    1116        items = other.items->clone_tuple_struct_items ();
    1117    }
    1118  
    1119    // Operator overload assignment operator to clone
    1120    TupleStructPattern &operator= (TupleStructPattern const &other)
    1121    {
    1122      path = other.path;
    1123      node_id = other.node_id;
    1124  
    1125      // guard to protect from null dereference
    1126      if (other.items != nullptr)
    1127        items = other.items->clone_tuple_struct_items ();
    1128      else
    1129        items = nullptr;
    1130  
    1131      return *this;
    1132    }
    1133  
    1134    // move constructors
    1135    TupleStructPattern (TupleStructPattern &&other) = default;
    1136    TupleStructPattern &operator= (TupleStructPattern &&other) = default;
    1137  
    1138    Location get_locus () const override { return path.get_locus (); }
    1139  
    1140    void accept_vis (ASTVisitor &vis) override;
    1141  
    1142    // TODO: seems kinda dodgy. Think of better way.
    1143    std::unique_ptr<TupleStructItems> &get_items ()
    1144    {
    1145      rust_assert (has_items ());
    1146      return items;
    1147    }
    1148  
    1149    PathInExpression &get_path () { return path; }
    1150    const PathInExpression &get_path () const { return path; }
    1151  
    1152    NodeId get_node_id () const { return node_id; }
    1153  
    1154    NodeId get_pattern_node_id () const override final { return node_id; }
    1155  
    1156  protected:
    1157    /* Use covariance to implement clone function as returning this object rather
    1158     * than base */
    1159    TupleStructPattern *clone_pattern_impl () const override
    1160    {
    1161      return new TupleStructPattern (*this);
    1162    }
    1163  };
    1164  
    1165  // Base abstract class representing TuplePattern patterns
    1166  class TuplePatternItems
    1167  {
    1168  public:
    1169    enum TuplePatternItemType
    1170    {
    1171      MULTIPLE,
    1172      RANGED,
    1173    };
    1174  
    1175    virtual ~TuplePatternItems () {}
    1176  
    1177    // TODO: should this store location data?
    1178  
    1179    // Unique pointer custom clone function
    1180    std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const
    1181    {
    1182      return std::unique_ptr<TuplePatternItems> (
    1183        clone_tuple_pattern_items_impl ());
    1184    }
    1185  
    1186    virtual std::string as_string () const = 0;
    1187  
    1188    virtual void accept_vis (ASTVisitor &vis) = 0;
    1189  
    1190    virtual TuplePatternItemType get_pattern_type () const = 0;
    1191  
    1192  protected:
    1193    // pure virtual clone implementation
    1194    virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0;
    1195  };
    1196  
    1197  // Class representing TuplePattern patterns where there is only a single pattern
    1198  /*class TuplePatternItemsSingle : public TuplePatternItems {
    1199      // Pattern pattern;
    1200      std::unique_ptr<Pattern> pattern;
    1201  
    1202    public:
    1203      TuplePatternItemsSingle(Pattern* pattern) : pattern(pattern) {}
    1204  
    1205      // Copy constructor uses clone
    1206      TuplePatternItemsSingle(TuplePatternItemsSingle const& other) :
    1207        pattern(other.pattern->clone_pattern()) {}
    1208  
    1209      // Destructor - define here if required
    1210  
    1211      // Overload assignment operator to clone
    1212      TuplePatternItemsSingle& operator=(TuplePatternItemsSingle const& other) {
    1213  	pattern = other.pattern->clone_pattern();
    1214  
    1215  	return *this;
    1216      }
    1217  
    1218      // move constructors
    1219      TuplePatternItemsSingle(TuplePatternItemsSingle&& other) = default;
    1220      TuplePatternItemsSingle& operator=(TuplePatternItemsSingle&& other) =
    1221  default;
    1222  
    1223    protected:
    1224      // Use covariance to implement clone function as returning this object
    1225  rather than base virtual TuplePatternItemsSingle*
    1226  clone_tuple_pattern_items_impl() const override { return new
    1227  TuplePatternItemsSingle(*this);
    1228      }
    1229  };*/
    1230  // removed in favour of single-element TuplePatternItemsMultiple
    1231  
    1232  // Class representing TuplePattern patterns where there are multiple patterns
    1233  class TuplePatternItemsMultiple : public TuplePatternItems
    1234  {
    1235    std::vector<std::unique_ptr<Pattern>> patterns;
    1236  
    1237  public:
    1238    TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns)
    1239      : patterns (std::move (patterns))
    1240    {}
    1241  
    1242    // Copy constructor with vector clone
    1243    TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other)
    1244    {
    1245      patterns.reserve (other.patterns.size ());
    1246      for (const auto &e : other.patterns)
    1247        patterns.push_back (e->clone_pattern ());
    1248    }
    1249  
    1250    // Overloaded assignment operator to vector clone
    1251    TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other)
    1252    {
    1253      patterns.reserve (other.patterns.size ());
    1254      for (const auto &e : other.patterns)
    1255        patterns.push_back (e->clone_pattern ());
    1256  
    1257      return *this;
    1258    }
    1259  
    1260    // move constructors
    1261    TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default;
    1262    TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other)
    1263      = default;
    1264  
    1265    std::string as_string () const override;
    1266  
    1267    void accept_vis (ASTVisitor &vis) override;
    1268  
    1269    // TODO: seems kinda dodgy. Think of better way.
    1270    std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
    1271    const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
    1272    {
    1273      return patterns;
    1274    }
    1275  
    1276    TuplePatternItemType get_pattern_type () const override
    1277    {
    1278      return TuplePatternItemType::MULTIPLE;
    1279    }
    1280  
    1281  protected:
    1282    /* Use covariance to implement clone function as returning this object rather
    1283     * than base */
    1284    TuplePatternItemsMultiple *clone_tuple_pattern_items_impl () const override
    1285    {
    1286      return new TuplePatternItemsMultiple (*this);
    1287    }
    1288  };
    1289  
    1290  // Class representing TuplePattern patterns where there are a range of patterns
    1291  class TuplePatternItemsRanged : public TuplePatternItems
    1292  {
    1293    std::vector<std::unique_ptr<Pattern>> lower_patterns;
    1294    std::vector<std::unique_ptr<Pattern>> upper_patterns;
    1295  
    1296  public:
    1297    TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns,
    1298  			   std::vector<std::unique_ptr<Pattern>> upper_patterns)
    1299      : lower_patterns (std::move (lower_patterns)),
    1300        upper_patterns (std::move (upper_patterns))
    1301    {}
    1302  
    1303    // Copy constructor with vector clone
    1304    TuplePatternItemsRanged (TuplePatternItemsRanged const &other)
    1305    {
    1306      lower_patterns.reserve (other.lower_patterns.size ());
    1307      for (const auto &e : other.lower_patterns)
    1308        lower_patterns.push_back (e->clone_pattern ());
    1309  
    1310      upper_patterns.reserve (other.upper_patterns.size ());
    1311      for (const auto &e : other.upper_patterns)
    1312        upper_patterns.push_back (e->clone_pattern ());
    1313    }
    1314  
    1315    // Overloaded assignment operator to clone
    1316    TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other)
    1317    {
    1318      lower_patterns.reserve (other.lower_patterns.size ());
    1319      for (const auto &e : other.lower_patterns)
    1320        lower_patterns.push_back (e->clone_pattern ());
    1321  
    1322      upper_patterns.reserve (other.upper_patterns.size ());
    1323      for (const auto &e : other.upper_patterns)
    1324        upper_patterns.push_back (e->clone_pattern ());
    1325  
    1326      return *this;
    1327    }
    1328  
    1329    // move constructors
    1330    TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default;
    1331    TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other)
    1332      = default;
    1333  
    1334    std::string as_string () const override;
    1335  
    1336    void accept_vis (ASTVisitor &vis) override;
    1337  
    1338    // TODO: seems kinda dodgy. Think of better way.
    1339    std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
    1340    {
    1341      return lower_patterns;
    1342    }
    1343    const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
    1344    {
    1345      return lower_patterns;
    1346    }
    1347  
    1348    // TODO: seems kinda dodgy. Think of better way.
    1349    std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
    1350    {
    1351      return upper_patterns;
    1352    }
    1353    const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
    1354    {
    1355      return upper_patterns;
    1356    }
    1357  
    1358    TuplePatternItemType get_pattern_type () const override
    1359    {
    1360      return TuplePatternItemType::RANGED;
    1361    }
    1362  
    1363  protected:
    1364    /* Use covariance to implement clone function as returning this object rather
    1365     * than base */
    1366    TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override
    1367    {
    1368      return new TuplePatternItemsRanged (*this);
    1369    }
    1370  };
    1371  
    1372  // AST node representing a tuple pattern
    1373  class TuplePattern : public Pattern
    1374  {
    1375    // bool has_tuple_pattern_items;
    1376    std::unique_ptr<TuplePatternItems> items;
    1377    Location locus;
    1378    NodeId node_id;
    1379  
    1380  public:
    1381    std::string as_string () const override;
    1382  
    1383    // Returns true if the tuple pattern has items
    1384    bool has_tuple_pattern_items () const { return items != nullptr; }
    1385  
    1386    TuplePattern (std::unique_ptr<TuplePatternItems> items, Location locus)
    1387      : items (std::move (items)), locus (locus),
    1388        node_id (Analysis::Mappings::get ()->get_next_node_id ())
    1389    {}
    1390  
    1391    // Copy constructor requires clone
    1392    TuplePattern (TuplePattern const &other) : locus (other.locus)
    1393    {
    1394      // guard to prevent null dereference
    1395      node_id = other.node_id;
    1396      if (other.items != nullptr)
    1397        items = other.items->clone_tuple_pattern_items ();
    1398    }
    1399  
    1400    // Overload assignment operator to clone
    1401    TuplePattern &operator= (TuplePattern const &other)
    1402    {
    1403      locus = other.locus;
    1404      node_id = other.node_id;
    1405  
    1406      // guard to prevent null dereference
    1407      if (other.items != nullptr)
    1408        items = other.items->clone_tuple_pattern_items ();
    1409      else
    1410        items = nullptr;
    1411  
    1412      return *this;
    1413    }
    1414  
    1415    Location get_locus () const override final { return locus; }
    1416  
    1417    void accept_vis (ASTVisitor &vis) override;
    1418  
    1419    // TODO: seems kinda dodgy. Think of better way.
    1420    std::unique_ptr<TuplePatternItems> &get_items ()
    1421    {
    1422      rust_assert (has_tuple_pattern_items ());
    1423      return items;
    1424    }
    1425  
    1426    NodeId get_node_id () const { return node_id; }
    1427  
    1428    NodeId get_pattern_node_id () const override final { return node_id; }
    1429  
    1430  protected:
    1431    /* Use covariance to implement clone function as returning this object rather
    1432     * than base */
    1433    TuplePattern *clone_pattern_impl () const override
    1434    {
    1435      return new TuplePattern (*this);
    1436    }
    1437  };
    1438  
    1439  // AST node representing a pattern in parentheses, used to control precedence
    1440  class GroupedPattern : public Pattern
    1441  {
    1442    std::unique_ptr<Pattern> pattern_in_parens;
    1443    Location locus;
    1444    NodeId node_id;
    1445  
    1446  public:
    1447    std::string as_string () const override
    1448    {
    1449      return "(" + pattern_in_parens->as_string () + ")";
    1450    }
    1451  
    1452    GroupedPattern (std::unique_ptr<Pattern> pattern_in_parens, Location locus)
    1453      : pattern_in_parens (std::move (pattern_in_parens)), locus (locus),
    1454        node_id (Analysis::Mappings::get ()->get_next_node_id ())
    1455    {}
    1456  
    1457    // Copy constructor uses clone
    1458    GroupedPattern (GroupedPattern const &other)
    1459      : pattern_in_parens (other.pattern_in_parens->clone_pattern ()),
    1460        locus (other.locus), node_id (other.node_id)
    1461    {}
    1462  
    1463    // Overload assignment operator to clone
    1464    GroupedPattern &operator= (GroupedPattern const &other)
    1465    {
    1466      pattern_in_parens = other.pattern_in_parens->clone_pattern ();
    1467      locus = other.locus;
    1468      node_id = other.node_id;
    1469  
    1470      return *this;
    1471    }
    1472  
    1473    // default move semantics
    1474    GroupedPattern (GroupedPattern &&other) = default;
    1475    GroupedPattern &operator= (GroupedPattern &&other) = default;
    1476  
    1477    Location get_locus () const override final { return locus; }
    1478  
    1479    void accept_vis (ASTVisitor &vis) override;
    1480  
    1481    // TODO: seems kinda dodgy. Think of better way.
    1482    std::unique_ptr<Pattern> &get_pattern_in_parens ()
    1483    {
    1484      rust_assert (pattern_in_parens != nullptr);
    1485      return pattern_in_parens;
    1486    }
    1487  
    1488    NodeId get_node_id () const { return node_id; }
    1489  
    1490    NodeId get_pattern_node_id () const override final { return node_id; }
    1491  
    1492  protected:
    1493    /* Use covariance to implement clone function as returning this object rather
    1494     * than base */
    1495    GroupedPattern *clone_pattern_impl () const override
    1496    {
    1497      return new GroupedPattern (*this);
    1498    }
    1499  };
    1500  
    1501  // AST node representing patterns that can match slices and arrays
    1502  class SlicePattern : public Pattern
    1503  {
    1504    std::vector<std::unique_ptr<Pattern>> items;
    1505    Location locus;
    1506    NodeId node_id;
    1507  
    1508  public:
    1509    std::string as_string () const override;
    1510  
    1511    SlicePattern (std::vector<std::unique_ptr<Pattern>> items, Location locus)
    1512      : items (std::move (items)), locus (locus),
    1513        node_id (Analysis::Mappings::get ()->get_next_node_id ())
    1514    {}
    1515  
    1516    // Copy constructor with vector clone
    1517    SlicePattern (SlicePattern const &other) : locus (other.locus)
    1518    {
    1519      node_id = other.node_id;
    1520      items.reserve (other.items.size ());
    1521      for (const auto &e : other.items)
    1522        items.push_back (e->clone_pattern ());
    1523    }
    1524  
    1525    // Overloaded assignment operator to vector clone
    1526    SlicePattern &operator= (SlicePattern const &other)
    1527    {
    1528      locus = other.locus;
    1529      node_id = other.node_id;
    1530  
    1531      items.reserve (other.items.size ());
    1532      for (const auto &e : other.items)
    1533        items.push_back (e->clone_pattern ());
    1534  
    1535      return *this;
    1536    }
    1537  
    1538    // move constructors
    1539    SlicePattern (SlicePattern &&other) = default;
    1540    SlicePattern &operator= (SlicePattern &&other) = default;
    1541  
    1542    Location get_locus () const override final { return locus; }
    1543  
    1544    void accept_vis (ASTVisitor &vis) override;
    1545  
    1546    // TODO: seems kinda dodgy. Think of better way.
    1547    std::vector<std::unique_ptr<Pattern>> &get_items () { return items; }
    1548    const std::vector<std::unique_ptr<Pattern>> &get_items () const
    1549    {
    1550      return items;
    1551    }
    1552  
    1553    NodeId get_node_id () const { return node_id; }
    1554  
    1555    NodeId get_pattern_node_id () const override final { return node_id; }
    1556  
    1557  protected:
    1558    /* Use covariance to implement clone function as returning this object rather
    1559     * than base */
    1560    SlicePattern *clone_pattern_impl () const override
    1561    {
    1562      return new SlicePattern (*this);
    1563    }
    1564  };
    1565  
    1566  // AST node for alternate patterns
    1567  // joins together what are technically 'PatternNoTopAlt's
    1568  class AltPattern : public Pattern
    1569  {
    1570    std::vector<std::unique_ptr<Pattern>> alts;
    1571    Location locus;
    1572    NodeId node_id;
    1573  
    1574  public:
    1575    std::string as_string () const override;
    1576  
    1577    AltPattern (std::vector<std::unique_ptr<Pattern>> alts, Location locus)
    1578      : alts (std::move (alts)), locus (locus),
    1579        node_id (Analysis::Mappings::get ()->get_next_node_id ())
    1580    {}
    1581  
    1582    // Copy constructor with vector clone
    1583    AltPattern (AltPattern const &other) : locus (other.locus)
    1584    {
    1585      node_id = other.node_id;
    1586      alts.reserve (other.alts.size ());
    1587      for (const auto &e : other.alts)
    1588        alts.push_back (e->clone_pattern ());
    1589    }
    1590  
    1591    // Overloaded assignment operator to vector clone
    1592    AltPattern &operator= (AltPattern const &other)
    1593    {
    1594      locus = other.locus;
    1595      node_id = other.node_id;
    1596  
    1597      alts.reserve (other.alts.size ());
    1598      for (const auto &e : other.alts)
    1599        alts.push_back (e->clone_pattern ());
    1600  
    1601      return *this;
    1602    }
    1603  
    1604    // move constructors
    1605    AltPattern (AltPattern &&other) = default;
    1606    AltPattern &operator= (AltPattern &&other) = default;
    1607  
    1608    Location get_locus () const override final { return locus; }
    1609  
    1610    void accept_vis (ASTVisitor &vis) override;
    1611  
    1612    // TODO: seems kinda dodgy. Think of better way.
    1613    std::vector<std::unique_ptr<Pattern>> &get_alts () { return alts; }
    1614    const std::vector<std::unique_ptr<Pattern>> &get_alts () const
    1615    {
    1616      return alts;
    1617    }
    1618  
    1619    NodeId get_node_id () const { return node_id; }
    1620  
    1621    NodeId get_pattern_node_id () const override final { return node_id; }
    1622  
    1623  protected:
    1624    /* Use covariance to implement clone function as returning this object rather
    1625     * than base */
    1626    AltPattern *clone_pattern_impl () const override
    1627    {
    1628      return new AltPattern (*this);
    1629    }
    1630  };
    1631  
    1632  // Moved definition to rust-path.h
    1633  class PathPattern;
    1634  
    1635  // Forward decls for paths (defined in rust-path.h)
    1636  class PathInExpression;
    1637  class QualifiedPathInExpression;
    1638  
    1639  // Replaced with forward decl - defined in rust-macro.h
    1640  class MacroInvocation;
    1641  } // namespace AST
    1642  } // namespace Rust
    1643  
    1644  #endif