// Copyright (C) 2020-2026 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_HIR_PATTERN_H
#define RUST_HIR_PATTERN_H

#include "rust-hir-pattern-abstract.h"
#include "rust-common.h"
#include "rust-hir-literal.h"
#include "rust-hir-path.h"

namespace Rust {
namespace HIR {
// Literal pattern HIR node (comparing to a literal)
class LiteralPattern : public Pattern
{
  Literal lit;
  location_t locus;
  Analysis::NodeMapping mappings;
  bool has_minus;

public:
  std::string to_string () const override;

  // Constructor for a literal pattern
  LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t locus)
    : lit (std::move (lit)), locus (locus), mappings (mappings),
      has_minus (false)
  {}

  LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t locus,
		  bool has_minus)
    : lit (std::move (lit)), locus (locus), mappings (mappings),
      has_minus (has_minus)
  {}

  LiteralPattern (Analysis::NodeMapping mappings, std::string val,
		  Literal::LitType type, location_t locus)
    : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)),
      locus (locus), mappings (mappings), has_minus (false)
  {}

  location_t get_locus () const override { return locus; }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  PatternType get_pattern_type () const override final
  {
    return PatternType::LITERAL;
  }

  Literal &get_literal () { return lit; }
  const Literal &get_literal () const { return lit; }

  bool get_has_minus () const { return has_minus; }

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 HIR node (bind value matched to a variable)
class IdentifierPattern : public Pattern
{
  Identifier variable_ident;
  bool is_ref;
  Mutability mut;
  std::unique_ptr<Pattern> subpattern;
  location_t locus;
  Analysis::NodeMapping mappings;

public:
  std::string to_string () const override;

  // Returns whether the IdentifierPattern has a pattern to bind.
  bool has_subpattern () const { return subpattern != nullptr; }

  // Constructor
  IdentifierPattern (Analysis::NodeMapping mappings, Identifier ident,
		     location_t locus, bool is_ref = false,
		     Mutability mut = Mutability::Imm,
		     std::unique_ptr<Pattern> subpattern = nullptr)
    : variable_ident (std::move (ident)), is_ref (is_ref), mut (mut),
      subpattern (std::move (subpattern)), locus (locus), mappings (mappings)
  {}

  // Copy constructor with clone
  IdentifierPattern (IdentifierPattern const &other)
    : variable_ident (other.variable_ident), is_ref (other.is_ref),
      mut (other.mut), locus (other.locus), mappings (other.mappings)
  {
    // fix to get prevent null pointer dereference
    if (other.subpattern != nullptr)
      subpattern = other.subpattern->clone_pattern ();
  }

  // Overload assignment operator to use clone
  IdentifierPattern &operator= (IdentifierPattern const &other)
  {
    variable_ident = other.variable_ident;
    is_ref = other.is_ref;
    mut = other.mut;
    locus = other.locus;
    mappings = other.mappings;

    // fix to get prevent null pointer dereference
    if (other.subpattern != nullptr)
      subpattern = other.subpattern->clone_pattern ();

    return *this;
  }

  // default move semantics
  IdentifierPattern (IdentifierPattern &&other) = default;
  IdentifierPattern &operator= (IdentifierPattern &&other) = default;

  location_t get_locus () const override { return locus; }

  bool is_mut () const { return mut == Mutability::Mut; }
  bool get_is_ref () const { return is_ref; }
  Pattern &get_subpattern () { return *subpattern; }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  Identifier get_identifier () const { return variable_ident; }

  PatternType get_pattern_type () const override final
  {
    return PatternType::IDENTIFIER;
  }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  IdentifierPattern *clone_pattern_impl () const override
  {
    return new IdentifierPattern (*this);
  }
};

// HIR node for using the '_' wildcard "match any value" pattern
class WildcardPattern : public Pattern
{
  location_t locus;
  Analysis::NodeMapping mappings;

public:
  std::string to_string () const override { return "_"; }

