// Copyright (C) 2020-2025 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_EXPR_H
#define RUST_HIR_EXPR_H

#include "rust-ast.h"
#include "rust-hir-expr-abstract.h"
#include "rust-hir-literal.h"
#include "rust-common.h"
#include "rust-hir-bound.h"
#include "rust-hir-attrs.h"
#include "rust-expr.h"
#include "rust-hir-map.h"
#include "rust-mapping-common.h"

namespace Rust {
namespace HIR {

// Loop label expression HIR node used with break and continue expressions
// TODO: inline?
class LoopLabel /*: public Node*/
{
  Lifetime label; // of type LIFETIME_OR_LABEL

  location_t locus;

  Analysis::NodeMapping mappings;

public:
  std::string as_string () const;

  LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label,
	     location_t locus);

  location_t get_locus () const { return locus; }

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

  Lifetime &get_lifetime () { return label; }
};

// HIR node for an expression with an accompanying block - abstract
class ExprWithBlock : public Expr
{
  // TODO: should this mean that a BlockExpr should be a member variable?
protected:
  ExprWithBlock (Analysis::NodeMapping mappings,
		 AST::AttrVec outer_attrs = AST::AttrVec ());

  // pure virtual clone implementation
  virtual ExprWithBlock *clone_expr_with_block_impl () const = 0;

  // prevent having to define multiple clone expressions
  ExprWithBlock *clone_expr_impl () const override
  {
    return clone_expr_with_block_impl ();
  }

public:
  // Unique pointer custom clone function
  std::unique_ptr<ExprWithBlock> clone_expr_with_block () const
  {
    return std::unique_ptr<ExprWithBlock> (clone_expr_with_block_impl ());
  }

  BlockType get_block_expr_type () const final override
  {
    return BlockType::WITH_BLOCK;
  };
};

// Literals? Or literal base?
class LiteralExpr : public ExprWithoutBlock
{
  Literal literal;
  location_t locus;
  bool negative_number = false;

public:
  std::string as_string () const override
  {
    return "( " + literal.as_string () + " (" + get_mappings ().as_string ()
	   + "))";
  }

  Literal::LitType get_lit_type () const { return literal.get_lit_type (); }

  LiteralExpr (Analysis::NodeMapping mappings, std::string value_as_string,
	       Literal::LitType type, PrimitiveCoreType type_hint,
	       location_t locus, AST::AttrVec outer_attrs);

  LiteralExpr (Analysis::NodeMapping mappings, Literal literal,
	       location_t locus, AST::AttrVec outer_attrs);

  // Unique pointer custom clone function
  std::unique_ptr<LiteralExpr> clone_literal_expr () const
  {
    return std::unique_ptr<LiteralExpr> (clone_literal_expr_impl ());
  }

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

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

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

  ExprType get_expression_type () const override final { return ExprType::Lit; }

  bool is_negative () const { return negative_number; }
  void set_negative ()
  {
    rust_assert (get_lit_type () == Literal::LitType::INT
		 || get_lit_type () == Literal::LitType::FLOAT);
    negative_number = true;
  }

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

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

  /* not virtual as currently no subclasses of LiteralExpr, but could be in
   * future */
  /*virtual*/ LiteralExpr *clone_literal_expr_impl () const
  {
    return new LiteralExpr (*this);
  }
};

/* Represents an expression using unary or binary operators as HIR node. Can be
 * overloaded. */
class OperatorExpr : public ExprWithoutBlock
{
  // TODO: create binary and unary operator subclasses?
private:
  location_t locus;

protected:
  /* Variable must be protected to allow derived classes to use it as a first
   * class citizen */
  std::unique_ptr<Expr> main_or_left_expr;

  // Constructor (only for initialisation of expr purposes)
  OperatorExpr (Analysis::NodeMapping mappings,
		std::unique_ptr<Expr> main_or_left_expr,
		AST::AttrVec outer_attribs, location_t locus);

  // Copy constructor (only for initialisation of expr purposes)
  OperatorExpr (OperatorExpr const &other);

  // Overload assignment operator to deep copy expr
  OperatorExpr &operator= (OperatorExpr const &other);

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

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

  Expr &get_expr () { return *main_or_left_expr; }

  ExprType get_expression_type () const override final
  {
    return ExprType::Operator;
  }
};

/* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be
 * overloaded. */
class BorrowExpr : public OperatorExpr
{
  Mutability mut;
  bool raw;

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

  BorrowExpr (Analysis::NodeMapping mappings,
	      std::unique_ptr<Expr> borrow_lvalue, Mutability mut, bool raw,
	      AST::AttrVec outer_attribs, location_t locus);

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

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

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

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

// Unary prefix * deference operator
class DereferenceExpr : public OperatorExpr
{
public:
  std::string as_string () const override;

  // Constructor calls OperatorExpr's protected constructor
  DereferenceExpr (Analysis::NodeMapping mappings,
		   std::unique_ptr<Expr> deref_lvalue,
		   AST::AttrVec outer_attribs, location_t locus);

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

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

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

// Unary postfix ? error propogation operator. Cannot be overloaded.
class ErrorPropagationExpr : public OperatorExpr
{
public:
  std::string as_string () const override;

  // Constructor calls OperatorExpr's protected constructor
  ErrorPropagationExpr (Analysis::NodeMapping mappings,
			std::unique_ptr<Expr> potential_error_value,
			AST::AttrVec outer_attribs, location_t locus);

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

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

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

// Unary prefix - or ! negation or NOT operators.
class NegationExpr : public OperatorExpr
{
public:
  using ExprType = NegationOperator;

private:
  /* Note: overload negation via std::ops::Neg and not via std::ops::Not
   * Negation only works for signed integer and floating-point types, NOT only
   * works for boolean and integer types (via bitwise NOT) */
  ExprType expr_type;

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

  ExprType get_expr_type () const { return expr_type; }

  // Constructor calls OperatorExpr's protected constructor
  NegationExpr (Analysis::NodeMapping mappings,
		std::unique_ptr<Expr> negated_value, ExprType expr_kind,
		AST::AttrVec outer_attribs, location_t locus);

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

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

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

// Infix binary operators. +, -, *, /, %, &, |, ^, <<, >>
class ArithmeticOrLogicalExpr : public OperatorExpr
{
public:
  using ExprType = ArithmeticOrLogicalOperator;

private:
  // Note: overloading trait specified in comments
  ExprType expr_type;

  std::unique_ptr<Expr> right_expr;

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

  ExprType get_expr_type () const { return expr_type; }

  // Constructor calls OperatorExpr's protected constructor
  ArithmeticOrLogicalExpr (Analysis::NodeMapping mappings,
			   std::unique_ptr<Expr> left_value,
			   std::unique_ptr<Expr> right_value,
			   ExprType expr_kind, location_t locus);
  // outer attributes not allowed

  // Copy constructor - probably required due to unique pointer
  ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr const &other);

  // Overload assignment operator
  ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr const &other);

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

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

  void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); }
  void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); }

  Expr &get_lhs () { return *main_or_left_expr; }
  Expr &get_rhs () { return *right_expr; }

  std::string get_operator_str () const;

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

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

// Infix binary comparison operators. ==, !=, <, <=, >, >=
class ComparisonExpr : public OperatorExpr
{
public:
  using ExprType = ComparisonOperator;

private:
  // Note: overloading trait specified in comments
  ExprType expr_type;

  std::unique_ptr<Expr> right_expr;

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

  ExprType get_expr_type () const { return expr_type; }

  // Constructor requires pointers for polymorphism
  ComparisonExpr (Analysis::NodeMapping mappings,
		  std::unique_ptr<Expr> left_value,
		  std::unique_ptr<Expr> right_value, ExprType comparison_kind,
		  location_t locus);
  // outer attributes not allowed

  // Copy constructor also calls OperatorExpr's protected constructor
  ComparisonExpr (ComparisonExpr const &other);

  // Overload assignment operator to deep copy
  ComparisonExpr &operator= (ComparisonExpr const &other);

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

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

  Expr &get_lhs () { return *main_or_left_expr; }
  Expr &get_rhs () { return *right_expr; }

  ExprType get_kind () { return expr_type; }

  /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2)
   * maybe? */
protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  ComparisonExpr *clone_expr_impl () const override
  {
    return new ComparisonExpr (*this);
  }

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

// Infix binary lazy boolean logical operators && and ||.
class LazyBooleanExpr : public OperatorExpr
{
public:
  using ExprType = LazyBooleanOperator;

private:
  ExprType expr_type;

  std::unique_ptr<Expr> right_expr;

public:
  // Constructor calls OperatorExpr's protected constructor
  LazyBooleanExpr (Analysis::NodeMapping mappings,
		   std::unique_ptr<Expr> left_bool_expr,
		   std::unique_ptr<Expr> right_bool_expr, ExprType expr_kind,
		   location_t locus);
  // outer attributes not allowed

  // Copy constructor also calls OperatorExpr's protected constructor
  LazyBooleanExpr (LazyBooleanExpr const &other);

  // Overload assignment operator to deep copy
  LazyBooleanExpr &operator= (LazyBooleanExpr const &other);

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

  std::string as_string () const override;

  ExprType get_expr_type () const { return expr_type; }

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

  Expr &get_lhs () { return *main_or_left_expr; }
  Expr &get_rhs () { return *right_expr; }

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

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

// Binary infix "as" chir expression.
class TypeCastExpr : public OperatorExpr
{
  std::unique_ptr<Type> type_to_convert_to;

  // Note: only certain type casts allowed, outlined in reference
public:
  std::string as_string () const override;

  // Constructor requires calling protected constructor of OperatorExpr
  TypeCastExpr (Analysis::NodeMapping mappings,
		std::unique_ptr<Expr> expr_to_cast,
		std::unique_ptr<Type> type_to_cast_to, location_t locus);
  // outer attributes not allowed

  // Copy constructor also requires calling protected constructor
  TypeCastExpr (TypeCastExpr const &other);

  // Overload assignment operator to deep copy
  TypeCastExpr &operator= (TypeCastExpr const &other);

  // move constructors as not supported in c++03
  TypeCastExpr (TypeCastExpr &&other) = default;
  TypeCastExpr &operator= (TypeCastExpr &&other) = default;

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

  // FIXME: isn't it the same as get_expr() from parent?
  Expr &get_casted_expr () { return *main_or_left_expr; }

  Type &get_type_to_convert_to () { return *type_to_convert_to; }

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

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

// Binary assignment expression.
class AssignmentExpr : public OperatorExpr
{
  std::unique_ptr<Expr> right_expr;

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

  // Call OperatorExpr constructor to initialise left_expr
  AssignmentExpr (Analysis::NodeMapping mappings,
		  std::unique_ptr<Expr> value_to_assign_to,
		  std::unique_ptr<Expr> value_to_assign, location_t locus);
  // outer attributes not allowed

  // Call OperatorExpr constructor in copy constructor, as well as clone
  AssignmentExpr (AssignmentExpr const &other);

  // Overload assignment operator to clone unique_ptr right_expr
  AssignmentExpr &operator= (AssignmentExpr const &other);

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

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

  void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); }
  void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); }

  Expr &get_lhs () { return *main_or_left_expr; }
  Expr &get_rhs () { return *right_expr; }

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

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

class CompoundAssignmentExpr : public OperatorExpr
{
public:
  using ExprType = ArithmeticOrLogicalOperator;

private:
  // Note: overloading trait specified in comments
  ExprType expr_type;
  std::unique_ptr<Expr> right_expr;

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

  ExprType get_expr_type () const { return expr_type; }

  // Use pointers in constructor to enable polymorphism
  CompoundAssignmentExpr (Analysis::NodeMapping mappings,
			  std::unique_ptr<Expr> value_to_assign_to,
			  std::unique_ptr<Expr> value_to_assign,
			  ExprType expr_kind, location_t locus);
  // outer attributes not allowed

  // Have clone in copy constructor
  CompoundAssignmentExpr (CompoundAssignmentExpr const &other);

  // Overload assignment operator to clone
  CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other);

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

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

  Expr &get_lhs () { return *main_or_left_expr; }

  Expr &get_rhs () { return *right_expr; }

  void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); }
  void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); }

  std::string get_operator_str () const;

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

// Expression in parentheses (i.e. like literally just any 3 + (2 * 6))
class GroupedExpr : public ExprWithoutBlock, public WithInnerAttrs
{
  std::unique_ptr<Expr> expr_in_parens;

  location_t locus;

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

  GroupedExpr (Analysis::NodeMapping mappings,
	       std::unique_ptr<Expr> parenthesised_expr,
	       AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
	       location_t locus);

  // Copy constructor includes clone for expr_in_parens
  GroupedExpr (GroupedExpr const &other);

  // Overloaded assignment operator to clone expr_in_parens
  GroupedExpr &operator= (GroupedExpr const &other);

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

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

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

  Expr &get_expr_in_parens () { return *expr_in_parens; }

  ExprType get_expression_type () const override final
  {
    return ExprType::Grouped;
  }

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

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

// Base array initialisation internal element representation thing (abstract)
// aka ArrayElements
class ArrayElems : public FullVisitable
{
public:
  enum ArrayExprType
  {
    VALUES,
    COPIED,
  };

  ArrayElems (Analysis::NodeMapping mappings) : mappings (mappings){};

  virtual ~ArrayElems () {}

  // Unique pointer custom clone ArrayElems function
  std::unique_ptr<ArrayElems> clone_array_elems () const
  {
    return std::unique_ptr<ArrayElems> (clone_array_elems_impl ());
  }

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

  virtual void accept_vis (HIRFullVisitor &vis) = 0;

  virtual ArrayExprType get_array_expr_type () const = 0;

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

protected:
  // pure virtual clone implementation
  virtual ArrayElems *clone_array_elems_impl () const = 0;

  Analysis::NodeMapping mappings;
};

// Value array elements
class ArrayElemsValues : public ArrayElems
{
  std::vector<std::unique_ptr<Expr>> values;

  // TODO: should this store location data?

public:
  ArrayElemsValues (Analysis::NodeMapping mappings,
		    std::vector<std::unique_ptr<Expr>> elems);

  // copy constructor with vector clone
  ArrayElemsValues (ArrayElemsValues const &other);

  // overloaded assignment operator with vector clone
  ArrayElemsValues &operator= (ArrayElemsValues const &other);

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

  std::string as_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  size_t get_num_elements () const { return values.size (); }

  std::vector<std::unique_ptr<Expr>> &get_values () { return values; }

  ArrayElems::ArrayExprType get_array_expr_type () const override final
  {
    return ArrayElems::ArrayExprType::VALUES;
  }

protected:
  ArrayElemsValues *clone_array_elems_impl () const override
  {
    return new ArrayElemsValues (*this);
  }
};

// Copied array element and number of copies
class ArrayElemsCopied : public ArrayElems
{
  std::unique_ptr<Expr> elem_to_copy;
  std::unique_ptr<Expr> num_copies;

public:
  // Constructor requires pointers for polymorphism
  ArrayElemsCopied (Analysis::NodeMapping mappings,
		    std::unique_ptr<Expr> copied_elem,
		    std::unique_ptr<Expr> copy_amount);

  // Copy constructor required due to unique_ptr - uses custom clone
  ArrayElemsCopied (ArrayElemsCopied const &other);

  // Overloaded assignment operator for deep copying
  ArrayElemsCopied &operator= (ArrayElemsCopied const &other);

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

  std::string as_string () const override;

  void accept_vis (HIRFullVisitor &vis) override;

  Expr &get_elem_to_copy () { return *elem_to_copy; }

  Expr &get_num_copies_expr () { return *num_copies; }

  ArrayElems::ArrayExprType get_array_expr_type () const override final
  {
    return ArrayElems::ArrayExprType::COPIED;
  }

protected:
  ArrayElemsCopied *clone_array_elems_impl () const override
  {
    return new ArrayElemsCopied (*this);
  }
};

// Array definition-ish expression
class ArrayExpr : public ExprWithoutBlock, public WithInnerAttrs
{
  std::unique_ptr<ArrayElems> internal_elements;

  location_t locus;

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

  // Returns whether array expr has array elems or if it is just empty.
  bool has_array_elems () const { return internal_elements != nullptr; }

  // Constructor requires ArrayElems pointer
  ArrayExpr (Analysis::NodeMapping mappings,
	     std::unique_ptr<ArrayElems> array_elems,
	     AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
	     location_t locus);

  // Copy constructor requires cloning ArrayElems for polymorphism to hold
  ArrayExpr (ArrayExpr const &other);

  // Overload assignment operator to clone internal_elements
  ArrayExpr &operator= (ArrayExpr const &other);

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

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

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