  WildcardPattern (Analysis::NodeMapping mappings, location_t locus)
    : locus (locus), mappings (mappings)
  {}

  location_t get_locus () const override { return locus; }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  PatternType get_pattern_type () const override final
  {
    return PatternType::WILDCARD;
  }

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 to_string () const = 0;

  virtual void accept_vis (HIRFullVisitor &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_t locus;

public:
  // Constructor
  RangePatternBoundLiteral (Literal literal, location_t locus,
			    bool has_minus = false)
    : literal (literal), has_minus (has_minus), locus (locus)
  {}

  std::string to_string () const override;

  location_t get_locus () const { return locus; }

  Literal get_literal () const { return literal; }
  bool get_has_minus () const { return has_minus; }

  void accept_vis (HIRFullVisitor &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 to_string () const override { return path.to_string (); }

  location_t get_locus () const { return path.get_locus (); }

  PathInExpression &get_path () { return path; }
  const PathInExpression &get_path () const { return path; }

  void accept_vis (HIRFullVisitor &vis) override;

  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 to_string () const override { return path.to_string (); }

  location_t get_locus () const { return path.get_locus (); }

  void accept_vis (HIRFullVisitor &vis) override;

  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);
  }
};

// HIR 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_t locus;
  bool is_inclusive;
  Analysis::NodeMapping mappings;

public:
  std::string to_string () const override;

  // Constructor
  RangePattern (Analysis::NodeMapping mappings,
		std::unique_ptr<RangePatternBound> lower,
		std::unique_ptr<RangePatternBound> upper, location_t locus,
		bool is_inclusive, bool has_ellipsis_syntax = false)
    : lower (std::move (lower)), upper (std::move (upper)),
      has_ellipsis_syntax (has_ellipsis_syntax), locus (locus),
      is_inclusive (is_inclusive), mappings (mappings)
  {}

  // 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),
      is_inclusive (other.is_inclusive), mappings (other.mappings)
  {}

  // 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;
    is_inclusive = other.is_inclusive;
    mappings = other.mappings;

    return *this;
  }

  // default move semantics
  RangePattern (RangePattern &&other) = default;
  RangePattern &operator= (RangePattern &&other) = default;

  location_t get_locus () const override { return locus; }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  bool get_has_ellipsis_syntax () { return has_ellipsis_syntax; };
  bool is_inclusive_range () const { return is_inclusive; }

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  PatternType get_pattern_type () const override final
  {
    return PatternType::RANGE;
  }

  RangePatternBound &get_lower_bound () { return *lower; }

  RangePatternBound &get_upper_bound () { return *upper; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  RangePattern *clone_pattern_impl () const override
  {
    return new RangePattern (*this);
  }
};

// HIR node for pattern based on dereferencing the pointers given
class ReferencePattern : public Pattern
{
  Mutability mut;
  std::unique_ptr<Pattern> pattern;
  location_t locus;
  Analysis::NodeMapping mappings;

public:
  std::string to_string () const override;

  ReferencePattern (Analysis::NodeMapping mappings,
		    std::unique_ptr<Pattern> pattern, Mutability reference_mut,
		    location_t locus)
    : mut (reference_mut), pattern (std::move (pattern)), locus (locus),
      mappings (mappings)
  {}

  // Copy constructor requires clone
  ReferencePattern (ReferencePattern const &other)
    : mut (other.mut), pattern (other.pattern->clone_pattern ()),
      locus (other.locus), mappings (other.mappings)
  {}

  // Overload assignment operator to clone
  ReferencePattern &operator= (ReferencePattern const &other)
  {
    pattern = other.pattern->clone_pattern ();
    mut = other.mut;
    locus = other.locus;
    mappings = other.mappings;

    return *this;
  }

  // default move semantics
  ReferencePattern (ReferencePattern &&other) = default;
  ReferencePattern &operator= (ReferencePattern &&other) = default;