  ArrayElems &get_internal_elements () { return *internal_elements; };

  ExprType get_expression_type () const override final
  {
    return ExprType::Array;
  }

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

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

class ArrayIndexExpr : public ExprWithoutBlock
{
  std::unique_ptr<Expr> array_expr;
  std::unique_ptr<Expr> index_expr;

  location_t locus;

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

  ArrayIndexExpr (Analysis::NodeMapping mappings,
		  std::unique_ptr<Expr> array_expr,
		  std::unique_ptr<Expr> array_index_expr,
		  AST::AttrVec outer_attribs, location_t locus);

  // Copy constructor requires special cloning due to unique_ptr
  ArrayIndexExpr (ArrayIndexExpr const &other);

  // Overload assignment operator to clone unique_ptrs
  ArrayIndexExpr &operator= (ArrayIndexExpr const &other);

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

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

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

  Expr &get_array_expr () { return *array_expr; }
  Expr &get_index_expr () { return *index_expr; }

  ExprType get_expression_type () const override final
  {
    return ExprType::ArrayIndex;
  }

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

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

// HIR representation of a tuple
class TupleExpr : public ExprWithoutBlock, public WithInnerAttrs
{
  std::vector<std::unique_ptr<Expr>> tuple_elems;
  // replaces (inlined version of) TupleElements

  location_t locus;

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

  TupleExpr (Analysis::NodeMapping mappings,
	     std::vector<std::unique_ptr<Expr>> tuple_elements,
	     AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
	     location_t locus);

  // copy constructor with vector clone
  TupleExpr (TupleExpr const &other);

  // overloaded assignment operator to vector clone
  TupleExpr &operator= (TupleExpr const &other);

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

  /* Note: syntactically, can disambiguate single-element tuple from parens with
   * comma, i.e. (0,) rather than (0) */

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

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

  const std::vector<std::unique_ptr<Expr>> &get_tuple_elems () const
  {
    return tuple_elems;
  }
  std::vector<std::unique_ptr<Expr>> &get_tuple_elems () { return tuple_elems; }

  bool is_unit () const { return tuple_elems.size () == 0; }

  ExprType get_expression_type () const override final
  {
    return ExprType::Tuple;
  }

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

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

class TupleIndexExpr : public ExprWithoutBlock
{
  std::unique_ptr<Expr> tuple_expr;
  TupleIndex tuple_index;
  location_t locus;

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

  TupleIndex get_tuple_index () const { return tuple_index; }

  TupleIndexExpr (Analysis::NodeMapping mappings,
		  std::unique_ptr<Expr> tuple_expr, TupleIndex index,
		  AST::AttrVec outer_attribs, location_t locus);

  // Copy constructor requires a clone for tuple_expr
  TupleIndexExpr (TupleIndexExpr const &other);

  // Overload assignment operator in order to clone
  TupleIndexExpr &operator= (TupleIndexExpr const &other);

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

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

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

  Expr &get_tuple_expr () { return *tuple_expr; }

  ExprType get_expression_type () const override final
  {
    return ExprType::TupleIdx;
  }

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

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

// Base struct/tuple/union value creator HIR node (abstract)
class StructExpr : public ExprWithoutBlock
{
protected:
  PathInExpression struct_name;

  // Protected constructor to allow initialising struct_name
  StructExpr (Analysis::NodeMapping mappings, PathInExpression struct_path,
	      AST::AttrVec outer_attribs);

public:
  PathInExpression &get_struct_name () { return struct_name; }

  std::string as_string () const override;

  ExprType get_expression_type () const override final
  {
    return ExprType::Struct;
  }
};

// Actual HIR node of the struct creator (with no fields). Not abstract!
class StructExprStruct : public StructExpr, public WithInnerAttrs
{
  location_t locus;

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

  // Constructor has to call protected constructor of base class
  StructExprStruct (Analysis::NodeMapping mappings,
		    PathInExpression struct_path, AST::AttrVec inner_attribs,
		    AST::AttrVec outer_attribs, location_t locus);

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

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

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

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

/* HIR node representing expression used to fill a struct's fields from another
 * struct */
struct StructBase
{
private:
  std::unique_ptr<Expr> base_struct;

public:
  // TODO: should this store location data?
  StructBase (std::unique_ptr<Expr> base_struct_ptr);

  // Copy constructor requires clone
  StructBase (StructBase const &other);

  // Destructor
  ~StructBase () = default;

  // Overload assignment operator to clone base_struct
  StructBase &operator= (StructBase const &other);

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

  // Returns a null expr-ed StructBase - error state
  static StructBase error () { return StructBase (nullptr); }

  // Returns whether StructBase is in error state
  bool is_invalid () const { return base_struct == nullptr; }

  std::string as_string () const;

  Expr &get_base () { return *base_struct; }
};

/* Base HIR node for a single struct expression field (in struct instance
 * creation) - abstract */
class StructExprField : public FullVisitable
{
public:
  enum StructExprFieldKind
  {
    IDENTIFIER_VALUE,
    IDENTIFIER,
    INDEX_VALUE,
  };

  virtual ~StructExprField () {}

  // Unique pointer custom clone function
  std::unique_ptr<StructExprField> clone_struct_expr_field () const
  {
    return std::unique_ptr<StructExprField> (clone_struct_expr_field_impl ());
  }

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

  virtual void accept_vis (HIRFullVisitor &vis) = 0;
  virtual void accept_vis (HIRExpressionVisitor &vis) = 0;

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

  location_t get_locus () { return locus; }

  virtual StructExprFieldKind get_kind () const = 0;

protected:
  // pure virtual clone implementation
  virtual StructExprField *clone_struct_expr_field_impl () const = 0;

  StructExprField (Analysis::NodeMapping mapping, location_t locus);

  Analysis::NodeMapping mappings;
  location_t locus;
};

// Identifier-only variant of StructExprField HIR node
class StructExprFieldIdentifier : public StructExprField
{
private:
  Identifier field_name;

  // TODO: should this store location data?
public:
  StructExprFieldIdentifier (Analysis::NodeMapping mapping,
			     Identifier field_identifier, location_t locus);

  std::string as_string () const override { return field_name.as_string (); }

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

  Identifier get_field_name () const { return field_name; }

  StructExprFieldKind get_kind () const override
  {
    return StructExprFieldKind::IDENTIFIER;
  }

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

/* Base HIR node for a single struct expression field with an assigned value -
 * abstract */
class StructExprFieldWithVal : public StructExprField
{
  std::unique_ptr<Expr> value;

protected:
  StructExprFieldWithVal (Analysis::NodeMapping mapping,
			  std::unique_ptr<Expr> field_value, location_t locus);

  // Copy constructor requires clone
  StructExprFieldWithVal (StructExprFieldWithVal const &other);

  // Overload assignment operator to clone unique_ptr
  StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other);

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

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

  Expr &get_value () { return *value; }
};

// Identifier and value variant of StructExprField HIR node
class StructExprFieldIdentifierValue : public StructExprFieldWithVal
{
public:
  Identifier field_name;

  // TODO: should this store location data?

  StructExprFieldIdentifierValue (Analysis::NodeMapping mapping,
				  Identifier field_identifier,
				  std::unique_ptr<Expr> field_value,
				  location_t locus);

  std::string as_string () const override;

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

  Identifier get_field_name () const { return field_name; }

  StructExprFieldKind get_kind () const override
  {
    return StructExprFieldKind::IDENTIFIER_VALUE;
  }

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

// Tuple index and value variant of StructExprField HIR node
class StructExprFieldIndexValue : public StructExprFieldWithVal
{
public:
  TupleIndex index;

  // TODO: should this store location data?

  StructExprFieldIndexValue (Analysis::NodeMapping mapping,
			     TupleIndex tuple_index,
			     std::unique_ptr<Expr> field_value,
			     location_t locus);

  std::string as_string () const override;

  TupleIndex get_tuple_index () const { return index; };

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

  StructExprFieldKind get_kind () const override
  {
    return StructExprFieldKind::INDEX_VALUE;
  }

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

// HIR node of a struct creator with fields
class StructExprStructFields : public StructExprStruct
{
  // std::vector<StructExprField> fields;
  std::vector<std::unique_ptr<StructExprField>> fields;
  tl::optional<std::unique_ptr<StructBase>> struct_base;

public:
  // For unions there is just one field, the index
  // is set when type checking
  int union_index = -1;

  std::string as_string () const override;

  bool has_struct_base () const { return struct_base.has_value (); }

  // Constructor for StructExprStructFields when no struct base is used
  StructExprStructFields (
    Analysis::NodeMapping mappings, PathInExpression struct_path,
    std::vector<std::unique_ptr<StructExprField>> expr_fields, location_t locus,
    tl::optional<std::unique_ptr<StructBase>> base_struct,
    AST::AttrVec inner_attribs, AST::AttrVec outer_attribs);

  // copy constructor with vector clone
  StructExprStructFields (StructExprStructFields const &other);

  // overloaded assignment operator with vector clone
  StructExprStructFields &operator= (StructExprStructFields const &other);

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

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

  std::vector<std::unique_ptr<StructExprField>> &get_fields ()
  {
    return fields;
  };

  const std::vector<std::unique_ptr<StructExprField>> &get_fields () const
  {
    return fields;
  };

  StructBase &get_struct_base () { return *struct_base.value (); }

  void
  set_fields_as_owner (std::vector<std::unique_ptr<StructExprField>> new_fields)
  {
    fields = std::move (new_fields);
  }

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

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

// HIR node of the functional update struct creator
class StructExprStructBase : public StructExprStruct
{
  StructBase struct_base;

public:
  StructExprStructBase (Analysis::NodeMapping mappings,
			PathInExpression struct_path, StructBase base_struct,
			AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
			location_t locus);

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

  StructBase &get_struct_base () { return struct_base; }

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

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

// Function call expression HIR node
class CallExpr : public ExprWithoutBlock
{
  std::unique_ptr<Expr> function;
  std::vector<std::unique_ptr<Expr>> params;
  location_t locus;

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

  CallExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> function_expr,
	    std::vector<std::unique_ptr<Expr>> function_params,
	    AST::AttrVec outer_attribs, location_t locus);

  // copy constructor requires clone
  CallExpr (CallExpr const &other);

  // Overload assignment operator to clone
  CallExpr &operator= (CallExpr const &other);

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

  // Returns whether function call has parameters.
  bool has_params () const { return !params.empty (); }

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

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

  bool has_fnexpr () const { return function != nullptr; }
  Expr &get_fnexpr () { return *function; }

  size_t num_params () const { return params.size (); }

  std::vector<std::unique_ptr<Expr>> &get_arguments () { return params; }

  const std::vector<std::unique_ptr<Expr>> &get_arguments () const
  {
    return params;
  }

  ExprType get_expression_type () const override final
  {
    return ExprType::Call;
  }

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

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

// Method call expression HIR node
class MethodCallExpr : public ExprWithoutBlock
{
  std::unique_ptr<Expr> receiver;
  PathExprSegment method_name;
  std::vector<std::unique_ptr<Expr>> params;
  location_t locus;

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

  MethodCallExpr (Analysis::NodeMapping mappings,
		  std::unique_ptr<Expr> call_receiver,
		  PathExprSegment method_path,
		  std::vector<std::unique_ptr<Expr>> method_params,
		  AST::AttrVec outer_attribs, location_t locus);

  // copy constructor required due to cloning
  MethodCallExpr (MethodCallExpr const &other);

  // Overload assignment operator to clone receiver object
  MethodCallExpr &operator= (MethodCallExpr const &other);

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

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

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

  Expr &get_receiver () { return *receiver; }

  PathExprSegment &get_method_name () { return method_name; };
  const PathExprSegment &get_method_name () const { return method_name; };

  bool has_params () const { return !params.empty (); }
  size_t num_params () const { return params.size (); }

  std::vector<std::unique_ptr<Expr>> &get_arguments () { return params; }

  const std::vector<std::unique_ptr<Expr>> &get_arguments () const
  {
    return params;
  }

  ExprType get_expression_type () const override final
  {
    return ExprType::MethodCall;
  }

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

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

// aka FieldExpression
// Struct or union field access expression HIR node
class FieldAccessExpr : public ExprWithoutBlock
{
  std::unique_ptr<Expr> receiver;
  Identifier field;

  location_t locus;

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

  FieldAccessExpr (Analysis::NodeMapping mappings,
		   std::unique_ptr<Expr> field_access_receiver,
		   Identifier field_name, AST::AttrVec outer_attribs,
		   location_t locus);

  // Copy constructor required due to unique_ptr cloning
  FieldAccessExpr (FieldAccessExpr const &other);

  // Overload assignment operator to clone unique_ptr
  FieldAccessExpr &operator= (FieldAccessExpr const &other);

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

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

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

  Expr &get_receiver_expr () { return *receiver; }

  Identifier get_field_name () const { return field; }

  ExprType get_expression_type () const override final
  {
    return ExprType::FieldAccess;
  }

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

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

// Closure parameter data structure
struct ClosureParam
{
private:
  std::vector<AST::Attribute> outer_attrs;
  std::unique_ptr<Pattern> pattern;
  std::unique_ptr<Type> type;
  location_t locus;

public:
  // Returns whether the type of the parameter has been given.
  bool has_type_given () const { return type != nullptr; }

  // Constructor for closure parameter
  ClosureParam (std::unique_ptr<Pattern> param_pattern, location_t locus,
		std::unique_ptr<Type> param_type = nullptr,
		std::vector<AST::Attribute> outer_attrs = {});

  // Copy constructor required due to cloning as a result of unique_ptrs
  ClosureParam (ClosureParam const &other);

  ~ClosureParam () = default;

  // Assignment operator must be overloaded to clone as well
  ClosureParam &operator= (ClosureParam const &other);

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

  std::string as_string () const;

  const std::vector<AST::Attribute> &get_outer_attrs () const
  {
    return outer_attrs;
  }
  std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; }

  Pattern &get_pattern () { return *pattern; }

  Type &get_type () { return *type; }

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

// Base closure definition expression HIR node - abstract
class ClosureExpr : public ExprWithoutBlock
{
private:
  bool has_move;
  std::vector<ClosureParam> params;
  location_t locus;
  std::unique_ptr<Type> return_type;
  std::unique_ptr<Expr> expr;

public:
  ClosureExpr (Analysis::NodeMapping mappings,
	       std::vector<ClosureParam> closure_params,
	       std::unique_ptr<Type> closure_return_type,
	       std::unique_ptr<Expr> closure_expr, bool has_move,
	       AST::AttrVec outer_attribs, location_t locus);

  // Copy constructor requires cloning
  ClosureExpr (ClosureExpr const &other);

  // Overload assignment operator to clone unique_ptrs
  ClosureExpr &operator= (ClosureExpr const &other);

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

  std::string as_string () const override;

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

  ExprType get_expression_type () const override final
  {
    return ExprType::Closure;
  }

  bool get_has_move () const { return has_move; }

  bool has_return_type () const { return return_type != nullptr; }

  Type &get_return_type () { return *return_type; };
  Expr &get_expr () { return *expr; }

  bool has_params () const { return !params.empty (); }
  std::vector<ClosureParam> &get_params () { return params; }

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

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

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

// A block HIR node
class BlockExpr : public ExprWithBlock, public WithInnerAttrs
{
  // FIXME this should be private + get/set
public:
  std::vector<std::unique_ptr<Stmt>> statements;
  std::unique_ptr<Expr> expr;
  bool tail_reachable;
  tl::optional<LoopLabel> label;
  location_t start_locus;
  location_t end_locus;

  std::string as_string () const override;

  AST::AttrVec get_inner_attrs () const { return inner_attrs; }

  // Returns whether the block contains statements.
  bool has_statements () const { return !statements.empty (); }

  // Returns whether the block contains an expression
  bool has_expr () const { return expr != nullptr; }

  bool is_tail_reachable () const { return tail_reachable; }

  BlockExpr (Analysis::NodeMapping mappings,
	     std::vector<std::unique_ptr<Stmt>> block_statements,
	     std::unique_ptr<Expr> block_expr, bool tail_reachable,
	     AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
	     tl::optional<LoopLabel> label, location_t start_locus,
	     location_t end_locus);

  // Copy constructor with clone
  BlockExpr (BlockExpr const &other);

  // Overloaded assignment operator to clone pointer
  BlockExpr &operator= (BlockExpr const &other);

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

  // Unique pointer custom clone function
  std::unique_ptr<BlockExpr> clone_block_expr () const
  {
    return std::unique_ptr<BlockExpr> (clone_block_expr_impl ());
  }

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