  bool is_mut () const { return mut == Mutability::Mut; }

  Mutability get_mutability () const { return mut; }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  location_t get_locus () const override final { return locus; }

  PatternType get_pattern_type () const override final
  {
    return PatternType::REFERENCE;
  }

  Pattern &get_referenced_pattern () { return *pattern; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  ReferencePattern *clone_pattern_impl () const override
  {
    return new ReferencePattern (*this);
  }
};

// Base class for a single field in a struct pattern - abstract
class StructPatternField
{
  AST::AttrVec outer_attrs;
  location_t locus;
  Analysis::NodeMapping mappings;

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 to_string () const;
  virtual void accept_vis (HIRFullVisitor &vis) = 0;
  virtual ItemType get_item_type () const = 0;

  location_t get_locus () const { return locus; }
  Analysis::NodeMapping get_mappings () const { return mappings; };
  AST::AttrVec get_outer_attrs () { return outer_attrs; }

protected:
  StructPatternField (Analysis::NodeMapping mappings,
		      AST::AttrVec outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)), locus (locus),
      mappings (mappings)
  {}

  // 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 (Analysis::NodeMapping mappings, TupleIndex index,
			      std::unique_ptr<Pattern> tuple_pattern,
			      AST::AttrVec outer_attribs, location_t locus)
    : StructPatternField (mappings, std::move (outer_attribs), locus),
      index (index), tuple_pattern (std::move (tuple_pattern))
  {}

  // Copy constructor requires clone
  StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other)
    : StructPatternField (other), index (other.index),
      tuple_pattern (other.tuple_pattern->clone_pattern ())
  {}

  // Overload assignment operator to perform clone
  StructPatternFieldTuplePat &
  operator= (StructPatternFieldTuplePat const &other)
  {
    StructPatternField::operator= (other);
    tuple_pattern = other.tuple_pattern->clone_pattern ();
    index = other.index;
    // outer_attrs = other.outer_attrs;

    return *this;
  }

  // default move semantics
  StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default;
  StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other)
    = default;

  std::string to_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  TupleIndex get_index () { return index; }
  Pattern &get_tuple_pattern () { 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 (Analysis::NodeMapping mappings, Identifier ident,
			      std::unique_ptr<Pattern> ident_pattern,
			      AST::AttrVec outer_attrs, location_t locus)
    : StructPatternField (mappings, std::move (outer_attrs), locus),
      ident (std::move (ident)), ident_pattern (std::move (ident_pattern))
  {}

  // Copy constructor requires clone
  StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other)
    : StructPatternField (other), ident (other.ident),
      ident_pattern (other.ident_pattern->clone_pattern ())
  {}

  // Overload assignment operator to clone
  StructPatternFieldIdentPat &
  operator= (StructPatternFieldIdentPat const &other)
  {
    StructPatternField::operator= (other);
    ident = other.ident;
    ident_pattern = other.ident_pattern->clone_pattern ();
    // outer_attrs = other.outer_attrs;

    return *this;
  }

  // default move semantics
  StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default;
  StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other)
    = default;

  std::string to_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  ItemType get_item_type () const override final { return ItemType::IDENT_PAT; }

  Identifier get_identifier () const { return ident; }

  Pattern &get_pattern () { return *ident_pattern; }

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;
  Mutability mut;
  Identifier ident;