  location_t get_start_locus () const { return start_locus; }

  location_t get_end_locus () const { return end_locus; }

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

  bool is_final_stmt (Stmt *stmt) { return statements.back ().get () == stmt; }

  bool has_final_expr () { return expr != nullptr; }
  Expr &get_final_expr () { return *expr; }

  std::vector<std::unique_ptr<Stmt>> &get_statements () { return statements; }

  ExprType get_expression_type () const final override
  {
    return ExprType::Block;
  }

  bool has_label () const { return label.has_value (); }
  LoopLabel &get_label () { return label.value (); }

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

  /* Use covariance to implement clone function as returning this object rather
   * than base */
  BlockExpr *clone_expr_with_block_impl () const override
  {
    return clone_block_expr_impl ();
  }

  /* This is the base method as not an abstract class - not virtual but could be
   * in future if required. */
  /*virtual*/ BlockExpr *clone_block_expr_impl () const
  {
    return new BlockExpr (*this);
  }
};

class AnonConst : public ExprWithBlock
{
public:
  enum class Kind
  {
    Explicit,
    DeferredInference
  };

  AnonConst (Analysis::NodeMapping mappings, std::unique_ptr<Expr> &&expr,
	     location_t locus = UNKNOWN_LOCATION);
  AnonConst (Analysis::NodeMapping mappings,
	     location_t locus = UNKNOWN_LOCATION);
  AnonConst (const AnonConst &other);
  AnonConst operator= (const AnonConst &other);

  std::string as_string () const override;

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

  ExprType get_expression_type () const final override
  {
    return ExprType::AnonConst;
  }

  location_t get_locus () const override { return locus; }

  Expr &get_inner_expr ()
  {
    rust_assert (kind == Kind::Explicit);
    return *expr.value ();
  }

  const Expr &get_inner_expr () const
  {
    rust_assert (kind == Kind::Explicit);
    return *expr.value ();
  }

  bool is_deferred () const { return kind == Kind::DeferredInference; }

private:
  location_t locus;
  Kind kind;
  tl::optional<std::unique_ptr<Expr>> expr;

  AnonConst *clone_expr_with_block_impl () const override
  {
    return new AnonConst (*this);
  }
};

class ConstBlock : public ExprWithBlock
{
public:
  ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr,
	      location_t locus = UNKNOWN_LOCATION,
	      AST::AttrVec outer_attrs = {});
  ConstBlock (const ConstBlock &other);
  ConstBlock operator= (const ConstBlock &other);

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

  std::string as_string () const override;

  ExprType get_expression_type () const final override
  {
    return ExprType::ConstBlock;
  }

  location_t get_locus () const override { return locus; }
  AnonConst &get_const_expr () { return expr; }
  const AnonConst &get_const_expr () const { return expr; }

private:
  AnonConst expr;
  location_t locus;

  ConstBlock *clone_expr_with_block_impl () const override
  {
    return new ConstBlock (*this);
  }
};

// HIR node representing continue expression within loops
class ContinueExpr : public ExprWithoutBlock
{
  tl::optional<Lifetime> label;
  location_t locus;

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

  // Returns true if the continue expr has a label.
  bool has_label () const { return label.has_value (); }

  // Constructor for a ContinueExpr with a label.
  ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
		tl::optional<Lifetime> label,
		AST::AttrVec outer_attribs = AST::AttrVec ());

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

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

  Lifetime &get_label () { return label.value (); }
  const Lifetime &get_label () const { return label.value (); }

  ExprType get_expression_type () const final override
  {
    return ExprType::Continue;
  }

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

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

// HIR node representing break expression within loops
class BreakExpr : public ExprWithoutBlock
{
  // bool has_label;
  tl::optional<Lifetime> label;

  // bool has_break_expr;
  std::unique_ptr<Expr> break_expr;

  location_t locus;

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

  // Returns whether the break expression has a label or not.
  bool has_label () const { return label.has_value (); }

  /* Returns whether the break expression has an expression used in the break or
   * not. */
  bool has_break_expr () const { return break_expr != nullptr; }

  // Constructor for a break expression
  BreakExpr (Analysis::NodeMapping mappings, location_t locus,
	     tl::optional<Lifetime> break_label,
	     std::unique_ptr<Expr> expr_in_break = nullptr,
	     AST::AttrVec outer_attribs = AST::AttrVec ());

  // Copy constructor defined to use clone for unique pointer
  BreakExpr (BreakExpr const &other);

  // Overload assignment operator to clone unique pointer
  BreakExpr &operator= (BreakExpr const &other);

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

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

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

  Lifetime &get_label () { return label.value (); }
  const Lifetime &get_label () const { return label.value (); }

  Expr &get_expr () { return *break_expr; }

  ExprType get_expression_type () const override final
  {
    return ExprType::Break;
  }

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

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

// Base range expression HIR node object - abstract
class RangeExpr : public ExprWithoutBlock
{
  location_t locus;

protected:
  // outer attributes not allowed before range expressions
  RangeExpr (Analysis::NodeMapping mappings, location_t locus);

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

  ExprType get_expression_type () const override final
  {
    return ExprType::Range;
  }
};

// Range from (inclusive) and to (exclusive) expression HIR node object
// aka RangeExpr; constructs a std::ops::Range object
class RangeFromToExpr : public RangeExpr
{
  std::unique_ptr<Expr> from;
  std::unique_ptr<Expr> to;

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

  RangeFromToExpr (Analysis::NodeMapping mappings,
		   std::unique_ptr<Expr> range_from,
		   std::unique_ptr<Expr> range_to, location_t locus);

  // Copy constructor with cloning
  RangeFromToExpr (RangeFromToExpr const &other);

  // Overload assignment operator to clone unique pointers
  RangeFromToExpr &operator= (RangeFromToExpr const &other);

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

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

  Expr &get_from_expr () { return *from; }
  Expr &get_to_expr () { return *to; }

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

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

// Range from (inclusive) expression HIR node object
// constructs a std::ops::RangeFrom object
class RangeFromExpr : public RangeExpr
{
  std::unique_ptr<Expr> from;

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

  RangeFromExpr (Analysis::NodeMapping mappings,
		 std::unique_ptr<Expr> range_from, location_t locus);

  // Copy constructor with clone
  RangeFromExpr (RangeFromExpr const &other);

  // Overload assignment operator to clone unique_ptr
  RangeFromExpr &operator= (RangeFromExpr const &other);

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

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

  Expr &get_from_expr () { return *from; }

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

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

// Range to (exclusive) expression HIR node object
// constructs a std::ops::RangeTo object
class RangeToExpr : public RangeExpr
{
  std::unique_ptr<Expr> to;

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

  // outer attributes not allowed
  RangeToExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> range_to,
	       location_t locus);

  // Copy constructor with clone
  RangeToExpr (RangeToExpr const &other);

  // Overload assignment operator to clone unique_ptr
  RangeToExpr &operator= (RangeToExpr const &other);

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

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

  Expr &get_to_expr () { return *to; }

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

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

// Full range expression HIR node object
// constructs a std::ops::RangeFull object
class RangeFullExpr : public RangeExpr
{
public:
  std::string as_string () const override;

  RangeFullExpr (Analysis::NodeMapping mappings, location_t locus);
  // outer attributes not allowed

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

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

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

// Range from (inclusive) and to (inclusive) expression HIR node object
// aka RangeInclusiveExpr; constructs a std::ops::RangeInclusive object
class RangeFromToInclExpr : public RangeExpr
{
  std::unique_ptr<Expr> from;
  std::unique_ptr<Expr> to;

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

  RangeFromToInclExpr (Analysis::NodeMapping mappings,
		       std::unique_ptr<Expr> range_from,
		       std::unique_ptr<Expr> range_to, location_t locus);
  // outer attributes not allowed

  // Copy constructor with clone
  RangeFromToInclExpr (RangeFromToInclExpr const &other);

  // Overload assignment operator to use clone
  RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other);

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

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

  Expr &get_from_expr () { return *from; }
  Expr &get_to_expr () { return *to; }

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

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

// Range to (inclusive) expression HIR node object
// aka RangeToInclusiveExpr; constructs a std::ops::RangeToInclusive object
class RangeToInclExpr : public RangeExpr
{
  std::unique_ptr<Expr> to;

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