public:
  StructPatternFieldIdent (Analysis::NodeMapping mappings, Identifier ident,
			   bool is_ref, Mutability mut,
			   AST::AttrVec outer_attrs, location_t locus)
    : StructPatternField (mappings, std::move (outer_attrs), locus),
      has_ref (is_ref), mut (mut), ident (std::move (ident))
  {}

  std::string to_string () const override;

  bool is_mut () const { return mut == Mutability::Mut; }

  void accept_vis (HIRFullVisitor &vis) override;

  ItemType get_item_type () const override final { return ItemType::IDENT; }
  bool get_has_ref () const { return has_ref; }
  Identifier get_identifier () const { return ident; };

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
class StructPatternElements
{
  std::vector<std::unique_ptr<StructPatternField>> fields;
  bool has_rest_pattern;

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 (); }

  bool has_rest () const { return has_rest_pattern; }

  // Constructor for StructPatternElements with both (potentially)
  StructPatternElements (
    std::vector<std::unique_ptr<StructPatternField>> fields)
    : fields (std::move (fields)), has_rest_pattern (false)
  {}

  StructPatternElements (
    std::vector<std::unique_ptr<StructPatternField>> fields,
    bool has_rest_pattern)
    : fields (std::move (fields)), has_rest_pattern (has_rest_pattern)
  {}

  // Copy constructor with vector clone
  StructPatternElements (StructPatternElements const &other)
  {
    fields.reserve (other.fields.size ());
    for (const auto &e : other.fields)
      fields.emplace_back (e->clone_struct_pattern_field ());
    has_rest_pattern = other.has_rest_pattern;
  }

  // Overloaded assignment operator with vector clone
  StructPatternElements &operator= (StructPatternElements const &other)
  {
    fields.clear ();
    fields.reserve (other.fields.size ());
    for (const auto &e : other.fields)
      fields.emplace_back (e->clone_struct_pattern_field ());
    has_rest_pattern = other.has_rest_pattern;
    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 to_string () const;

  std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields ()
  {
    return fields;
  }
};

// Struct pattern HIR node representation
class StructPattern : public Pattern
{
  PathInExpression path;
  StructPatternElements elems;
  Analysis::NodeMapping mappings;

public:
  std::string to_string () const override;

  StructPattern (Analysis::NodeMapping mappings, PathInExpression struct_path,
		 StructPatternElements elems)
    : path (std::move (struct_path)), elems (std::move (elems)),
      mappings (mappings)
  {}

  bool has_struct_pattern_elems () const { return !elems.is_empty (); }

  location_t get_locus () const override { return path.get_locus (); }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  PathInExpression &get_path () { return path; }
  StructPatternElements &get_struct_pattern_elems () { return elems; }

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  PatternType get_pattern_type () const override final
  {
    return PatternType::STRUCT;
  }

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 TupleStructItems, TuplePatternItems &
// SlicePatternItems
class PatternItems : public FullVisitable
{
public:
  enum ItemType
  {
    NO_REST,
    HAS_REST,
  };

  virtual ~PatternItems () {}

  // TODO: should this store location data?

  // Unique pointer custom clone function
  std::unique_ptr<PatternItems> clone_pattern_items () const
  {
    return std::unique_ptr<PatternItems> (clone_pattern_items_impl ());
  }

  virtual ItemType get_item_type () const = 0;

  virtual std::string to_string () const = 0;

protected:
  // pure virtual clone implementation
  virtual PatternItems *clone_pattern_items_impl () const = 0;
};

// Base abstract class for patterns used in TupleStructPattern
class TupleStructItems : public PatternItems
{
public:
  // Unique pointer custom clone function
  std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
  {
    return std::unique_ptr<TupleStructItems> (clone_pattern_items_impl ());
  }

protected:
  // pure virtual clone implementation
  virtual TupleStructItems *clone_pattern_items_impl () const override = 0;
};

// Class for patterns within a tuple struct pattern, without a rest pattern
class TupleStructItemsNoRest : public TupleStructItems
{
  std::vector<std::unique_ptr<Pattern>> patterns;

public:
  TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
    : patterns (std::move (patterns))
  {}

  // Copy constructor with vector clone
  TupleStructItemsNoRest (TupleStructItemsNoRest 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
  TupleStructItemsNoRest &operator= (TupleStructItemsNoRest const &other)
  {
    patterns.clear ();
    patterns.reserve (other.patterns.size ());
    for (const auto &e : other.patterns)
      patterns.push_back (e->clone_pattern ());

    return *this;
  }

  // move constructors
  TupleStructItemsNoRest (TupleStructItemsNoRest &&other) = default;
  TupleStructItemsNoRest &operator= (TupleStructItemsNoRest &&other) = default;

  std::string to_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  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_REST; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  TupleStructItemsNoRest *clone_pattern_items_impl () const override
  {
    return new TupleStructItemsNoRest (*this);
  }
};

// Class for patterns within a tuple struct pattern, with a rest pattern
// included
class TupleStructItemsHasRest : public TupleStructItems
{
  std::vector<std::unique_ptr<Pattern>> lower_patterns;
  std::vector<std::unique_ptr<Pattern>> upper_patterns;

public:
  TupleStructItemsHasRest (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
  TupleStructItemsHasRest (TupleStructItemsHasRest 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
  TupleStructItemsHasRest &operator= (TupleStructItemsHasRest const &other)
  {
    lower_patterns.clear ();
    lower_patterns.reserve (other.lower_patterns.size ());
    for (const auto &e : other.lower_patterns)
      lower_patterns.push_back (e->clone_pattern ());

    upper_patterns.clear ();
    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
  TupleStructItemsHasRest (TupleStructItemsHasRest &&other) = default;
  TupleStructItemsHasRest &operator= (TupleStructItemsHasRest &&other)
    = default;

  std::string to_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  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::HAS_REST; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  TupleStructItemsHasRest *clone_pattern_items_impl () const override
  {
    return new TupleStructItemsHasRest (*this);
  }
};

// HIR node representing a tuple struct pattern
class TupleStructPattern : public Pattern
{
  PathInExpression path;
  std::unique_ptr<TupleStructItems> items;
  Analysis::NodeMapping mappings;

  /* TOOD: should this store location data? current accessor uses path location
   * data */

public:
  std::string to_string () const override;

  TupleStructPattern (Analysis::NodeMapping mappings,
		      PathInExpression tuple_struct_path,
		      std::unique_ptr<TupleStructItems> items)
    : path (std::move (tuple_struct_path)), items (std::move (items)),
      mappings (mappings)
  {}

  // Copy constructor required to clone
  TupleStructPattern (TupleStructPattern const &other)
    : path (other.path), items (other.items->clone_tuple_struct_items ()),
      mappings (other.mappings)
  {}

  // Operator overload assignment operator to clone
  TupleStructPattern &operator= (TupleStructPattern const &other)
  {
    path = other.path;
    items = other.items->clone_tuple_struct_items ();
    mappings = other.mappings;

    return *this;
  }

  // move constructors
  TupleStructPattern (TupleStructPattern &&other) = default;
  TupleStructPattern &operator= (TupleStructPattern &&other) = default;

  location_t get_locus () const override { return path.get_locus (); }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  PathInExpression &get_path () { return path; }

  TupleStructItems &get_items () { return *items; }

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  PatternType get_pattern_type () const override final
  {
    return PatternType::TUPLE_STRUCT;
  }

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 PatternItems
{
public:
  // Unique pointer custom clone function
  std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const
  {
    return std::unique_ptr<TuplePatternItems> (clone_pattern_items_impl ());
  }

protected:
  // pure virtual clone implementation
  virtual TuplePatternItems *clone_pattern_items_impl () const override = 0;
};

// Class representing patterns within a TuplePattern, without a rest pattern
class TuplePatternItemsNoRest : public TuplePatternItems
{
  std::vector<std::unique_ptr<Pattern>> patterns;

public:
  TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
    : patterns (std::move (patterns))
  {}

  // Copy constructor with vector clone
  TuplePatternItemsNoRest (TuplePatternItemsNoRest 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
  TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest const &other)
  {
    patterns.clear ();
    patterns.reserve (other.patterns.size ());
    for (const auto &e : other.patterns)
      patterns.push_back (e->clone_pattern ());

    return *this;
  }

  // move constructors
  TuplePatternItemsNoRest (TuplePatternItemsNoRest &&other) = default;
  TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest &&other)
    = default;

  std::string to_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  ItemType get_item_type () const override { return ItemType::NO_REST; }

  std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
  const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
  {
    return patterns;
  }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  TuplePatternItemsNoRest *clone_pattern_items_impl () const override
  {
    return new TuplePatternItemsNoRest (*this);
  }
};

// Class representing patterns within a TuplePattern, with a rest pattern
// included
class TuplePatternItemsHasRest : public TuplePatternItems
{
  std::vector<std::unique_ptr<Pattern>> lower_patterns;
  std::vector<std::unique_ptr<Pattern>> upper_patterns;

public:
  TuplePatternItemsHasRest (
    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
  TuplePatternItemsHasRest (TuplePatternItemsHasRest 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
  TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest const &other)
  {
    lower_patterns.clear ();
    lower_patterns.reserve (other.lower_patterns.size ());
    for (const auto &e : other.lower_patterns)
      lower_patterns.push_back (e->clone_pattern ());

    lower_patterns.clear ();
    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
  TuplePatternItemsHasRest (TuplePatternItemsHasRest &&other) = default;
  TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest &&other)
    = default;

  std::string to_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  ItemType get_item_type () const override { return ItemType::HAS_REST; }

  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;
  }

  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;
  }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  TuplePatternItemsHasRest *clone_pattern_items_impl () const override
  {
    return new TuplePatternItemsHasRest (*this);
  }
};

// HIR node representing a tuple pattern
class TuplePattern : public Pattern
{
  std::unique_ptr<TuplePatternItems> items;
  location_t locus;
  Analysis::NodeMapping mappings;

public:
  std::string to_string () const override;

  // Returns true if the tuple pattern has items
  bool has_tuple_pattern_items () const { return items != nullptr; }

  TuplePattern (Analysis::NodeMapping mappings,
		std::unique_ptr<TuplePatternItems> items, location_t locus)
    : items (std::move (items)), locus (locus), mappings (mappings)
  {}

  // Copy constructor requires clone
  TuplePattern (TuplePattern const &other)
    : items (other.items->clone_tuple_pattern_items ()), locus (other.locus),
      mappings (other.mappings)
  {}

  // Overload assignment operator to clone
  TuplePattern &operator= (TuplePattern const &other)
  {
    items = other.items->clone_tuple_pattern_items ();
    locus = other.locus;
    mappings = other.mappings;

    return *this;
  }

  location_t get_locus () const override { return locus; }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  PatternType get_pattern_type () const override final
  {
    return PatternType::TUPLE;
  }

  TuplePatternItems &get_items () { return *items; }
  const TuplePatternItems &get_items () const { return *items; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  TuplePattern *clone_pattern_impl () const override
  {
    return new TuplePattern (*this);
  }
};

// Base abstract class representing SlicePattern patterns
class SlicePatternItems : public PatternItems
{
public:
  // Unique pointer custom clone function
  std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const
  {
    return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ());
  }

protected:
  // pure virtual clone implementation
  virtual SlicePatternItems *clone_pattern_items_impl () const override = 0;
};

// Class representing patterns within a SlicePattern, without a rest pattern
class SlicePatternItemsNoRest : public SlicePatternItems
{
  std::vector<std::unique_ptr<Pattern>> patterns;

public:
  SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
    : patterns (std::move (patterns))
  {}

  // Copy constructor with vector clone
  SlicePatternItemsNoRest (SlicePatternItemsNoRest 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
  SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other)
  {
    patterns.clear ();
    patterns.reserve (other.patterns.size ());
    for (const auto &e : other.patterns)
      patterns.push_back (e->clone_pattern ());

    return *this;
  }

  // move constructors
  SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default;
  SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other)
    = default;

  std::string to_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  ItemType get_item_type () const override { return ItemType::NO_REST; }

  std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
  const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
  {
    return patterns;
  }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  SlicePatternItemsNoRest *clone_pattern_items_impl () const override
  {
    return new SlicePatternItemsNoRest (*this);
  }
};

// Class representing patterns within a SlicePattern, with a rest pattern
// included
class SlicePatternItemsHasRest : public SlicePatternItems
{
  std::vector<std::unique_ptr<Pattern>> lower_patterns;
  std::vector<std::unique_ptr<Pattern>> upper_patterns;

public:
  SlicePatternItemsHasRest (
    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
  SlicePatternItemsHasRest (SlicePatternItemsHasRest 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
  SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other)
  {
    lower_patterns.clear ();
    lower_patterns.reserve (other.lower_patterns.size ());
    for (const auto &e : other.lower_patterns)
      lower_patterns.push_back (e->clone_pattern ());

    lower_patterns.clear ();
    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
  SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default;
  SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other)
    = default;

  std::string to_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  ItemType get_item_type () const override { return ItemType::HAS_REST; }

  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;
  }

  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;
  }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  SlicePatternItemsHasRest *clone_pattern_items_impl () const override
  {
    return new SlicePatternItemsHasRest (*this);
  }
};

// HIR node representing patterns that can match slices and arrays
class SlicePattern : public Pattern
{
  std::unique_ptr<SlicePatternItems> items;
  location_t locus;
  Analysis::NodeMapping mappings;

public:
  std::string to_string () const override;