  RangeToInclExpr (Analysis::NodeMapping mappings,
		   std::unique_ptr<Expr> range_to, location_t locus);
  // outer attributes not allowed

  // Copy constructor with clone
  RangeToInclExpr (RangeToInclExpr const &other);

  // Overload assignment operator to clone pointer
  RangeToInclExpr &operator= (RangeToInclExpr const &other);

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

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

  Expr &get_to_expr () { return *to; };

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

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

// Return expression HIR node representation
class ReturnExpr : public ExprWithoutBlock
{
public:
  std::unique_ptr<Expr> return_expr;

  location_t locus;

  std::string as_string () const override;

  /* Returns whether the object has an expression returned (i.e. not void return
   * type). */
  bool has_return_expr () const { return return_expr != nullptr; }

  // Constructor for ReturnExpr.
  ReturnExpr (Analysis::NodeMapping mappings, location_t locus,
	      std::unique_ptr<Expr> returned_expr = nullptr,
	      AST::AttrVec outer_attribs = AST::AttrVec ());

  // Copy constructor with clone
  ReturnExpr (ReturnExpr const &other);

  // Overloaded assignment operator to clone return_expr pointer
  ReturnExpr &operator= (ReturnExpr const &other);

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

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

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

  bool has_expr () { return return_expr != nullptr; }
  Expr &get_expr () { return *return_expr; }

  ExprType get_expression_type () const override final
  {
    return ExprType::Return;
  }

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

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

// An unsafe block HIR node
class UnsafeBlockExpr : public ExprWithBlock
{
  // Or just have it extend BlockExpr
  std::unique_ptr<BlockExpr> expr;
  location_t locus;

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

  UnsafeBlockExpr (Analysis::NodeMapping mappings,
		   std::unique_ptr<BlockExpr> block_expr,
		   AST::AttrVec outer_attribs, location_t locus);

  // Copy constructor with clone
  UnsafeBlockExpr (UnsafeBlockExpr const &other);

  // Overloaded assignment operator to clone
  UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other);

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

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

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

  BlockExpr &get_block_expr () { return *expr; }

  ExprType get_expression_type () const override final
  {
    return ExprType::UnsafeBlock;
  }

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

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

// Base loop expression HIR node - aka LoopExpr
class BaseLoopExpr : public ExprWithBlock
{
protected:
  tl::optional<LoopLabel> loop_label;
  std::unique_ptr<BlockExpr> loop_block;

private:
  location_t locus;

protected:
  // Constructor for BaseLoopExpr
  BaseLoopExpr (Analysis::NodeMapping mappings,
		std::unique_ptr<BlockExpr> loop_block, location_t locus,
		tl::optional<LoopLabel> loop_label,
		AST::AttrVec outer_attribs = AST::AttrVec ());

  // Copy constructor for BaseLoopExpr with clone
  BaseLoopExpr (BaseLoopExpr const &other);

  // Overloaded assignment operator to clone
  BaseLoopExpr &operator= (BaseLoopExpr const &other);

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

  ExprType get_expression_type () const final override
  {
    return ExprType::BaseLoop;
  }

public:
  bool has_loop_label () const { return loop_label.has_value (); }

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

  HIR::BlockExpr &get_loop_block () { return *loop_block; };

  LoopLabel &get_loop_label () { return loop_label.value (); }
  const LoopLabel &get_loop_label () const { return loop_label.value (); }
};

// 'Loop' expression (i.e. the infinite loop) HIR node
class LoopExpr : public BaseLoopExpr
{
public:
  std::string as_string () const override;

  // Constructor for LoopExpr
  LoopExpr (Analysis::NodeMapping mappings,
	    std::unique_ptr<BlockExpr> loop_block, location_t locus,
	    tl::optional<LoopLabel> loop_label,
	    AST::AttrVec outer_attribs = AST::AttrVec ());

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

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

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

// While loop expression HIR node (predicate loop)
class WhileLoopExpr : public BaseLoopExpr
{
  std::unique_ptr<Expr> condition;

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

  // Constructor for while loop with loop label
  WhileLoopExpr (Analysis::NodeMapping mappings,
		 std::unique_ptr<Expr> loop_condition,
		 std::unique_ptr<BlockExpr> loop_block, location_t locus,
		 tl::optional<LoopLabel> loop_label,
		 AST::AttrVec outer_attribs = AST::AttrVec ());

  // Copy constructor with clone
  WhileLoopExpr (WhileLoopExpr const &other);

  // Overloaded assignment operator to clone
  WhileLoopExpr &operator= (WhileLoopExpr const &other);

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

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

  Expr &get_predicate_expr () { return *condition; }

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

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

// While let loop expression HIR node (predicate pattern loop)
class WhileLetLoopExpr : public BaseLoopExpr
{
  // MatchArmPatterns patterns;
  std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
  std::unique_ptr<Expr> condition;

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

  // Constructor with a loop label
  WhileLetLoopExpr (Analysis::NodeMapping mappings,
		    std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
		    std::unique_ptr<Expr> condition,
		    std::unique_ptr<BlockExpr> loop_block, location_t locus,
		    tl::optional<LoopLabel> loop_label,
		    AST::AttrVec outer_attribs = AST::AttrVec ());

  // Copy constructor with clone
  WhileLetLoopExpr (WhileLetLoopExpr const &other);

  // Overloaded assignment operator to clone pointers
  WhileLetLoopExpr &operator= (WhileLetLoopExpr const &other);

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

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

  Expr &get_cond () { return *condition; }
  std::vector<std::unique_ptr<Pattern>> &get_patterns ()
  {
    return match_arm_patterns;
  }

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

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

// Base if expression with no "else" or "if let" HIR node
class IfExpr : public ExprWithBlock
{
  std::unique_ptr<Expr> condition;
  std::unique_ptr<BlockExpr> if_block;

  location_t locus;

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

  IfExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> condition,
	  std::unique_ptr<BlockExpr> if_block, location_t locus);
  // outer attributes are never allowed on IfExprs

  // Copy constructor with clone
  IfExpr (IfExpr const &other);

  // Overloaded assignment operator to clone expressions
  IfExpr &operator= (IfExpr const &other);

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

  // Unique pointer custom clone function
  std::unique_ptr<IfExpr> clone_if_expr () const
  {
    return std::unique_ptr<IfExpr> (clone_if_expr_impl ());
  }

  /* Note that multiple "else if"s are handled via nested HIRs rather than a
   * vector of else ifs - i.e. not like a switch statement. TODO - is this a
   * better approach? or does it not parse correctly and have downsides? */

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

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

  void vis_if_condition (HIRFullVisitor &vis) { condition->accept_vis (vis); }
  void vis_if_block (HIRFullVisitor &vis) { if_block->accept_vis (vis); }

  Expr &get_if_condition () { return *condition; }
  BlockExpr &get_if_block () { return *if_block; }

  ExprType get_expression_type () const final override { return ExprType::If; }

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

  // Base clone function but still concrete as concrete base class
  virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); }

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

// If expression with an ending "else" expression HIR node (trailing)
class IfExprConseqElse : public IfExpr
{
  std::unique_ptr<ExprWithBlock> else_block;

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

  IfExprConseqElse (Analysis::NodeMapping mappings,
		    std::unique_ptr<Expr> condition,
		    std::unique_ptr<BlockExpr> if_block,
		    std::unique_ptr<ExprWithBlock> else_block,
		    location_t locus);
  // again, outer attributes not allowed

  // Copy constructor with clone
  IfExprConseqElse (IfExprConseqElse const &other);

  // Overloaded assignment operator with cloning
  IfExprConseqElse &operator= (IfExprConseqElse const &other);

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

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

  void vis_else_block (HIRFullVisitor &vis) { else_block->accept_vis (vis); }

  ExprWithBlock &get_else_block () { return *else_block; }

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

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

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

// Match arm expression
struct MatchArm
{
private:
  AST::AttrVec outer_attrs;
  std::vector<std::unique_ptr<Pattern>> match_arm_patterns;
  std::unique_ptr<Expr> guard_expr;
  location_t locus;

public:
  // Returns whether the MatchArm has a match arm guard expression
  bool has_match_arm_guard () const { return guard_expr != nullptr; }

  // Constructor for match arm with a guard expression
  MatchArm (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
	    location_t locus, std::unique_ptr<Expr> guard_expr = nullptr,
	    AST::AttrVec outer_attrs = AST::AttrVec ());

  // Copy constructor with clone
  MatchArm (MatchArm const &other);

  ~MatchArm () = default;

  // Overload assignment operator to clone
  MatchArm &operator= (MatchArm const &other);

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

  // Returns whether match arm is in an error state.
  bool is_error () const { return match_arm_patterns.empty (); }

  // Creates a match arm in an error state.
  static MatchArm create_error ()
  {
    location_t locus = UNDEF_LOCATION;
    return MatchArm (std::vector<std::unique_ptr<Pattern>> (), locus);
  }

  std::string as_string () const;

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

  Expr &get_guard_expr () { return *guard_expr; }

  location_t get_locus () const { return locus; }

  AST::AttrVec &get_outer_attrs () { return outer_attrs; }
};

/* A "match case" - a correlated match arm and resulting expression. Not
 * abstract. */
struct MatchCase
{
private:
  Analysis::NodeMapping mappings;
  MatchArm arm;
  std::unique_ptr<Expr> expr;

public:
  MatchCase (Analysis::NodeMapping mappings, MatchArm arm,
	     std::unique_ptr<Expr> expr);

  MatchCase (const MatchCase &other);

  MatchCase &operator= (const MatchCase &other);

  MatchCase (MatchCase &&other) = default;
  MatchCase &operator= (MatchCase &&other) = default;

  ~MatchCase () = default;

  std::string as_string () const;

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

  MatchArm &get_arm () { return arm; }
  Expr &get_expr () { return *expr; }
};

// Match expression HIR node
class MatchExpr : public ExprWithBlock, public WithInnerAttrs
{
  std::unique_ptr<Expr> branch_value;
  std::vector<MatchCase> match_arms;
  location_t locus;

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

  bool has_match_arms () const { return !match_arms.empty (); }

  MatchExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> branch_value,
	     std::vector<MatchCase> match_arms, AST::AttrVec inner_attrs,
	     AST::AttrVec outer_attrs, location_t locus);

  // Copy constructor requires clone due to unique_ptr
  MatchExpr (MatchExpr const &other);

  // Overloaded assignment operator to clone due to unique_ptr
  MatchExpr &operator= (MatchExpr const &other);

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

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

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

  Expr &get_scrutinee_expr () { return *branch_value; }
  AST::AttrVec get_inner_attrs () const { return inner_attrs; }
  const std::vector<MatchCase> &get_match_cases () const { return match_arms; }
  std::vector<MatchCase> &get_match_cases () { return match_arms; }

  ExprType get_expression_type () const final override
  {
    return ExprType::Match;
  }

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

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

// Await expression HIR node (pseudo-member variable access)
class AwaitExpr : public ExprWithoutBlock
{
  std::unique_ptr<Expr> awaited_expr;
  location_t locus;

public:
  // TODO: ensure outer attributes are actually allowed
  AwaitExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> awaited_expr,
	     AST::AttrVec outer_attrs, location_t locus);

  // copy constructor with clone
  AwaitExpr (AwaitExpr const &other);

  // overloaded assignment operator with clone
  AwaitExpr &operator= (AwaitExpr const &other);

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

  std::string as_string () const override;

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

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

  Expr &get_awaited_expr () { return *awaited_expr; }

  ExprType get_expression_type () const final override
  {
    return ExprType::Await;
  }

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

// Async block expression HIR node (block expr that evaluates to a future)
class AsyncBlockExpr : public ExprWithBlock
{
  bool has_move;
  std::unique_ptr<BlockExpr> block_expr;
  location_t locus;

public:
  AsyncBlockExpr (Analysis::NodeMapping mappings,
		  std::unique_ptr<BlockExpr> block_expr, bool has_move,
		  AST::AttrVec outer_attrs, location_t locus);

  // copy constructor with clone
  AsyncBlockExpr (AsyncBlockExpr const &other);

  // overloaded assignment operator to clone
  AsyncBlockExpr &operator= (AsyncBlockExpr const &other);

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

  std::string as_string () const override;

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

  bool get_has_move () const { return has_move; }
  BlockExpr &get_block_expr () { return *block_expr; }

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

  ExprType get_expression_type () const final override
  {
    return ExprType::AsyncBlock;
  }

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

// this is a utility helper class for type-checking and code-generation
class OperatorExprMeta
{
public:
  OperatorExprMeta (HIR::CompoundAssignmentExpr &expr);

  OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr);

  OperatorExprMeta (HIR::NegationExpr &expr);

  OperatorExprMeta (HIR::DereferenceExpr &expr);

  OperatorExprMeta (HIR::ArrayIndexExpr &expr);

  OperatorExprMeta (HIR::ComparisonExpr &expr);

  OperatorExprMeta (const OperatorExprMeta &other)
    : node_mappings (other.node_mappings),
      lvalue_mappings (other.lvalue_mappings),
      rvalue_mappings (other.rvalue_mappings), locus (other.locus)
  {}

  OperatorExprMeta &operator= (const OperatorExprMeta &other)
  {
    node_mappings = other.node_mappings;
    lvalue_mappings = other.lvalue_mappings;
    rvalue_mappings = other.rvalue_mappings;
    locus = other.locus;

    return *this;
  }

  const Analysis::NodeMapping &get_mappings () const { return node_mappings; }

  const Analysis::NodeMapping &get_lvalue_mappings () const
  {
    return lvalue_mappings;
  }

  const Analysis::NodeMapping &get_rvalue_mappings () const
  {
    return rvalue_mappings;
  }

  bool has_rvalue_mappings () const
  {
    return rvalue_mappings.get_hirid () != UNKNOWN_HIRID;
  }

  location_t get_locus () const { return locus; }

private:
  Analysis::NodeMapping node_mappings;
  Analysis::NodeMapping lvalue_mappings;
  Analysis::NodeMapping rvalue_mappings;
  location_t locus;
};

class InlineAsmReg
{
  enum Kind
  {
    X86,
    Arm,
    AArch64,
    RiscV,
    Nvptx,
    PowerPC,
    Hexagon,
    Mips,
    S390x,
    SpirV,
    Wasm,
    Bpf,
    Avr,
    Msp430,
    // Placeholder for invalid register constraints for the current target
    Err,
  };

  // this placeholder is to be removed when the definations
  // of the above enums are made in a later PR/patch.
  std::string placeholder;
};

class InlineAsmRegClass
{
  enum Type
  {
    X86,
    Arm,
    AArch64,
    RiscV,
    Nvptx,
    PowerPC,
    Hexagon,
    Mips,
    S390x,
    SpirV,
    Wasm,
    Bpf,
    Avr,
    Msp430,
    // Placeholder for invalid register constraints for the current target
    Err,
  };

  // this placeholder is to be removed when the definations
  // of the above enums are made in a later PR/patch.
  std::string placeholder;
};

class InlineAsmOperand
{
public:
  struct In
  {
    tl::optional<struct AST::InlineAsmRegOrRegClass> reg;
    std::unique_ptr<Expr> expr;

    In (const tl::optional<struct AST::InlineAsmRegOrRegClass> &reg,
	std::unique_ptr<Expr> expr);

    In (const struct In &other);

    In operator= (const struct In &other);
  };

  struct Out
  {
    tl::optional<struct AST::InlineAsmRegOrRegClass> reg;
    bool late;
    std::unique_ptr<Expr> expr; // can be null

    Out (tl::optional<struct AST::InlineAsmRegOrRegClass> &reg, bool late,
	 std::unique_ptr<Expr> expr);

    Out (const struct Out &other);

    Out operator= (const struct Out &other);
  };

  struct InOut
  {
    tl::optional<struct AST::InlineAsmRegOrRegClass> reg;
    bool late;
    std::unique_ptr<Expr> expr; // this can't be null

    InOut (tl::optional<struct AST::InlineAsmRegOrRegClass> &reg, bool late,
	   std::unique_ptr<Expr> expr);

    InOut (const struct InOut &other);

    InOut operator= (const struct InOut &other);
  };

  struct SplitInOut
  {
    tl::optional<struct AST::InlineAsmRegOrRegClass> reg;
    bool late;
    std::unique_ptr<Expr> in_expr;
    std::unique_ptr<Expr> out_expr; // could be null

    SplitInOut (tl::optional<struct AST::InlineAsmRegOrRegClass> &reg,
		bool late, std::unique_ptr<Expr> in_expr,
		std::unique_ptr<Expr> out_expr);

    SplitInOut (const struct SplitInOut &other);