  SlicePattern (Analysis::NodeMapping mappings,
		std::unique_ptr<SlicePatternItems> items, location_t locus)
    : items (std::move (items)), locus (locus), mappings (mappings)
  {}

  // Copy constructor requires clone
  SlicePattern (SlicePattern const &other)
    : items (other.items->clone_slice_pattern_items ()), locus (other.locus),
      mappings (other.mappings)
  {}

  // Overloaded assignment operator to vector clone
  SlicePattern &operator= (SlicePattern const &other)
  {
    items = other.items->clone_slice_pattern_items ();
    locus = other.locus;
    mappings = other.mappings;

    return *this;
  }

  // move constructors
  SlicePattern (SlicePattern &&other) = default;
  SlicePattern &operator= (SlicePattern &&other) = default;

  SlicePatternItems &get_items () { return *items; }
  const SlicePatternItems &get_items () const { return *items; }

  location_t get_locus () const override { return locus; }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  PatternType get_pattern_type () const override final
  {
    return PatternType::SLICE;
  }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  SlicePattern *clone_pattern_impl () const override
  {
    return new SlicePattern (*this);
  }
};

// HIR node for alternative patterns
class AltPattern : public Pattern
{
  std::vector<std::unique_ptr<Pattern>> alts;
  location_t locus;
  Analysis::NodeMapping mappings;

public:
  std::string to_string () const override;

  AltPattern (Analysis::NodeMapping mappings,
	      std::vector<std::unique_ptr<Pattern>> alts, location_t locus)
    : alts (std::move (alts)), locus (locus), mappings (mappings)
  {}

  // Copy constructor with vector clone
  AltPattern (AltPattern const &other)
    : locus (other.locus), mappings (other.mappings)
  {
    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;
    mappings = other.mappings;

    alts.clear ();
    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;

  std::vector<std::unique_ptr<Pattern>> &get_alts () { return alts; }
  const std::vector<std::unique_ptr<Pattern>> &get_alts () const
  {
    return alts;
  }

  location_t get_locus () const override { return locus; }

  void accept_vis (HIRFullVisitor &vis) override;
  void accept_vis (HIRPatternVisitor &vis) override;

  const Analysis::NodeMapping &get_mappings () const override final
  {
    return mappings;
  }

  PatternType get_pattern_type () const override final
  {
    return PatternType::ALT;
  }

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;

} // namespace HIR
} // namespace Rust

#endif