    SplitInOut operator= (const struct SplitInOut &other);
  };

  struct Const
  {
    AnonConst anon_const;
  };

  struct Sym
  {
    std::unique_ptr<Expr> expr;

    Sym (std::unique_ptr<Expr> expr);

    Sym (const struct Sym &other);

    Sym operator= (const struct Sym &other);
  };

  struct Label
  {
    std::string label_name;
    std::unique_ptr<Expr> expr;

    Label (tl::optional<std::string> label_name, std::unique_ptr<Expr> expr);

    Label (const struct Label &other);

    Label operator= (const struct Label &other);
  };

  using RegisterType = AST::InlineAsmOperand::RegisterType;

private:
  AST::InlineAsmOperand::RegisterType register_type;

  tl::optional<struct In> in;
  tl::optional<struct Out> out;
  tl::optional<struct InOut> in_out;
  tl::optional<struct SplitInOut> split_in_out;
  tl::optional<struct Const> cnst;
  tl::optional<struct Sym> sym;
  tl::optional<struct Label> label;

public:
  InlineAsmOperand (const InlineAsmOperand &other)
    : register_type (other.register_type), in (other.in), out (other.out),
      in_out (other.in_out), split_in_out (other.split_in_out),
      cnst (other.cnst), sym (other.sym)
  {}

  InlineAsmOperand (const struct In &reg)
    : register_type (RegisterType::In), in (reg)
  {}

  InlineAsmOperand (const struct Out &reg)
    : register_type (RegisterType::Out), out (reg)
  {}
  InlineAsmOperand (const struct InOut &reg)
    : register_type (RegisterType::InOut), in_out (reg)
  {}
  InlineAsmOperand (const struct SplitInOut &reg)
    : register_type (RegisterType::SplitInOut), split_in_out (reg)
  {}
  InlineAsmOperand (const struct Const &reg)
    : register_type (RegisterType::Const), cnst (reg)
  {}
  InlineAsmOperand (const struct Sym &reg)
    : register_type (RegisterType::Sym), sym (reg)
  {}
  InlineAsmOperand (const struct Label &reg)
    : register_type (RegisterType::Label), label (reg)
  {}

  RegisterType get_register_type () const { return register_type; }

  // Potentially unsafe without get_register_type() check
  const struct In &get_in () const { return in.value (); }
  const struct Out &get_out () const { return out.value (); }
  const struct InOut &get_in_out () const { return in_out.value (); }
  const struct SplitInOut &get_split_in_out () const
  {
    return split_in_out.value ();
  }
  const struct Const &get_const () const { return cnst.value (); }
  const struct Sym &get_sym () const { return sym.value (); }
  const struct Label &get_label () const { return label.value (); }

  struct In &get_in () { return in.value (); }
  struct Out &get_out () { return out.value (); }
  struct InOut &get_in_out () { return in_out.value (); }
  struct SplitInOut &get_split_in_out () { return split_in_out.value (); }
  struct Const &get_const () { return cnst.value (); }
  struct Sym &get_sym () { return sym.value (); }
  struct Label &get_label () { return label.value (); }
};

// Inline Assembly Node
class InlineAsm : public ExprWithoutBlock
{
  NodeId id;
  location_t locus;

public:
  bool is_global_asm;

  std::vector<AST::InlineAsmTemplatePiece> template_;
  std::vector<AST::TupleTemplateStr> template_strs;
  std::vector<HIR::InlineAsmOperand> operands;
  std::vector<AST::TupleClobber> clobber_abi;
  std::set<AST::InlineAsm::Option> options;

  std::vector<location_t> line_spans;

  void accept_vis (HIRExpressionVisitor &vis) override;

  void accept_vis (HIRFullVisitor &vis) override;

  std::string as_string () const override { return "InlineAsm HIR Node"; }

  location_t get_locus () const override { return locus; }

  InlineAsm *clone_expr_without_block_impl () const override
  {
    return new InlineAsm (*this);
  }

  ExprType get_expression_type () const final override
  {
    return ExprType::InlineAsm;
  }
  std::vector<AST::InlineAsmTemplatePiece> get_template_ ()
  {
    return template_;
  }

  std::vector<AST::TupleTemplateStr> get_template_strs ()
  {
    return template_strs;
  }

  std::vector<HIR::InlineAsmOperand> &get_operands () { return operands; }

  std::vector<AST::TupleClobber> get_clobber_abi () { return clobber_abi; }

  std::set<AST::InlineAsm::Option> get_options () { return options; }

  bool is_simple_asm ()
  {
    // INFO: A simple asm is an asm that does not have any operands
    return this->operands.size () == 0;
  }

  bool is_inline_asm ()
  {
    // INFO: An inline asm is asm!, which is the opposite of a global_asm()
    return !this->is_global_asm;
  }

  InlineAsm (location_t locus, bool is_global_asm,
	     std::vector<AST::InlineAsmTemplatePiece> template_,
	     std::vector<AST::TupleTemplateStr> template_strs,
	     std::vector<HIR::InlineAsmOperand> operands,
	     std::vector<AST::TupleClobber> clobber_abi,
	     std::set<AST::InlineAsm::Option> options,
	     Analysis::NodeMapping mappings,
	     AST::AttrVec outer_attribs = AST::AttrVec ());
};

class OffsetOf : public ExprWithoutBlock
{
public:
  OffsetOf (std::unique_ptr<Type> &&type, Identifier field,
	    Analysis::NodeMapping mappings, location_t loc)
    : ExprWithoutBlock (mappings), type (std::move (type)), field (field),
      loc (loc)
  {}

  OffsetOf (const OffsetOf &other)
    : ExprWithoutBlock (other), type (other.type->clone_type ()),
      field (other.field), loc (other.loc)
  {}

  OffsetOf &operator= (const OffsetOf &other);

  ExprWithoutBlock *clone_expr_without_block_impl () const override;
  std::string as_string () const override;

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

  ExprType get_expression_type () const override { return ExprType::OffsetOf; }

  location_t get_locus () const override { return loc; }

  Type &get_type () { return *type; }
  const Type &get_type () const { return *type; }
  const Identifier &get_field () const { return field; }

private:
  std::unique_ptr<Type> type;
  Identifier field;
  location_t loc;
};

struct LlvmOperand
{
  std::string constraint;
  std::unique_ptr<Expr> expr;

  LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr)
    : constraint (constraint), expr (std::move (expr))
  {}

  LlvmOperand (const LlvmOperand &other)
    : constraint (other.constraint), expr (other.expr->clone_expr ())
  {}
  LlvmOperand &operator= (const LlvmOperand &other)
  {
    constraint = other.constraint;
    expr = other.expr->clone_expr ();

    return *this;
  }
};

class LlvmInlineAsm : public ExprWithoutBlock
{
public:
  struct Options
  {
    bool is_volatile;
    bool align_stack;
    AST::LlvmInlineAsm::Dialect dialect;
  };

  location_t locus;
  AST::AttrVec outer_attrs;
  std::vector<LlvmOperand> inputs;
  std::vector<LlvmOperand> outputs;
  std::vector<AST::TupleTemplateStr> templates;
  std::vector<AST::TupleClobber> clobbers;
  Options options;

  LlvmInlineAsm (location_t locus, std::vector<LlvmOperand> inputs,
		 std::vector<LlvmOperand> outputs,
		 std::vector<AST::TupleTemplateStr> templates,
		 std::vector<AST::TupleClobber> clobbers, Options options,
		 AST::AttrVec outer_attrs, Analysis::NodeMapping mappings)
    : ExprWithoutBlock (mappings, std::move (outer_attrs)), locus (locus),
      inputs (std::move (inputs)), outputs (std::move (outputs)),
      templates (std::move (templates)), clobbers (std::move (clobbers)),
      options (options)
  {}

  AST::LlvmInlineAsm::Dialect get_dialect () { return options.dialect; }

  location_t get_locus () const override { return locus; }

  std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; }

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

  LlvmInlineAsm *clone_expr_without_block_impl () const override
  {
    return new LlvmInlineAsm (*this);
  }

  std::vector<AST::TupleTemplateStr> &get_templates () { return templates; }

  Expr::ExprType get_expression_type () const override
  {
    return Expr::ExprType::LlvmInlineAsm;
  }

  std::vector<AST::TupleClobber> get_clobbers () { return clobbers; }
};

} // namespace HIR
} // namespace Rust

#endif
