#ifndef RUST_AST_EXPR_H
#define RUST_AST_EXPR_H

#include "rust-ast.h"
#include "rust-common.h"
#include "rust-path.h"
#include "rust-macro.h"
#include "rust-operators.h"

namespace Rust {
namespace AST {
/* TODO: if GCC moves to C++17 or allows boost, replace some boolean
 * "has_whatever" pairs with
 * optional types (std::optional or boost::optional)? */

// Loop label expression AST node used with break and continue expressions
// TODO: inline?
class LoopLabel /*: public Visitable*/
{
  Lifetime label; // or type LIFETIME_OR_LABEL
  location_t locus;

  NodeId node_id;

public:
  std::string as_string () const;

  LoopLabel (Lifetime loop_label, location_t locus = UNDEF_LOCATION)
    : label (std::move (loop_label)), locus (locus),
      node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  // Returns whether the LoopLabel is in an error state.
  location_t get_locus () const { return locus; }

  Lifetime &get_lifetime () { return label; }

  NodeId get_node_id () const { return node_id; }
};

// AST node for an expression with an accompanying block - abstract
class ExprWithBlock : public Expr
{
protected:
  // 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 final override
  {
    return clone_expr_with_block_impl ();
  }

  bool is_expr_without_block () const final override { return false; };

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

// Literals? Or literal base?
class LiteralExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  Literal literal;
  location_t locus;

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

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

  LiteralExpr (std::string value_as_string, Literal::LitType type,
	       PrimitiveCoreType type_hint, std::vector<Attribute> outer_attrs,
	       location_t locus)
    : outer_attrs (std::move (outer_attrs)),
      literal (std::move (value_as_string), type, type_hint), locus (locus)
  {}

  LiteralExpr (Literal literal, std::vector<Attribute> outer_attrs,
	       location_t locus)
    : outer_attrs (std::move (outer_attrs)), literal (std::move (literal)),
      locus (locus)
  {}

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

  bool is_literal () const override final { return true; }

  Literal get_literal () const { return literal; }

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if literal is in error state, so base stripping on that.
  void mark_for_strip () override { literal = Literal::create_error (); }
  bool is_marked_for_strip () const override { return literal.is_error (); }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Literal; }

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

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

// Literal expression attribute body (non-macro attribute)
class AttrInputLiteral : public AttrInput
{
  LiteralExpr literal_expr;

public:
  AttrInputLiteral (LiteralExpr lit_expr) : literal_expr (std::move (lit_expr))
  {}

  std::string as_string () const override
  {
    return " = " + literal_expr.as_string ();
  }

  void accept_vis (ASTVisitor &vis) override;

  /* this can never be a cfg predicate - cfg and cfg_attr require a token-tree
   * cfg */
  bool check_cfg_predicate (const Session &) const override { return false; }

  bool is_meta_item () const override { return false; }

  LiteralExpr &get_literal () { return literal_expr; }

  AttrInputType get_attr_input_type () const final override
  {
    return AttrInput::AttrInputType::LITERAL;
  }

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

// Like an AttrInputLiteral, but stores a MacroInvocation
class AttrInputMacro : public AttrInput
{
  std::unique_ptr<MacroInvocation> macro;

public:
  AttrInputMacro (std::unique_ptr<MacroInvocation> macro)
    : macro (std::move (macro))
  {}

  AttrInputMacro (const AttrInputMacro &oth);

  AttrInputMacro (AttrInputMacro &&oth) : macro (std::move (oth.macro)) {}

  void operator= (const AttrInputMacro &oth);

  void operator= (AttrInputMacro &&oth) { macro = std::move (oth.macro); }

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  // assuming this can't be a cfg predicate
  bool check_cfg_predicate (const Session &) const override { return false; }

  // assuming this is like AttrInputLiteral
  bool is_meta_item () const override { return false; }

  std::unique_ptr<MacroInvocation> &get_macro () { return macro; }

  AttrInputType get_attr_input_type () const final override
  {
    return AttrInput::AttrInputType::MACRO;
  }

protected:
  AttrInputMacro *clone_attr_input_impl () const override
  {
    return new AttrInputMacro (*this);
  }
};

/* literal expr only meta item inner - TODO possibly replace with inheritance of
 * LiteralExpr itself? */
class MetaItemLitExpr : public MetaItemInner
{
  LiteralExpr lit_expr;

public:
  MetaItemLitExpr (LiteralExpr lit_expr) : lit_expr (std::move (lit_expr)) {}

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

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

  LiteralExpr get_literal () const { return lit_expr; }

  LiteralExpr &get_literal () { return lit_expr; }

  void accept_vis (ASTVisitor &vis) override;

  bool check_cfg_predicate (const Session &session) const override;

  MetaItemInner::Kind get_kind () override
  {
    return MetaItemInner::Kind::LitExpr;
  }

protected:
  // Use covariance to implement clone function as returning this type
  MetaItemLitExpr *clone_meta_item_inner_impl () const override
  {
    return new MetaItemLitExpr (*this);
  }
};

// more generic meta item "path = lit" form
class MetaItemPathLit : public MetaItem
{
  SimplePath path;
  LiteralExpr lit;

public:
  MetaItemPathLit (SimplePath path, LiteralExpr lit_expr)
    : path (std::move (path)), lit (std::move (lit_expr))
  {}

  SimplePath get_path () const { return path; }

  SimplePath &get_path () { return path; }

  LiteralExpr get_literal () const { return lit; }

  LiteralExpr &get_literal () { return lit; }

  std::string as_string () const override
  {
    return path.as_string () + " = " + lit.as_string ();
  }

  MetaItem::ItemKind get_item_kind () const override
  {
    return MetaItem::ItemKind::PathLit;
  }

  // There are two Locations in MetaItemPathLit (path and lit_expr),
  //  we have no idea use which of them, just simply return UNKNOWN_LOCATION
  //  now.
  // Maybe we will figure out when we really need the location in the future.
  location_t get_locus () const override { return UNKNOWN_LOCATION; }

  void accept_vis (ASTVisitor &vis) override;

  bool check_cfg_predicate (const Session &session) const override;
  /* TODO: return true if "ident" is defined and value of it is "lit", return
   * false otherwise */

  Attribute to_attribute () const override;

protected:
  // Use covariance to implement clone function as returning this type
  MetaItemPathLit *clone_meta_item_inner_impl () const override
  {
    return new MetaItemPathLit (*this);
  }
};

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

protected:
  /* Variables must be protected to allow derived classes to use them as first
   * class citizens */
  std::vector<Attribute> outer_attrs;
  std::unique_ptr<Expr> main_or_left_expr;

  // Constructor (only for initialisation of expr purposes)
  OperatorExpr (std::unique_ptr<Expr> main_or_left_expr,
		std::vector<Attribute> outer_attribs, location_t locus)
    : locus (locus), outer_attrs (std::move (outer_attribs)),
      main_or_left_expr (std::move (main_or_left_expr))
  {}

  // Copy constructor (only for initialisation of expr purposes)
  OperatorExpr (OperatorExpr const &other)
    : locus (other.locus), outer_attrs (other.outer_attrs)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.main_or_left_expr != nullptr)
      main_or_left_expr = other.main_or_left_expr->clone_expr ();
  }

  // Overload assignment operator to deep copy expr
  OperatorExpr &operator= (OperatorExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    locus = other.locus;
    outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.main_or_left_expr != nullptr)
      main_or_left_expr = other.main_or_left_expr->clone_expr ();
    else
      main_or_left_expr = nullptr;

    return *this;
  }

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

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

  // Invalid if expr is null, so base stripping on that.
  void mark_for_strip () override { main_or_left_expr = nullptr; }
  bool is_marked_for_strip () const override
  {
    return main_or_left_expr == nullptr;
  }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Operator; }
};

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

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

  BorrowExpr (std::unique_ptr<Expr> borrow_lvalue, Mutability mutability,
	      bool raw_borrow, bool is_double_borrow,
	      std::vector<Attribute> outer_attribs, location_t locus)
    : OperatorExpr (std::move (borrow_lvalue), std::move (outer_attribs),
		    locus),
      mutability (mutability), raw_borrow (raw_borrow),
      double_borrow (is_double_borrow)
  {}

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_borrowed_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  bool get_is_mut () const { return mutability == Mutability::Mut; }

  Mutability get_mutability () const { return mutability; }

  bool get_is_double_borrow () const { return double_borrow; }
  bool is_raw_borrow () const { return raw_borrow; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Borrow; }

protected:
  /* 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 (std::unique_ptr<Expr> deref_lvalue,
		   std::vector<Attribute> outer_attribs, location_t locus)
    : OperatorExpr (std::move (deref_lvalue), std::move (outer_attribs), locus)
  {}

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_dereferenced_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Dereference; }

protected:
  /* 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 (std::unique_ptr<Expr> potential_error_value,
			std::vector<Attribute> outer_attribs, location_t locus)
    : OperatorExpr (std::move (potential_error_value),
		    std::move (outer_attribs), locus)
  {}

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_propagating_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  Expr::Kind get_expr_kind () const override
  {
    return Expr::Kind::ErrorPropagation;
  }

protected:
  /* 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 (std::unique_ptr<Expr> negated_value, ExprType expr_kind,
		std::vector<Attribute> outer_attribs, location_t locus)
    : OperatorExpr (std::move (negated_value), std::move (outer_attribs),
		    locus),
      expr_type (expr_kind)
  {}

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_negated_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Negation; }

protected:
  /* 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 (std::unique_ptr<Expr> left_value,
			   std::unique_ptr<Expr> right_value,
			   ExprType expr_kind, location_t locus)
    : OperatorExpr (std::move (left_value), std::vector<Attribute> (), locus),
      expr_type (expr_kind), right_expr (std::move (right_value))
  {}
  // outer attributes not allowed

  // Copy constructor - probably required due to unique pointer
  ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr const &other)
    : OperatorExpr (other), expr_type (other.expr_type),
      right_expr (other.right_expr->clone_expr ())
  {}

  // Overload assignment operator
  ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr const &other)
  {
    OperatorExpr::operator= (other);
    // main_or_left_expr = other.main_or_left_expr->clone_expr();
    right_expr = other.right_expr->clone_expr ();
    expr_type = other.expr_type;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_left_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  std::unique_ptr<Expr> &get_left_expr_ptr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return main_or_left_expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_right_expr ()
  {
    rust_assert (right_expr != nullptr);
    return *right_expr;
  }

  std::unique_ptr<Expr> &get_right_expr_ptr ()
  {
    rust_assert (right_expr != nullptr);
    return right_expr;
  }

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

  Expr::Kind get_expr_kind () const override
  {
    return Expr::Kind::ArithmeticOrLogical;
  }

protected:
  /* 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 (std::unique_ptr<Expr> left_value,
		  std::unique_ptr<Expr> right_value, ExprType comparison_kind,
		  location_t locus)
    : OperatorExpr (std::move (left_value), std::vector<Attribute> (), locus),
      expr_type (comparison_kind), right_expr (std::move (right_value))
  {}
  // outer attributes not allowed

  // Copy constructor also calls OperatorExpr's protected constructor
  ComparisonExpr (ComparisonExpr const &other)
    : OperatorExpr (other), expr_type (other.expr_type),
      right_expr (other.right_expr->clone_expr ())
  {}

  // Overload assignment operator to deep copy
  ComparisonExpr &operator= (ComparisonExpr const &other)
  {
    OperatorExpr::operator= (other);
    // main_or_left_expr = other.main_or_left_expr->clone_expr();
    right_expr = other.right_expr->clone_expr ();
    expr_type = other.expr_type;
    // outer_attrs = other.outer_attrs;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_left_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  std::unique_ptr<Expr> &get_left_expr_ptr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return main_or_left_expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_right_expr ()
  {
    rust_assert (right_expr != nullptr);
    return *right_expr;
  }

  std::unique_ptr<Expr> &get_right_expr_ptr ()
  {
    rust_assert (right_expr != nullptr);
    return right_expr;
  }

  ExprType get_kind () { return expr_type; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Comparison; }

  /* 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_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 (std::unique_ptr<Expr> left_bool_expr,
		   std::unique_ptr<Expr> right_bool_expr, ExprType expr_kind,
		   location_t locus)
    : OperatorExpr (std::move (left_bool_expr), std::vector<Attribute> (),
		    locus),
      expr_type (expr_kind), right_expr (std::move (right_bool_expr))
  {}
  // outer attributes not allowed

  // Copy constructor also calls OperatorExpr's protected constructor
  LazyBooleanExpr (LazyBooleanExpr const &other)
    : OperatorExpr (other), expr_type (other.expr_type),
      right_expr (other.right_expr->clone_expr ())
  {}

  // Overload assignment operator to deep copy
  LazyBooleanExpr &operator= (LazyBooleanExpr const &other)
  {
    OperatorExpr::operator= (other);
    // main_or_left_expr = other.main_or_left_expr->clone_expr();
    right_expr = other.right_expr->clone_expr ();
    expr_type = other.expr_type;

    return *this;
  }

  // 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 (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_left_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  std::unique_ptr<Expr> &get_left_expr_ptr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return main_or_left_expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_right_expr ()
  {
    rust_assert (right_expr != nullptr);
    return *right_expr;
  }

  std::unique_ptr<Expr> &get_right_expr_ptr ()
  {
    rust_assert (right_expr != nullptr);
    return right_expr;
  }

  ExprType get_kind () { return expr_type; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::LazyBoolean; }

protected:
  /* 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" cast expression.
class TypeCastExpr : public OperatorExpr
{
  std::unique_ptr<TypeNoBounds> 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 (std::unique_ptr<Expr> expr_to_cast,
		std::unique_ptr<TypeNoBounds> type_to_cast_to, location_t locus)
    : OperatorExpr (std::move (expr_to_cast), std::vector<Attribute> (), locus),
      type_to_convert_to (std::move (type_to_cast_to))
  {}
  // outer attributes not allowed

  // Copy constructor also requires calling protected constructor
  TypeCastExpr (TypeCastExpr const &other)
    : OperatorExpr (other),
      type_to_convert_to (other.type_to_convert_to->clone_type_no_bounds ())
  {}

  // Overload assignment operator to deep copy
  TypeCastExpr &operator= (TypeCastExpr const &other)
  {
    OperatorExpr::operator= (other);
    // main_or_left_expr = other.main_or_left_expr->clone_expr();
    type_to_convert_to = other.type_to_convert_to->clone_type_no_bounds ();

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_casted_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  TypeNoBounds &get_type_to_cast_to ()
  {
    rust_assert (type_to_convert_to != nullptr);
    return *type_to_convert_to;
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::TypeCast; }

protected:
  /* 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 (std::unique_ptr<Expr> value_to_assign_to,
		  std::unique_ptr<Expr> value_to_assign,
		  std::vector<Attribute> outer_attribs, location_t locus)
    : OperatorExpr (std::move (value_to_assign_to), std::move (outer_attribs),
		    locus),
      right_expr (std::move (value_to_assign))
  {}
  // outer attributes not allowed

  // Call OperatorExpr constructor in copy constructor, as well as clone
  AssignmentExpr (AssignmentExpr const &other)
    : OperatorExpr (other), right_expr (other.right_expr->clone_expr ())
  {}

  // Overload assignment operator to clone unique_ptr right_expr
  AssignmentExpr &operator= (AssignmentExpr const &other)
  {
    OperatorExpr::operator= (other);
    // main_or_left_expr = other.main_or_left_expr->clone_expr();
    right_expr = other.right_expr->clone_expr ();
    // outer_attrs = other.outer_attrs;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

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

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_left_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  std::unique_ptr<Expr> &get_left_expr_ptr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return main_or_left_expr;
  }

  std::unique_ptr<Expr> &get_right_expr_ptr ()
  {
    rust_assert (right_expr != nullptr);
    return right_expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_right_expr ()
  {
    rust_assert (right_expr != nullptr);
    return *right_expr;
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Assignment; }

protected:
  /* 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);
  }
};

/* Binary infix compound assignment (arithmetic or logic then assignment)
 * expressions. */
class CompoundAssignmentExpr : public OperatorExpr
{
public:
  using ExprType = CompoundAssignmentOperator;

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 (std::unique_ptr<Expr> value_to_assign_to,
			  std::unique_ptr<Expr> value_to_assign,
			  ExprType expr_kind, location_t locus)
    : OperatorExpr (std::move (value_to_assign_to), std::vector<Attribute> (),
		    locus),
      expr_type (expr_kind), right_expr (std::move (value_to_assign))
  {}
  // outer attributes not allowed

  // Have clone in copy constructor
  CompoundAssignmentExpr (CompoundAssignmentExpr const &other)
    : OperatorExpr (other), expr_type (other.expr_type),
      right_expr (other.right_expr->clone_expr ())
  {}

  // Overload assignment operator to clone
  CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other)
  {
    OperatorExpr::operator= (other);
    // main_or_left_expr = other.main_or_left_expr->clone_expr();
    right_expr = other.right_expr->clone_expr ();
    expr_type = other.expr_type;
    // outer_attrs = other.outer_attrs;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_left_expr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return *main_or_left_expr;
  }

  std::unique_ptr<Expr> &get_left_expr_ptr ()
  {
    rust_assert (main_or_left_expr != nullptr);
    return main_or_left_expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_right_expr ()
  {
    rust_assert (right_expr != nullptr);
    return *right_expr;
  }

  std::unique_ptr<Expr> &get_right_expr_ptr ()
  {
    rust_assert (right_expr != nullptr);
    return right_expr;
  }

  Expr::Kind get_expr_kind () const override
  {
    return Expr::Kind::CompoundAssignment;
  }

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
{
  std::vector<Attribute> outer_attrs;
  std::vector<Attribute> inner_attrs;
  std::unique_ptr<Expr> expr_in_parens;
  location_t locus;

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

  const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
  std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  GroupedExpr (std::unique_ptr<Expr> parenthesised_expr,
	       std::vector<Attribute> inner_attribs,
	       std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)),
      inner_attrs (std::move (inner_attribs)),
      expr_in_parens (std::move (parenthesised_expr)), locus (locus)
  {}

  // Copy constructor includes clone for expr_in_parens
  GroupedExpr (GroupedExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      inner_attrs (other.inner_attrs), locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.expr_in_parens != nullptr)
      expr_in_parens = other.expr_in_parens->clone_expr ();
  }

  // Overloaded assignment operator to clone expr_in_parens
  GroupedExpr &operator= (GroupedExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    inner_attrs = other.inner_attrs;
    locus = other.locus;
    outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.expr_in_parens != nullptr)
      expr_in_parens = other.expr_in_parens->clone_expr ();
    else
      expr_in_parens = nullptr;

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if inner expr is null, so base stripping on that.
  void mark_for_strip () override { expr_in_parens = nullptr; }
  bool is_marked_for_strip () const override
  {
    return expr_in_parens == nullptr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_expr_in_parens ()
  {
    rust_assert (expr_in_parens != nullptr);
    return *expr_in_parens;
  }

  std::unique_ptr<Expr> &get_expr_in_parens_ptr ()
  {
    rust_assert (expr_in_parens != nullptr);
    return expr_in_parens;
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Grouped; }

protected:
  /* 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:
  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 (ASTVisitor &vis) = 0;

  NodeId get_node_id () const { return node_id; }

protected:
  ArrayElems () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}

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

  NodeId node_id;
};

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

public:
  ArrayElemsValues (std::vector<std::unique_ptr<Expr> > elems, location_t locus)
    : ArrayElems (), values (std::move (elems)), locus (locus)
  {}

  // copy constructor with vector clone
  ArrayElemsValues (ArrayElemsValues const &other)
  {
    values.reserve (other.values.size ());
    for (const auto &e : other.values)
      values.push_back (e->clone_expr ());
  }

  // overloaded assignment operator with vector clone
  ArrayElemsValues &operator= (ArrayElemsValues const &other)
  {
    values.reserve (other.values.size ());
    for (const auto &e : other.values)
      values.push_back (e->clone_expr ());

    return *this;
  }

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

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<std::unique_ptr<Expr> > &get_values () const
  {
    return values;
  }
  std::vector<std::unique_ptr<Expr> > &get_values () { return values; }

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

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;
  location_t locus;

public:
  // Constructor requires pointers for polymorphism
  ArrayElemsCopied (std::unique_ptr<Expr> copied_elem,
		    std::unique_ptr<Expr> copy_amount, location_t locus)
    : ArrayElems (), elem_to_copy (std::move (copied_elem)),
      num_copies (std::move (copy_amount)), locus (locus)
  {}

  // Copy constructor required due to unique_ptr - uses custom clone
  ArrayElemsCopied (ArrayElemsCopied const &other)
    : elem_to_copy (other.elem_to_copy->clone_expr ()),
      num_copies (other.num_copies->clone_expr ())
  {}

  // Overloaded assignment operator for deep copying
  ArrayElemsCopied &operator= (ArrayElemsCopied const &other)
  {
    elem_to_copy = other.elem_to_copy->clone_expr ();
    num_copies = other.num_copies->clone_expr ();

    return *this;
  }

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

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_elem_to_copy ()
  {
    rust_assert (elem_to_copy != nullptr);
    return *elem_to_copy;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_num_copies ()
  {
    rust_assert (num_copies != nullptr);
    return *num_copies;
  }

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

// Array definition-ish expression
class ArrayExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  std::vector<Attribute> inner_attrs;
  std::unique_ptr<ArrayElems> internal_elements;
  location_t locus;

  // TODO: find another way to store this to save memory?
  bool marked_for_strip = false;

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

  const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
  std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  // Constructor requires ArrayElems pointer
  ArrayExpr (std::unique_ptr<ArrayElems> array_elems,
	     std::vector<Attribute> inner_attribs,
	     std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)),
      inner_attrs (std::move (inner_attribs)),
      internal_elements (std::move (array_elems)), locus (locus)
  {
    rust_assert (internal_elements != nullptr);
  }

  // Copy constructor requires cloning ArrayElems for polymorphism to hold
  ArrayExpr (ArrayExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      inner_attrs (other.inner_attrs), locus (other.locus),
      marked_for_strip (other.marked_for_strip)
  {
    internal_elements = other.internal_elements->clone_array_elems ();
    rust_assert (internal_elements != nullptr);
  }

  // Overload assignment operator to clone internal_elements
  ArrayExpr &operator= (ArrayExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    inner_attrs = other.inner_attrs;
    locus = other.locus;
    marked_for_strip = other.marked_for_strip;
    outer_attrs = other.outer_attrs;

    internal_elements = other.internal_elements->clone_array_elems ();

    rust_assert (internal_elements != nullptr);
    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Can't think of any invalid invariants, so store boolean.
  void mark_for_strip () override { marked_for_strip = true; }
  bool is_marked_for_strip () const override { return marked_for_strip; }

  // TODO: is this better? Or is a "vis_block" better?
  std::unique_ptr<ArrayElems> &get_array_elems ()
  {
    rust_assert (internal_elements != nullptr);
    return internal_elements;
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Array; }

protected:
  /* 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);
  }
};

// Aka IndexExpr (also applies to slices)
/* Apparently a[b] is equivalent to *std::ops::Index::index(&a, b) or
 * *std::ops::Index::index_mut(&mut a, b) */
/* Also apparently deref operations on a will be repeatedly applied to find an
 * implementation */
class ArrayIndexExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  std::unique_ptr<Expr> array_expr;
  std::unique_ptr<Expr> index_expr;
  location_t locus;

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

  ArrayIndexExpr (std::unique_ptr<Expr> array_expr,
		  std::unique_ptr<Expr> array_index_expr,
		  std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)),
      array_expr (std::move (array_expr)),
      index_expr (std::move (array_index_expr)), locus (locus)
  {}

  // Copy constructor requires special cloning due to unique_ptr
  ArrayIndexExpr (ArrayIndexExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.array_expr != nullptr)
      array_expr = other.array_expr->clone_expr ();
    if (other.index_expr != nullptr)
      index_expr = other.index_expr->clone_expr ();
  }

  // Overload assignment operator to clone unique_ptrs
  ArrayIndexExpr &operator= (ArrayIndexExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    outer_attrs = other.outer_attrs;
    locus = other.locus;

    // guard to prevent null dereference (only required if error state)
    if (other.array_expr != nullptr)
      array_expr = other.array_expr->clone_expr ();
    else
      array_expr = nullptr;
    if (other.index_expr != nullptr)
      index_expr = other.index_expr->clone_expr ();
    else
      index_expr = nullptr;

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if either expr is null, so base stripping on that.
  void mark_for_strip () override
  {
    array_expr = nullptr;
    index_expr = nullptr;
  }
  bool is_marked_for_strip () const override
  {
    return array_expr == nullptr && index_expr == nullptr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_array_expr ()
  {
    rust_assert (array_expr != nullptr);
    return *array_expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_index_expr ()
  {
    rust_assert (index_expr != nullptr);
    return *index_expr;
  }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::ArrayIndex; }

protected:
  /* 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);
  }
};

// AST representation of a tuple
class TupleExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  std::vector<Attribute> inner_attrs;
  std::vector<std::unique_ptr<Expr> > tuple_elems;
  location_t locus;

  // TODO: find another way to store this to save memory?
  bool marked_for_strip = false;

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

  const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
  std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  TupleExpr (std::vector<std::unique_ptr<Expr> > tuple_elements,
	     std::vector<Attribute> inner_attribs,
	     std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)),
      inner_attrs (std::move (inner_attribs)),
      tuple_elems (std::move (tuple_elements)), locus (locus)
  {}

  // copy constructor with vector clone
  TupleExpr (TupleExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      inner_attrs (other.inner_attrs), locus (other.locus),
      marked_for_strip (other.marked_for_strip)
  {
    tuple_elems.reserve (other.tuple_elems.size ());
    for (const auto &e : other.tuple_elems)
      tuple_elems.push_back (e->clone_expr ());
  }

  // overloaded assignment operator to vector clone
  TupleExpr &operator= (TupleExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    outer_attrs = other.outer_attrs;
    inner_attrs = other.inner_attrs;
    locus = other.locus;
    marked_for_strip = other.marked_for_strip;

    tuple_elems.reserve (other.tuple_elems.size ());
    for (const auto &e : other.tuple_elems)
      tuple_elems.push_back (e->clone_expr ());

    return *this;
  }

  // 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 (ASTVisitor &vis) override;

  // Can't think of any invalid invariants, so store boolean.
  void mark_for_strip () override { marked_for_strip = true; }
  bool is_marked_for_strip () const override { return marked_for_strip; }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  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; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Tuple; }

protected:
  /* 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);
  }
};

// aka TupleIndexingExpr
// AST representation of a tuple indexing expression
class TupleIndexExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  std::unique_ptr<Expr> tuple_expr;
  // TupleIndex is a decimal int literal with no underscores or suffix
  TupleIndex tuple_index;

  location_t locus;

  // i.e. pair.0

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

  TupleIndex get_tuple_index () const { return tuple_index; }

  TupleIndexExpr (std::unique_ptr<Expr> tuple_expr, TupleIndex index,
		  std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)),
      tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus)
  {}

  // Copy constructor requires a clone for tuple_expr
  TupleIndexExpr (TupleIndexExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      tuple_index (other.tuple_index), locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.tuple_expr != nullptr)
      tuple_expr = other.tuple_expr->clone_expr ();
  }

  // Overload assignment operator in order to clone
  TupleIndexExpr &operator= (TupleIndexExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    tuple_index = other.tuple_index;
    locus = other.locus;
    outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.tuple_expr != nullptr)
      tuple_expr = other.tuple_expr->clone_expr ();
    else
      tuple_expr = nullptr;

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if tuple expr is null, so base stripping on that.
  void mark_for_strip () override { tuple_expr = nullptr; }
  bool is_marked_for_strip () const override { return tuple_expr == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_tuple_expr ()
  {
    rust_assert (tuple_expr != nullptr);
    return *tuple_expr;
  }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::TupleIndex; }

protected:
  /* 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 AST node (abstract)
class StructExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  PathInExpression struct_name;

protected:
  // Protected constructor to allow initialising struct_name
  StructExpr (PathInExpression struct_path,
	      std::vector<Attribute> outer_attribs)
    : outer_attrs (std::move (outer_attribs)),
      struct_name (std::move (struct_path))
  {}

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

  std::string as_string () const override;

  // Invalid if path is empty, so base stripping on that.
  void mark_for_strip () override
  {
    struct_name = PathInExpression::create_error ();
  }
  bool is_marked_for_strip () const override { return struct_name.is_error (); }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Struct; }
};

// Actual AST node of the struct creator (with no fields). Not abstract!
class StructExprStruct : public StructExpr
{
  std::vector<Attribute> inner_attrs;

  location_t locus;

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

  const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
  std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }

  // Constructor has to call protected constructor of base class
  StructExprStruct (PathInExpression struct_path,
		    std::vector<Attribute> inner_attribs,
		    std::vector<Attribute> outer_attribs, location_t locus)
    : StructExpr (std::move (struct_path), std::move (outer_attribs)),
      inner_attrs (std::move (inner_attribs)), locus (locus)
  {}

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

  void accept_vis (ASTVisitor &vis) override;

protected:
  /* 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);
  }
};

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

public:
  StructBase (std::unique_ptr<Expr> base_struct_ptr, location_t locus)
    : base_struct (std::move (base_struct_ptr)), locus (locus)
  {}

  // Copy constructor requires clone
  StructBase (StructBase const &other)
  {
    /* HACK: gets around base_struct pointer being null (e.g. if no struct base
     * exists) */
    if (other.base_struct != nullptr)
      base_struct = other.base_struct->clone_expr ();
  }

  // Destructor
  ~StructBase () = default;

  // Overload assignment operator to clone base_struct
  StructBase &operator= (StructBase const &other)
  {
    // prevent null pointer dereference
    if (other.base_struct != nullptr)
      base_struct = other.base_struct->clone_expr ();
    else
      base_struct = nullptr;

    return *this;
  }

  // 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, UNDEF_LOCATION); }

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

  std::string as_string () const;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_base_struct ()
  {
    rust_assert (base_struct != nullptr);
    return *base_struct;
  }
};

/* Base AST node for a single struct expression field (in struct instance
 * creation) - abstract */
class StructExprField
{
public:
  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 (ASTVisitor &vis) = 0;

  virtual location_t get_locus () const = 0;

  NodeId get_node_id () const { return node_id; }

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

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

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

  StructExprField () : node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  StructExprField (AST::AttrVec outer_attrs)
    : outer_attrs (std::move (outer_attrs)),
      node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  AST::AttrVec outer_attrs;
  NodeId node_id;
};

// Identifier-only variant of StructExprField AST node
class StructExprFieldIdentifier : public StructExprField
{
  Identifier field_name;
  location_t locus;

public:
  StructExprFieldIdentifier (Identifier field_identifier,
			     AST::AttrVec outer_attrs, location_t locus)
    : StructExprField (std::move (outer_attrs)),
      field_name (std::move (field_identifier)), locus (locus)
  {}

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

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

  void accept_vis (ASTVisitor &vis) override;

  Identifier get_field_name () const { return field_name; }

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 AST node for a single struct expression field with an assigned value -
 * abstract */
class StructExprFieldWithVal : public StructExprField
{
  std::unique_ptr<Expr> value;

protected:
  StructExprFieldWithVal (std::unique_ptr<Expr> field_value,
			  AST::AttrVec outer_attrs)
    : StructExprField (std::move (outer_attrs)), value (std::move (field_value))
  {}

  // Copy constructor requires clone
  StructExprFieldWithVal (StructExprFieldWithVal const &other)
    : StructExprField (other.get_outer_attrs ()),
      value (other.value->clone_expr ())
  {}

  // Overload assignment operator to clone unique_ptr
  StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other)
  {
    value = other.value->clone_expr ();
    outer_attrs = other.get_outer_attrs ();

    return *this;
  }

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

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

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_value ()
  {
    rust_assert (value != nullptr);
    return *value;
  }
};

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

public:
  StructExprFieldIdentifierValue (Identifier field_identifier,
				  std::unique_ptr<Expr> field_value,
				  AST::AttrVec outer_attrs, location_t locus)
    : StructExprFieldWithVal (std::move (field_value), std::move (outer_attrs)),
      field_name (std::move (field_identifier)), locus (locus)
  {}

  StructExprFieldIdentifierValue (Identifier field_identifier,
				  std::unique_ptr<Expr> field_value,
				  location_t locus)
    : StructExprFieldWithVal (std::move (field_value), {}),
      field_name (std::move (field_identifier)), locus (locus)
  {}

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

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

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

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 AST node
class StructExprFieldIndexValue : public StructExprFieldWithVal
{
  TupleIndex index;
  location_t locus;

public:
  StructExprFieldIndexValue (TupleIndex tuple_index,
			     std::unique_ptr<Expr> field_value,
			     AST::AttrVec outer_attrs, location_t locus)
    : StructExprFieldWithVal (std::move (field_value), std::move (outer_attrs)),
      index (tuple_index), locus (locus)
  {}

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  TupleIndex get_index () const { return index; }

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

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

// AST node of a struct creator with fields
class StructExprStructFields : public StructExprStruct
{
  // std::vector<StructExprField> fields;
  std::vector<std::unique_ptr<StructExprField> > fields;

  // bool has_struct_base;
  StructBase struct_base;

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

  bool has_struct_base () const { return !struct_base.is_invalid (); }

  // Constructor for StructExprStructFields when no struct base is used
  StructExprStructFields (
    PathInExpression struct_path,
    std::vector<std::unique_ptr<StructExprField> > expr_fields,
    location_t locus, StructBase base_struct = StructBase::error (),
    std::vector<Attribute> inner_attribs = std::vector<Attribute> (),
    std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
    : StructExprStruct (std::move (struct_path), std::move (inner_attribs),
			std::move (outer_attribs), locus),
      fields (std::move (expr_fields)), struct_base (std::move (base_struct))
  {}

  // copy constructor with vector clone
  StructExprStructFields (StructExprStructFields const &other)
    : StructExprStruct (other), struct_base (other.struct_base)
  {
    fields.reserve (other.fields.size ());
    for (const auto &e : other.fields)
      fields.push_back (e->clone_struct_expr_field ());
  }

  // overloaded assignment operator with vector clone
  StructExprStructFields &operator= (StructExprStructFields const &other)
  {
    StructExprStruct::operator= (other);
    struct_base = other.struct_base;

    fields.reserve (other.fields.size ());
    for (const auto &e : other.fields)
      fields.push_back (e->clone_struct_expr_field ());

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // TODO: this mutable getter seems really dodgy. Think up better way.
  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; }
  const StructBase &get_struct_base () const { return struct_base; }

protected:
  /* 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);
  }
};

// AST node of the functional update struct creator
/* TODO: remove and replace with StructExprStructFields, except with empty
 * vector of fields? */
class StructExprStructBase : public StructExprStruct
{
  StructBase struct_base;

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

  StructExprStructBase (PathInExpression struct_path, StructBase base_struct,
			std::vector<Attribute> inner_attribs,
			std::vector<Attribute> outer_attribs, location_t locus)
    : StructExprStruct (std::move (struct_path), std::move (inner_attribs),
			std::move (outer_attribs), locus),
      struct_base (std::move (base_struct))
  {}

  void accept_vis (ASTVisitor &vis) override;

  StructBase &get_struct_base () { return struct_base; }
  const StructBase &get_struct_base () const { return struct_base; }

protected:
  /* 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);
  }
};

// Forward decl for Function - used in CallExpr
class Function;

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

public:
  Function *fndeclRef;

  std::string as_string () const override;

  CallExpr (std::unique_ptr<Expr> function_expr,
	    std::vector<std::unique_ptr<Expr> > function_params,
	    std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)),
      function (std::move (function_expr)),
      params (std::move (function_params)), locus (locus)
  {}

  // copy constructor requires clone
  CallExpr (CallExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.function != nullptr)
      function = other.function->clone_expr ();

    params.reserve (other.params.size ());
    for (const auto &e : other.params)
      params.push_back (e->clone_expr ());
  }

  // Overload assignment operator to clone
  CallExpr &operator= (CallExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    locus = other.locus;
    outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.function != nullptr)
      function = other.function->clone_expr ();
    else
      function = nullptr;

    params.reserve (other.params.size ());
    for (const auto &e : other.params)
      params.push_back (e->clone_expr ());

    return *this;
  }

  // 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 (ASTVisitor &vis) override;

  // Invalid if function expr is null, so base stripping on that.
  void mark_for_strip () override { function = nullptr; }
  bool is_marked_for_strip () const override { return function == nullptr; }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<std::unique_ptr<Expr> > &get_params () const
  {
    return params;
  }
  std::vector<std::unique_ptr<Expr> > &get_params () { return params; }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_function_expr ()
  {
    rust_assert (function != nullptr);
    return *function;
  }

  std::unique_ptr<Expr> &get_function_expr_ptr () { return function; }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Call; }

protected:
  /* 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 AST node
class MethodCallExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  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 (std::unique_ptr<Expr> call_receiver,
		  PathExprSegment method_path,
		  std::vector<std::unique_ptr<Expr> > method_params,
		  std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)),
      receiver (std::move (call_receiver)),
      method_name (std::move (method_path)), params (std::move (method_params)),
      locus (locus)
  {}

  // copy constructor required due to cloning
  MethodCallExpr (MethodCallExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      method_name (other.method_name), locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.receiver != nullptr)
      receiver = other.receiver->clone_expr ();

    params.reserve (other.params.size ());
    for (const auto &e : other.params)
      params.push_back (e->clone_expr ());
  }

  // Overload assignment operator to clone receiver object
  MethodCallExpr &operator= (MethodCallExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    method_name = other.method_name;
    locus = other.locus;
    outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.receiver != nullptr)
      receiver = other.receiver->clone_expr ();
    else
      receiver = nullptr;

    params.reserve (other.params.size ());
    for (const auto &e : other.params)
      params.push_back (e->clone_expr ());

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if receiver expr is null, so base stripping on that.
  void mark_for_strip () override { receiver = nullptr; }
  bool is_marked_for_strip () const override { return receiver == nullptr; }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<std::unique_ptr<Expr> > &get_params () const
  {
    return params;
  }
  std::vector<std::unique_ptr<Expr> > &get_params () { return params; }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_receiver_expr ()
  {
    rust_assert (receiver != nullptr);
    return *receiver;
  }

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

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::MethodCall; }

protected:
  /* 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 AST node
class FieldAccessExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  std::unique_ptr<Expr> receiver;
  Identifier field;
  location_t locus;

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

  FieldAccessExpr (std::unique_ptr<Expr> field_access_receiver,
		   Identifier field_name, std::vector<Attribute> outer_attribs,
		   location_t locus)
    : outer_attrs (std::move (outer_attribs)),
      receiver (std::move (field_access_receiver)),
      field (std::move (field_name)), locus (locus)
  {}

  // Copy constructor required due to unique_ptr cloning
  FieldAccessExpr (FieldAccessExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      field (other.field), locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.receiver != nullptr)
      receiver = other.receiver->clone_expr ();
  }

  // Overload assignment operator to clone unique_ptr
  FieldAccessExpr &operator= (FieldAccessExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    field = other.field;
    locus = other.locus;
    outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.receiver != nullptr)
      receiver = other.receiver->clone_expr ();
    else
      receiver = nullptr;

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if receiver expr is null, so base stripping on that.
  void mark_for_strip () override { receiver = nullptr; }
  bool is_marked_for_strip () const override { return receiver == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_receiver_expr ()
  {
    rust_assert (receiver != nullptr);
    return *receiver;
  }

  Identifier get_field_name () const { return field; }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::FieldAccess; }

protected:
  /* 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<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; }

  bool has_outer_attrs () const { return !outer_attrs.empty (); }

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

  // Copy constructor required due to cloning as a result of unique_ptrs
  ClosureParam (ClosureParam const &other) : outer_attrs (other.outer_attrs)
  {
    // guard to protect from null pointer dereference
    if (other.pattern != nullptr)
      pattern = other.pattern->clone_pattern ();
    if (other.type != nullptr)
      type = other.type->clone_type ();
  }

  ~ClosureParam () = default;

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

    // guard to protect from null pointer dereference
    if (other.pattern != nullptr)
      pattern = other.pattern->clone_pattern ();
    else
      pattern = nullptr;
    if (other.type != nullptr)
      type = other.type->clone_type ();
    else
      type = nullptr;

    return *this;
  }

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

  // Returns whether closure parameter is in an error state.
  bool is_error () const { return pattern == nullptr; }

  // Creates an error state closure parameter.
  static ClosureParam create_error ()
  {
    return ClosureParam (nullptr, UNDEF_LOCATION);
  }

  std::string as_string () const;

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

  Pattern &get_pattern ()
  {
    rust_assert (pattern != nullptr);
    return *pattern;
  }

  Type &get_type ()
  {
    rust_assert (has_type_given ());
    return *type;
  }

  std::unique_ptr<Type> &get_type_ptr ()
  {
    rust_assert (has_type_given ());
    return type;
  }

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

// Base closure definition expression AST node - abstract
class ClosureExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  bool has_move;
  std::vector<ClosureParam> params; // may be empty
  location_t locus;

protected:
  ClosureExpr (std::vector<ClosureParam> closure_params, bool has_move,
	       std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)), has_move (has_move),
      params (std::move (closure_params)), locus (locus)
  {}

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

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

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<ClosureParam> &get_params () const { return params; }
  std::vector<ClosureParam> &get_params () { return params; }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  bool get_has_move () const { return has_move; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; }
};

// Represents a non-type-specified closure expression AST node
class ClosureExprInner : public ClosureExpr
{
  std::unique_ptr<Expr> closure_inner;

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

  // Constructor for a ClosureExprInner
  ClosureExprInner (std::unique_ptr<Expr> closure_inner_expr,
		    std::vector<ClosureParam> closure_params, location_t locus,
		    bool is_move = false,
		    std::vector<Attribute> outer_attribs
		    = std::vector<Attribute> ())
    : ClosureExpr (std::move (closure_params), is_move,
		   std::move (outer_attribs), locus),
      closure_inner (std::move (closure_inner_expr))
  {}

  // Copy constructor must be defined to allow copying via cloning of unique_ptr
  ClosureExprInner (ClosureExprInner const &other) : ClosureExpr (other)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.closure_inner != nullptr)
      closure_inner = other.closure_inner->clone_expr ();
  }

  // Overload assignment operator to clone closure_inner
  ClosureExprInner &operator= (ClosureExprInner const &other)
  {
    ClosureExpr::operator= (other);
    // params = other.params;
    // has_move = other.has_move;
    // outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.closure_inner != nullptr)
      closure_inner = other.closure_inner->clone_expr ();
    else
      closure_inner = nullptr;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if inner expr is null, so base stripping on that.
  void mark_for_strip () override { closure_inner = nullptr; }
  bool is_marked_for_strip () const override
  {
    return closure_inner == nullptr;
  }

  Expr &get_definition_expr ()
  {
    rust_assert (closure_inner != nullptr);
    return *closure_inner;
  }

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

// A block AST node
class BlockExpr : public ExprWithBlock
{
  std::vector<Attribute> outer_attrs;
  std::vector<Attribute> inner_attrs;
  std::vector<std::unique_ptr<Stmt> > statements;
  std::unique_ptr<Expr> expr;
  tl::optional<LoopLabel> label;
  location_t start_locus;
  location_t end_locus;
  bool marked_for_strip = false;

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

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

  // Returns whether the block contains a final expression.
  bool has_tail_expr () const { return expr != nullptr; }

  BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements,
	     std::unique_ptr<Expr> block_expr,
	     std::vector<Attribute> inner_attribs,
	     std::vector<Attribute> outer_attribs,
	     tl::optional<LoopLabel> label, location_t start_locus,
	     location_t end_locus)
    : outer_attrs (std::move (outer_attribs)),
      inner_attrs (std::move (inner_attribs)),
      statements (std::move (block_statements)), expr (std::move (block_expr)),
      label (std::move (label)), start_locus (start_locus),
      end_locus (end_locus)
  {}

  // Copy constructor with clone
  BlockExpr (BlockExpr const &other)
    : ExprWithBlock (other), outer_attrs (other.outer_attrs),
      inner_attrs (other.inner_attrs), label (other.label),
      start_locus (other.start_locus), end_locus (other.end_locus),
      marked_for_strip (other.marked_for_strip)
  {
    // guard to protect from null pointer dereference
    if (other.expr != nullptr)
      expr = other.expr->clone_expr ();

    statements.reserve (other.statements.size ());
    for (const auto &e : other.statements)
      statements.push_back (e->clone_stmt ());
  }

  // Overloaded assignment operator to clone pointer
  BlockExpr &operator= (BlockExpr const &other)
  {
    ExprWithBlock::operator= (other);
    inner_attrs = other.inner_attrs;
    start_locus = other.start_locus;
    end_locus = other.end_locus;
    marked_for_strip = other.marked_for_strip;
    outer_attrs = other.outer_attrs;

    // guard to protect from null pointer dereference
    if (other.expr != nullptr)
      expr = other.expr->clone_expr ();
    else
      expr = nullptr;

    statements.reserve (other.statements.size ());
    for (const auto &e : other.statements)
      statements.push_back (e->clone_stmt ());

    return *this;
  }

  // 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 (ASTVisitor &vis) override;

  // Can be completely empty, so have to have a separate flag.
  void mark_for_strip () override { marked_for_strip = true; }
  bool is_marked_for_strip () const override { return marked_for_strip; }

  size_t num_statements () const { return statements.size (); }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
  std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }

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

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_tail_expr ()
  {
    rust_assert (has_tail_expr ());
    return *expr;
  }

  std::unique_ptr<Expr> &get_tail_expr_ptr ()
  {
    rust_assert (has_tail_expr ());
    return expr;
  }

  std::unique_ptr<Expr> take_tail_expr ()
  {
    rust_assert (has_tail_expr ());
    return std::move (expr);
  }

  void set_tail_expr (std::unique_ptr<Expr> expr)
  {
    this->expr = std::move (expr);
  }

  // Removes the tail expression from the block.
  void strip_tail_expr () { expr = nullptr; }
  // Normalizes a trailing statement without a semicolon to a tail expression.
  void normalize_tail_expr ();

  void try_convert_last_stmt ();

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

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

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Block; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  BlockExpr *clone_expr_with_block_impl () const final 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);
  }
};

// Represents a type-specified closure expression AST node
class ClosureExprInnerTyped : public ClosureExpr
{
  // TODO: spec says typenobounds
  std::unique_ptr<Type> return_type;
  std::unique_ptr<BlockExpr>
    expr; // only used because may be polymorphic in future

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

  // Constructor potentially with a move
  ClosureExprInnerTyped (std::unique_ptr<Type> closure_return_type,
			 std::unique_ptr<BlockExpr> closure_expr,
			 std::vector<ClosureParam> closure_params,
			 location_t locus, bool is_move = false,
			 std::vector<Attribute> outer_attribs
			 = std::vector<Attribute> ())
    : ClosureExpr (std::move (closure_params), is_move,
		   std::move (outer_attribs), locus),
      return_type (std::move (closure_return_type)),
      expr (std::move (closure_expr))
  {}

  // Copy constructor requires cloning
  ClosureExprInnerTyped (ClosureExprInnerTyped const &other)
    : ClosureExpr (other)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.expr != nullptr)
      expr = other.expr->clone_block_expr ();
    if (other.return_type != nullptr)
      return_type = other.return_type->clone_type ();
  }

  // Overload assignment operator to clone unique_ptrs
  ClosureExprInnerTyped &operator= (ClosureExprInnerTyped const &other)
  {
    ClosureExpr::operator= (other);
    // params = other.params;
    // has_move = other.has_move;
    // outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.expr != nullptr)
      expr = other.expr->clone_block_expr ();
    else
      expr = nullptr;
    if (other.return_type != nullptr)
      return_type = other.return_type->clone_type ();
    else
      return_type = nullptr;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  /* Invalid if inner expr is null, so base stripping on that. Technically,
   * type should also not be null. */
  void mark_for_strip () override { expr = nullptr; }
  bool is_marked_for_strip () const override { return expr == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  BlockExpr &get_definition_block ()
  {
    rust_assert (expr != nullptr);
    return *expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Type &get_return_type ()
  {
    rust_assert (return_type != nullptr);
    return *return_type;
  }

  std::unique_ptr<Type> &get_return_type_ptr ()
  {
    rust_assert (return_type != nullptr);
    return return_type;
  }

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

// AST node representing continue expression within loops
class ContinueExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  tl::optional<Lifetime> label;
  location_t locus;

  // TODO: find another way to store this to save memory?
  bool marked_for_strip = false;

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 (tl::optional<Lifetime> label,
		std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)), label (std::move (label)),
      locus (locus)
  {}

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

  void accept_vis (ASTVisitor &vis) override;

  // Can't think of any invalid invariants, so store boolean.
  void mark_for_strip () override { marked_for_strip = true; }
  bool is_marked_for_strip () const override { return marked_for_strip; }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

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

  tl::optional<Lifetime> &get_label () { return label; }
  const tl::optional<Lifetime> &get_label () const { return label; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Continue; }

protected:
  /* 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);
  }
};
// TODO: merge "break" and "continue"? Or even merge in "return"?

// AST node representing break expression within loops
class BreakExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  tl::optional<LoopLabel> label;
  std::unique_ptr<Expr> break_expr;
  location_t locus;

  // TODO: find another way to store this to save memory?
  bool marked_for_strip = false;

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 (tl::optional<LoopLabel> break_label,
	     std::unique_ptr<Expr> expr_in_break,
	     std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)), label (std::move (break_label)),
      break_expr (std::move (expr_in_break)), locus (locus)
  {}

  // Copy constructor defined to use clone for unique pointer
  BreakExpr (BreakExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      label (other.label), locus (other.locus),
      marked_for_strip (other.marked_for_strip)
  {
    // guard to protect from null pointer dereference
    if (other.break_expr != nullptr)
      break_expr = other.break_expr->clone_expr ();
  }

  // Overload assignment operator to clone unique pointer
  BreakExpr &operator= (BreakExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    label = other.label;
    locus = other.locus;
    marked_for_strip = other.marked_for_strip;
    outer_attrs = other.outer_attrs;

    // guard to protect from null pointer dereference
    if (other.break_expr != nullptr)
      break_expr = other.break_expr->clone_expr ();
    else
      break_expr = nullptr;

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Can't think of any invalid invariants, so store boolean.
  void mark_for_strip () override { marked_for_strip = true; }
  bool is_marked_for_strip () const override { return marked_for_strip; }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_break_expr ()
  {
    rust_assert (has_break_expr ());
    return *break_expr;
  }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  LoopLabel &get_label_unchecked () { return label.value (); }
  const LoopLabel &get_label_unchecked () const { return label.value (); }

  tl::optional<LoopLabel> &get_label () { return label; }
  const tl::optional<LoopLabel> &get_label () const { return label; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Break; }

protected:
  /* 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 AST node object - abstract
class RangeExpr : public ExprWithoutBlock
{
  location_t locus;

  // Some visitors still check for attributes on RangeExprs, and they will need
  // to be supported in the future - so keep that for now
  std::vector<Attribute> empty_attributes = {};

protected:
  // outer attributes not allowed before range expressions
  RangeExpr (location_t locus) : locus (locus) {}

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

  std::vector<Attribute> &get_outer_attrs () override final
  {
    return empty_attributes;
  }

  // should never be called - error if called
  void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override {}

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Range; }
};

// Range from (inclusive) and to (exclusive) expression AST 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 (std::unique_ptr<Expr> range_from,
		   std::unique_ptr<Expr> range_to, location_t locus)
    : RangeExpr (locus), from (std::move (range_from)),
      to (std::move (range_to))
  {}

  // Copy constructor with cloning
  RangeFromToExpr (RangeFromToExpr const &other) : RangeExpr (other)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.from != nullptr)
      from = other.from->clone_expr ();
    if (other.to != nullptr)
      to = other.to->clone_expr ();
  }

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

    // guard to prevent null dereference (only required if error state)
    if (other.from != nullptr)
      from = other.from->clone_expr ();
    else
      from = nullptr;
    if (other.to != nullptr)
      to = other.to->clone_expr ();
    else
      to = nullptr;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if either expr is null, so base stripping on that.
  void mark_for_strip () override
  {
    from = nullptr;
    to = nullptr;
  }
  bool is_marked_for_strip () const override
  {
    return from == nullptr && to == nullptr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_from_expr ()
  {
    rust_assert (from != nullptr);
    return *from;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_to_expr ()
  {
    rust_assert (to != nullptr);
    return *to;
  }

protected:
  /* 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 AST 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 (std::unique_ptr<Expr> range_from, location_t locus)
    : RangeExpr (locus), from (std::move (range_from))
  {}

  // Copy constructor with clone
  RangeFromExpr (RangeFromExpr const &other) : RangeExpr (other)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.from != nullptr)
      from = other.from->clone_expr ();
  }

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

    // guard to prevent null dereference (only required if error state)
    if (other.from != nullptr)
      from = other.from->clone_expr ();
    else
      from = nullptr;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if expr is null, so base stripping on that.
  void mark_for_strip () override { from = nullptr; }
  bool is_marked_for_strip () const override { return from == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_from_expr ()
  {
    rust_assert (from != nullptr);
    return *from;
  }

protected:
  /* 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 AST 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 (std::unique_ptr<Expr> range_to, location_t locus)
    : RangeExpr (locus), to (std::move (range_to))
  {}

  // Copy constructor with clone
  RangeToExpr (RangeToExpr const &other) : RangeExpr (other)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.to != nullptr)
      to = other.to->clone_expr ();
  }

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

    // guard to prevent null dereference (only required if error state)
    if (other.to != nullptr)
      to = other.to->clone_expr ();
    else
      to = nullptr;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if expr is null, so base stripping on that.
  void mark_for_strip () override { to = nullptr; }
  bool is_marked_for_strip () const override { return to == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_to_expr ()
  {
    rust_assert (to != nullptr);
    return *to;
  }

protected:
  /* 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 AST node object
// constructs a std::ops::RangeFull object
class RangeFullExpr : public RangeExpr
{
  // TODO: find another way to store this to save memory?
  bool marked_for_strip = false;

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

  RangeFullExpr (location_t locus) : RangeExpr (locus) {}
  // outer attributes not allowed

  void accept_vis (ASTVisitor &vis) override;

  // Can't think of any invalid invariants, so store boolean.
  void mark_for_strip () override { marked_for_strip = true; }
  bool is_marked_for_strip () const override { return marked_for_strip; }

protected:
  /* 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 AST 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 (std::unique_ptr<Expr> range_from,
		       std::unique_ptr<Expr> range_to, location_t locus)
    : RangeExpr (locus), from (std::move (range_from)),
      to (std::move (range_to))
  {}
  // outer attributes not allowed

  // Copy constructor with clone
  RangeFromToInclExpr (RangeFromToInclExpr const &other) : RangeExpr (other)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.from != nullptr)
      from = other.from->clone_expr ();
    if (other.to != nullptr)
      to = other.to->clone_expr ();
  }

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

    // guard to prevent null dereference (only required if error state)
    if (other.from != nullptr)
      from = other.from->clone_expr ();
    else
      from = nullptr;
    if (other.to != nullptr)
      to = other.to->clone_expr ();
    else
      to = nullptr;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if either expr is null, so base stripping on that.
  void mark_for_strip () override
  {
    from = nullptr;
    to = nullptr;
  }
  bool is_marked_for_strip () const override
  {
    return from == nullptr && to == nullptr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_from_expr ()
  {
    rust_assert (from != nullptr);
    return *from;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_to_expr ()
  {
    rust_assert (to != nullptr);
    return *to;
  }

protected:
  /* 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 AST 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 (std::unique_ptr<Expr> range_to, location_t locus)
    : RangeExpr (locus), to (std::move (range_to))
  {}
  // outer attributes not allowed

  // Copy constructor with clone
  RangeToInclExpr (RangeToInclExpr const &other) : RangeExpr (other)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.to != nullptr)
      to = other.to->clone_expr ();
  }

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

    // guard to prevent null dereference (only required if error state)
    if (other.to != nullptr)
      to = other.to->clone_expr ();
    else
      to = nullptr;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if expr is null, so base stripping on that.
  void mark_for_strip () override { to = nullptr; }
  bool is_marked_for_strip () const override { return to == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_to_expr ()
  {
    rust_assert (to != nullptr);
    return *to;
  }

protected:
  /* 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);
  }
};

class BoxExpr : public ExprWithoutBlock
{
  std::unique_ptr<Expr> expr;
  std::vector<Attribute> outer_attrs;
  location_t locus;

public:
  BoxExpr (std::unique_ptr<Expr> expr, std::vector<Attribute> outer_attrs,
	   location_t locus)
    : expr (std::move (expr)), outer_attrs (outer_attrs), locus (locus)
  {}

  // Copy constructor with clone
  BoxExpr (BoxExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      locus (other.locus)
  {
    // guard to protect from null pointer dereference
    if (other.expr != nullptr)
      expr = other.expr->clone_expr ();
  }

  BoxExpr &operator= (BoxExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    locus = other.locus;
    outer_attrs = other.outer_attrs;

    // guard to protect from null pointer dereference
    if (other.expr != nullptr)
      expr = other.expr->clone_expr ();
    else
      expr = nullptr;

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  void mark_for_strip () override { expr = nullptr; }
  bool is_marked_for_strip () const override { return expr == nullptr; }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  std::string as_string () const override;

  Expr &get_boxed_expr ()
  {
    rust_assert (expr != nullptr);
    return *expr;
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Box; }

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

// Return expression AST node representation
class ReturnExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  std::unique_ptr<Expr> return_expr;
  location_t locus;

  // TODO: find another way to store this to save memory?
  bool marked_for_strip = false;

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

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

  // Constructor for ReturnExpr.
  ReturnExpr (std::unique_ptr<Expr> returned_expr,
	      std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)),
      return_expr (std::move (returned_expr)), locus (locus)
  {}

  // Copy constructor with clone
  ReturnExpr (ReturnExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      locus (other.locus), marked_for_strip (other.marked_for_strip)
  {
    // guard to protect from null pointer dereference
    if (other.return_expr != nullptr)
      return_expr = other.return_expr->clone_expr ();
  }

  // Overloaded assignment operator to clone return_expr pointer
  ReturnExpr &operator= (ReturnExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    locus = other.locus;
    marked_for_strip = other.marked_for_strip;
    outer_attrs = other.outer_attrs;

    // guard to protect from null pointer dereference
    if (other.return_expr != nullptr)
      return_expr = other.return_expr->clone_expr ();
    else
      return_expr = nullptr;

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Can't think of any invalid invariants, so store boolean.
  void mark_for_strip () override { marked_for_strip = true; }
  bool is_marked_for_strip () const override { return marked_for_strip; }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_returned_expr ()
  {
    rust_assert (return_expr != nullptr);
    return *return_expr;
  }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Return; }

protected:
  /* 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);
  }
};

// Forward decl - defined in rust-macro.h
class MacroInvocation;

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

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

  UnsafeBlockExpr (std::unique_ptr<BlockExpr> block_expr,
		   std::vector<Attribute> outer_attribs, location_t locus)
    : outer_attrs (std::move (outer_attribs)), expr (std::move (block_expr)),
      locus (locus)
  {}

  // Copy constructor with clone
  UnsafeBlockExpr (UnsafeBlockExpr const &other)
    : ExprWithBlock (other), outer_attrs (other.outer_attrs),
      locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.expr != nullptr)
      expr = other.expr->clone_block_expr ();
  }

  // Overloaded assignment operator to clone
  UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other)
  {
    ExprWithBlock::operator= (other);
    locus = other.locus;
    outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.expr != nullptr)
      expr = other.expr->clone_block_expr ();
    else
      expr = nullptr;

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if block is null, so base stripping on that.
  void mark_for_strip () override { expr = nullptr; }
  bool is_marked_for_strip () const override { return expr == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  BlockExpr &get_block_expr ()
  {
    rust_assert (expr != nullptr);
    return *expr;
  }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::UnsafeBlock; }

protected:
  /* 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 AST node - aka LoopExpr
class BaseLoopExpr : public ExprWithBlock
{
protected:
  // protected to allow subclasses better use of them
  std::vector<Attribute> outer_attrs;
  tl::optional<LoopLabel> loop_label;
  std::unique_ptr<BlockExpr> loop_block;

private:
  location_t locus;

protected:
  // Constructor for BaseLoopExpr
  BaseLoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus,
		tl::optional<LoopLabel> loop_label = tl::nullopt,
		std::vector<Attribute> outer_attribs
		= std::vector<Attribute> ())
    : outer_attrs (std::move (outer_attribs)),
      loop_label (std::move (loop_label)), loop_block (std::move (loop_block)),
      locus (locus)
  {}

  // Copy constructor for BaseLoopExpr with clone
  BaseLoopExpr (BaseLoopExpr const &other)
    : ExprWithBlock (other), outer_attrs (other.outer_attrs),
      loop_label (other.loop_label), locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.loop_block != nullptr)
      loop_block = other.loop_block->clone_block_expr ();
  }

  // Overloaded assignment operator to clone
  BaseLoopExpr &operator= (BaseLoopExpr const &other)
  {
    ExprWithBlock::operator= (other);
    loop_label = other.loop_label;
    locus = other.locus;
    outer_attrs = other.outer_attrs;

    // guard to prevent null dereference (only required if error state)
    if (other.loop_block != nullptr)
      loop_block = other.loop_block->clone_block_expr ();
    else
      loop_block = nullptr;

    return *this;
  }

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

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

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

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

  // Invalid if loop block is null, so base stripping on that.
  void mark_for_strip () override { loop_block = nullptr; }
  bool is_marked_for_strip () const override { return loop_block == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  BlockExpr &get_loop_block ()
  {
    rust_assert (loop_block != nullptr);
    return *loop_block;
  }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Loop; }

  enum class Kind
  {
    Loop,
    While,
    WhileLet,
    For
  };

  virtual Kind get_loop_kind () const = 0;
};

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

  // Constructor for LoopExpr
  LoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus,
	    tl::optional<LoopLabel> loop_label = tl::nullopt,
	    std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
    : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
		    std::move (outer_attribs))
  {}

  void accept_vis (ASTVisitor &vis) override;

  BaseLoopExpr::Kind get_loop_kind () const override
  {
    return BaseLoopExpr::Kind::Loop;
  }

protected:
  /* 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 AST 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 (std::unique_ptr<Expr> loop_condition,
		 std::unique_ptr<BlockExpr> loop_block, location_t locus,
		 tl::optional<LoopLabel> loop_label = tl::nullopt,
		 std::vector<Attribute> outer_attribs
		 = std::vector<Attribute> ())
    : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
		    std::move (outer_attribs)),
      condition (std::move (loop_condition))
  {}

  // Copy constructor with clone
  WhileLoopExpr (WhileLoopExpr const &other)
    : BaseLoopExpr (other), condition (other.condition->clone_expr ())
  {}

  // Overloaded assignment operator to clone
  WhileLoopExpr &operator= (WhileLoopExpr const &other)
  {
    BaseLoopExpr::operator= (other);
    condition = other.condition->clone_expr ();
    // loop_block = other.loop_block->clone_block_expr();
    // loop_label = other.loop_label;
    // outer_attrs = other.outer_attrs;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_predicate_expr ()
  {
    rust_assert (condition != nullptr);
    return *condition;
  }

  BaseLoopExpr::Kind get_loop_kind () const override
  {
    return BaseLoopExpr::Kind::While;
  }

protected:
  /* 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 AST node (predicate pattern loop)
class WhileLetLoopExpr : public BaseLoopExpr
{
  // MatchArmPatterns patterns;
  std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
  std::unique_ptr<Expr> scrutinee;

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

  // Constructor with a loop label
  WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
		    std::unique_ptr<Expr> scrutinee,
		    std::unique_ptr<BlockExpr> loop_block, location_t locus,
		    tl::optional<LoopLabel> loop_label = tl::nullopt,
		    std::vector<Attribute> outer_attribs
		    = std::vector<Attribute> ())
    : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
		    std::move (outer_attribs)),
      match_arm_patterns (std::move (match_arm_patterns)),
      scrutinee (std::move (scrutinee))
  {}

  // Copy constructor with clone
  WhileLetLoopExpr (WhileLetLoopExpr const &other)
    : BaseLoopExpr (other),
      /*match_arm_patterns(other.match_arm_patterns),*/ scrutinee (
	other.scrutinee->clone_expr ())
  {
    match_arm_patterns.reserve (other.match_arm_patterns.size ());
    for (const auto &e : other.match_arm_patterns)
      match_arm_patterns.push_back (e->clone_pattern ());
  }

  // Overloaded assignment operator to clone pointers
  WhileLetLoopExpr &operator= (WhileLetLoopExpr const &other)
  {
    BaseLoopExpr::operator= (other);
    // match_arm_patterns = other.match_arm_patterns;
    scrutinee = other.scrutinee->clone_expr ();
    // loop_block = other.loop_block->clone_block_expr();
    // loop_label = other.loop_label;
    // outer_attrs = other.outer_attrs;

    match_arm_patterns.reserve (other.match_arm_patterns.size ());
    for (const auto &e : other.match_arm_patterns)
      match_arm_patterns.push_back (e->clone_pattern ());

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_scrutinee_expr ()
  {
    rust_assert (scrutinee != nullptr);
    return *scrutinee;
  }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
  {
    return match_arm_patterns;
  }
  std::vector<std::unique_ptr<Pattern> > &get_patterns ()
  {
    return match_arm_patterns;
  }

  BaseLoopExpr::Kind get_loop_kind () const override
  {
    return BaseLoopExpr::Kind::WhileLet;
  }

protected:
  /* 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);
  }
};

// For loop expression AST node (iterator loop)
class ForLoopExpr : public BaseLoopExpr
{
  std::unique_ptr<Pattern> pattern;
  std::unique_ptr<Expr> iterator_expr;

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

  // Constructor with loop label
  ForLoopExpr (std::unique_ptr<Pattern> loop_pattern,
	       std::unique_ptr<Expr> iterator_expr,
	       std::unique_ptr<BlockExpr> loop_body, location_t locus,
	       tl::optional<LoopLabel> loop_label = tl::nullopt,
	       std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
    : BaseLoopExpr (std::move (loop_body), locus, std::move (loop_label),
		    std::move (outer_attribs)),
      pattern (std::move (loop_pattern)),
      iterator_expr (std::move (iterator_expr))
  {}

  // Copy constructor with clone
  ForLoopExpr (ForLoopExpr const &other)
    : BaseLoopExpr (other), pattern (other.pattern->clone_pattern ()),
      iterator_expr (other.iterator_expr->clone_expr ())
  {}

  // Overloaded assignment operator to clone
  ForLoopExpr &operator= (ForLoopExpr const &other)
  {
    BaseLoopExpr::operator= (other);
    pattern = other.pattern->clone_pattern ();
    iterator_expr = other.iterator_expr->clone_expr ();
    /*loop_block = other.loop_block->clone_block_expr();
    loop_label = other.loop_label;
    outer_attrs = other.outer_attrs;*/

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_iterator_expr ()
  {
    rust_assert (iterator_expr != nullptr);
    return *iterator_expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Pattern &get_pattern ()
  {
    rust_assert (pattern != nullptr);
    return *pattern;
  }

  BaseLoopExpr::Kind get_loop_kind () const override
  {
    return BaseLoopExpr::Kind::For;
  }

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

// forward decl for IfExpr
class IfLetExpr;

// Base if expression with no "else" or "if let" AST node
class IfExpr : public ExprWithBlock
{
  std::vector<Attribute> outer_attrs;
  std::unique_ptr<Expr> condition;
  std::unique_ptr<BlockExpr> if_block;
  location_t locus;

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

  IfExpr (std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> if_block,
	  std::vector<Attribute> outer_attrs, location_t locus)
    : outer_attrs (std::move (outer_attrs)), condition (std::move (condition)),
      if_block (std::move (if_block)), locus (locus)
  {}
  // outer attributes are never allowed on IfExprs

  // Copy constructor with clone
  IfExpr (IfExpr const &other)
    : ExprWithBlock (other), outer_attrs (other.outer_attrs),
      locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.condition != nullptr)
      condition = other.condition->clone_expr ();
    if (other.if_block != nullptr)
      if_block = other.if_block->clone_block_expr ();
  }

  // Overloaded assignment operator to clone expressions
  IfExpr &operator= (IfExpr const &other)
  {
    ExprWithBlock::operator= (other);
    outer_attrs = other.outer_attrs;
    locus = other.locus;

    // guard to prevent null dereference (only required if error state)
    if (other.condition != nullptr)
      condition = other.condition->clone_expr ();
    else
      condition = nullptr;
    if (other.if_block != nullptr)
      if_block = other.if_block->clone_block_expr ();
    else
      if_block = nullptr;

    return *this;
  }

  // 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 ASTs 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 (ASTVisitor &vis) override;

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

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_condition_expr ()
  {
    rust_assert (condition != nullptr);
    return *condition;
  }

  std::unique_ptr<Expr> &get_condition_expr_ptr ()
  {
    rust_assert (condition != nullptr);
    return condition;
  }

  // TODO: is this better? Or is a "vis_block" better?
  BlockExpr &get_if_block ()
  {
    rust_assert (if_block != nullptr);
    return *if_block;
  }

  // Invalid if if block or condition is null, so base stripping on that.
  void mark_for_strip () override
  {
    if_block = nullptr;
    condition = nullptr;
  }
  bool is_marked_for_strip () const override
  {
    return if_block == nullptr && condition == nullptr;
  }

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
  std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::If; }

protected:
  // 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 final override
  {
    return clone_if_expr_impl ();
  }
};

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

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

  IfExprConseqElse (std::unique_ptr<Expr> condition,
		    std::unique_ptr<BlockExpr> if_block,
		    std::unique_ptr<ExprWithBlock> else_block,
		    std::vector<Attribute> outer_attrs, location_t locus)
    : IfExpr (std::move (condition), std::move (if_block),
	      std::move (outer_attrs), locus),
      else_block (std::move (else_block))
  {}
  // again, outer attributes not allowed

  // Copy constructor with clone
  IfExprConseqElse (IfExprConseqElse const &other)
    : IfExpr (other), else_block (other.else_block->clone_expr_with_block ())
  {}

  // Overloaded assignment operator with cloning
  IfExprConseqElse &operator= (IfExprConseqElse const &other)
  {
    IfExpr::operator= (other);
    // condition = other.condition->clone_expr();
    // if_block = other.if_block->clone_block_expr();
    else_block = other.else_block->clone_expr_with_block ();

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

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

  // TODO: is this better? Or is a "vis_block" better?
  ExprWithBlock &get_else_block ()
  {
    rust_assert (else_block != nullptr);
    return *else_block;
  }

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

// Basic "if let" expression AST node with no else
class IfLetExpr : public ExprWithBlock
{
  std::vector<Attribute> outer_attrs;
  std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
  std::unique_ptr<Expr> value;
  std::unique_ptr<BlockExpr> if_block;
  location_t locus;

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

  IfLetExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
	     std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
	     std::vector<Attribute> outer_attrs, location_t locus)
    : outer_attrs (std::move (outer_attrs)),
      match_arm_patterns (std::move (match_arm_patterns)),
      value (std::move (value)), if_block (std::move (if_block)), locus (locus)
  {}

  // copy constructor with clone
  IfLetExpr (IfLetExpr const &other)
    : ExprWithBlock (other), outer_attrs (other.outer_attrs),
      locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.value != nullptr)
      value = other.value->clone_expr ();
    if (other.if_block != nullptr)
      if_block = other.if_block->clone_block_expr ();

    match_arm_patterns.reserve (other.match_arm_patterns.size ());
    for (const auto &e : other.match_arm_patterns)
      match_arm_patterns.push_back (e->clone_pattern ());
  }

  // overload assignment operator to clone
  IfLetExpr &operator= (IfLetExpr const &other)
  {
    ExprWithBlock::operator= (other);
    outer_attrs = other.outer_attrs;
    locus = other.locus;

    // guard to prevent null dereference (only required if error state)
    if (other.value != nullptr)
      value = other.value->clone_expr ();
    else
      value = nullptr;
    if (other.if_block != nullptr)
      if_block = other.if_block->clone_block_expr ();
    else
      if_block = nullptr;

    match_arm_patterns.reserve (other.match_arm_patterns.size ());
    for (const auto &e : other.match_arm_patterns)
      match_arm_patterns.push_back (e->clone_pattern ());

    return *this;
  }

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

  // Unique pointer custom clone function
  std::unique_ptr<IfLetExpr> clone_if_let_expr () const
  {
    return std::unique_ptr<IfLetExpr> (clone_if_let_expr_impl ());
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if block or value is null, so base stripping on that.
  void mark_for_strip () override
  {
    if_block = nullptr;
    value = nullptr;
  }
  bool is_marked_for_strip () const override
  {
    return if_block == nullptr && value == nullptr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_value_expr ()
  {
    rust_assert (value != nullptr);
    return *value;
  }

  std::unique_ptr<Expr> &get_value_expr_ptr ()
  {
    rust_assert (value != nullptr);
    return value;
  }

  // TODO: is this better? Or is a "vis_block" better?
  BlockExpr &get_if_block ()
  {
    rust_assert (if_block != nullptr);
    return *if_block;
  }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
  {
    return match_arm_patterns;
  }
  std::vector<std::unique_ptr<Pattern> > &get_patterns ()
  {
    return match_arm_patterns;
  }

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
  std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::IfLet; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base (or rather this or any derived object) */
  IfLetExpr *clone_expr_with_block_impl () const final override
  {
    return clone_if_let_expr_impl ();
  }

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

/* AST node representing "if let" expression with an "else" expression at the
 * end */
class IfLetExprConseqElse : public IfLetExpr
{
  std::unique_ptr<ExprWithBlock> else_block;

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

  IfLetExprConseqElse (
    std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
    std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
    std::unique_ptr<ExprWithBlock> else_block,
    std::vector<Attribute> outer_attrs, location_t locus)
    : IfLetExpr (std::move (match_arm_patterns), std::move (value),
		 std::move (if_block), std::move (outer_attrs), locus),
      else_block (std::move (else_block))
  {}
  // outer attributes not allowed

  // copy constructor with clone
  IfLetExprConseqElse (IfLetExprConseqElse const &other)
    : IfLetExpr (other), else_block (other.else_block->clone_expr_with_block ())
  {}

  // overload assignment operator to clone
  IfLetExprConseqElse &operator= (IfLetExprConseqElse const &other)
  {
    IfLetExpr::operator= (other);
    // match_arm_patterns = other.match_arm_patterns;
    // value = other.value->clone_expr();
    // if_block = other.if_block->clone_block_expr();
    else_block = other.else_block->clone_expr_with_block ();
    // outer_attrs = other.outer_attrs;

    return *this;
  }

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

  void accept_vis (ASTVisitor &vis) override;

  // TODO: is this better? Or is a "vis_block" better?
  ExprWithBlock &get_else_block ()
  {
    rust_assert (else_block != nullptr);
    return *else_block;
  }

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

// Match arm expression
struct MatchArm
{
private:
  std::vector<Attribute> outer_attrs;
  // MatchArmPatterns patterns;
  std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined

  // bool has_match_arm_guard;
  // inlined from MatchArmGuard
  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,
	    std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
    : outer_attrs (std::move (outer_attrs)),
      match_arm_patterns (std::move (match_arm_patterns)),
      guard_expr (std::move (guard_expr)), locus (locus)
  {}

  // Copy constructor with clone
  MatchArm (MatchArm const &other) : outer_attrs (other.outer_attrs)
  {
    // guard to protect from null pointer dereference
    if (other.guard_expr != nullptr)
      guard_expr = other.guard_expr->clone_expr ();

    match_arm_patterns.reserve (other.match_arm_patterns.size ());
    for (const auto &e : other.match_arm_patterns)
      match_arm_patterns.push_back (e->clone_pattern ());

    locus = other.locus;
  }

  ~MatchArm () = default;

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

    if (other.guard_expr != nullptr)
      guard_expr = other.guard_expr->clone_expr ();
    else
      guard_expr = nullptr;

    match_arm_patterns.reserve (other.match_arm_patterns.size ());
    for (const auto &e : other.match_arm_patterns)
      match_arm_patterns.push_back (e->clone_pattern ());

    return *this;
  }

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

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_guard_expr ()
  {
    rust_assert (has_match_arm_guard ());
    return *guard_expr;
  }

  std::unique_ptr<Expr> &get_guard_expr_ptr ()
  {
    rust_assert (has_match_arm_guard ());
    return guard_expr;
  }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
  std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }

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

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

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

  /* TODO: does whether trailing comma exists need to be stored? currently
   * assuming it is only syntactical and has no effect on meaning. */

public:
  MatchCase (MatchArm arm, std::unique_ptr<Expr> expr)
    : arm (std::move (arm)), expr (std::move (expr)),
      node_id (Analysis::Mappings::get ().get_next_node_id ())
  {}

  MatchCase (const MatchCase &other)
    : arm (other.arm), expr (other.expr->clone_expr ()), node_id (other.node_id)
  {}

  MatchCase &operator= (const MatchCase &other)
  {
    arm = other.arm;
    expr = other.expr->clone_expr ();
    node_id = other.node_id;

    return *this;
  }

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

  ~MatchCase () = default;

  std::string as_string () const;

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_expr ()
  {
    rust_assert (expr != nullptr);
    return *expr;
  }

  std::unique_ptr<Expr> &get_expr_ptr ()
  {
    rust_assert (expr != nullptr);
    return expr;
  }

  // TODO: is this better? Or is a "vis_block" better?
  MatchArm &get_arm ()
  {
    rust_assert (!arm.is_error ());
    return arm;
  }

  NodeId get_node_id () const { return node_id; }
};

// Match expression AST node
class MatchExpr : public ExprWithBlock
{
  std::vector<Attribute> outer_attrs;
  std::unique_ptr<Expr> branch_value;
  std::vector<Attribute> inner_attrs;
  std::vector<MatchCase> match_arms;
  location_t locus;

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

  // Returns whether the match expression has any match arms.
  bool has_match_arms () const { return !match_arms.empty (); }

  MatchExpr (std::unique_ptr<Expr> branch_value,
	     std::vector<MatchCase> match_arms,
	     std::vector<Attribute> inner_attrs,
	     std::vector<Attribute> outer_attrs, location_t locus)
    : outer_attrs (std::move (outer_attrs)),
      branch_value (std::move (branch_value)),
      inner_attrs (std::move (inner_attrs)),
      match_arms (std::move (match_arms)), locus (locus)
  {}

  // Copy constructor requires clone due to unique_ptr
  MatchExpr (MatchExpr const &other)
    : ExprWithBlock (other), outer_attrs (other.outer_attrs),
      inner_attrs (other.inner_attrs), match_arms (other.match_arms),
      locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.branch_value != nullptr)
      branch_value = other.branch_value->clone_expr ();
  }

  // Overloaded assignment operator to clone due to unique_ptr
  MatchExpr &operator= (MatchExpr const &other)
  {
    ExprWithBlock::operator= (other);
    inner_attrs = other.inner_attrs;
    match_arms = other.match_arms;
    outer_attrs = other.outer_attrs;
    locus = other.locus;

    // guard to prevent null dereference (only required if error state)
    if (other.branch_value != nullptr)
      branch_value = other.branch_value->clone_expr ();
    else
      branch_value = nullptr;

    return *this;
  }

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

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if branch value is null, so base stripping on that.
  void mark_for_strip () override { branch_value = nullptr; }
  bool is_marked_for_strip () const override { return branch_value == nullptr; }

  // TODO: this mutable getter seems really dodgy. Think up better way.
  const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
  std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  // TODO: is this better? Or is a "vis_block" better?
  Expr &get_scrutinee_expr ()
  {
    rust_assert (branch_value != nullptr);
    return *branch_value;
  }

  const std::vector<MatchCase> &get_match_cases () const { return match_arms; }
  std::vector<MatchCase> &get_match_cases () { return match_arms; }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::Match; }

protected:
  /* 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 AST node (pseudo-member variable access)
class AwaitExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  std::unique_ptr<Expr> awaited_expr;
  location_t locus;

public:
  // TODO: ensure outer attributes are actually allowed
  AwaitExpr (std::unique_ptr<Expr> awaited_expr,
	     std::vector<Attribute> outer_attrs, location_t locus)
    : outer_attrs (std::move (outer_attrs)),
      awaited_expr (std::move (awaited_expr)), locus (locus)
  {}

  // copy constructor with clone
  AwaitExpr (AwaitExpr const &other)
    : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
      locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.awaited_expr != nullptr)
      awaited_expr = other.awaited_expr->clone_expr ();
  }

  // overloaded assignment operator with clone
  AwaitExpr &operator= (AwaitExpr const &other)
  {
    ExprWithoutBlock::operator= (other);
    outer_attrs = other.outer_attrs;
    locus = other.locus;

    // guard to prevent null dereference (only required if error state)
    if (other.awaited_expr != nullptr)
      awaited_expr = other.awaited_expr->clone_expr ();
    else
      awaited_expr = nullptr;

    return *this;
  }

  // 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 (ASTVisitor &vis) override;

  // Invalid if awaited expr is null, so base stripping on that.
  void mark_for_strip () override { awaited_expr = nullptr; }
  bool is_marked_for_strip () const override { return awaited_expr == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  std::unique_ptr<Expr> &get_awaited_expr ()
  {
    rust_assert (awaited_expr != nullptr);
    return awaited_expr;
  }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::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 AST node (block expr that evaluates to a future)
class AsyncBlockExpr : public ExprWithBlock
{
  // TODO: should this extend BlockExpr rather than be a composite of it?
  std::vector<Attribute> outer_attrs;
  bool has_move;
  std::unique_ptr<BlockExpr> block_expr;
  location_t locus;

public:
  AsyncBlockExpr (std::unique_ptr<BlockExpr> block_expr, bool has_move,
		  std::vector<Attribute> outer_attrs, location_t locus)
    : outer_attrs (std::move (outer_attrs)), has_move (has_move),
      block_expr (std::move (block_expr)), locus (locus)
  {}

  // copy constructor with clone
  AsyncBlockExpr (AsyncBlockExpr const &other)
    : ExprWithBlock (other), outer_attrs (other.outer_attrs),
      has_move (other.has_move), locus (other.locus)
  {
    // guard to prevent null dereference (only required if error state)
    if (other.block_expr != nullptr)
      block_expr = other.block_expr->clone_block_expr ();
  }

  // overloaded assignment operator to clone
  AsyncBlockExpr &operator= (AsyncBlockExpr const &other)
  {
    ExprWithBlock::operator= (other);
    outer_attrs = other.outer_attrs;
    has_move = other.has_move;
    locus = other.locus;

    // guard to prevent null dereference (only required if error state)
    if (other.block_expr != nullptr)
      block_expr = other.block_expr->clone_block_expr ();
    else
      block_expr = nullptr;

    return *this;
  }

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

  std::string as_string () const override;

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

  void accept_vis (ASTVisitor &vis) override;

  // Invalid if block is null, so base stripping on that.
  void mark_for_strip () override { block_expr = nullptr; }
  bool is_marked_for_strip () const override { return block_expr == nullptr; }

  // TODO: is this better? Or is a "vis_block" better?
  std::unique_ptr<BlockExpr> &get_block_expr ()
  {
    rust_assert (block_expr != nullptr);
    return block_expr;
  }

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

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

  Expr::Kind get_expr_kind () const override { return Expr::Kind::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);
  }
};

// Inline-assembly specific options
enum class InlineAsmOption
{
  PURE = 1 << 0,
  NOMEM = 1 << 1,
  READONLY = 1 << 2,
  PRESERVES_FLAGS = 1 << 3,
  NORETURN = 1 << 4,
  NOSTACK = 1 << 5,
  ATT_SYNTAX = 1 << 6,
  RAW = 1 << 7,
  MAY_UNWIND = 1 << 8,
};

struct AnonConst
{
  NodeId id;
  std::unique_ptr<Expr> expr;
  AnonConst (NodeId id, std::unique_ptr<Expr> expr)
    : id (id), expr (std::move (expr))
  {
    rust_assert (this->expr != nullptr);
  }
  AnonConst (const AnonConst &other)
  {
    id = other.id;
    expr = other.expr->clone_expr ();
  }

  AnonConst operator= (const AnonConst &other)
  {
    id = other.id;
    expr = other.expr->clone_expr ();
    return *this;
  }
};

struct InlineAsmRegOrRegClass
{
  enum Type
  {
    Reg,
    RegClass,
  };

  struct Reg
  {
    std::string Symbol;
  };

  struct RegClass
  {
    std::string Symbol;
  };

  Type type;
  struct Reg reg;
  struct RegClass reg_class;

  Identifier name;
  location_t locus;
};

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 InlineAsmOperand
{
public:
  enum class RegisterType
  {
    In,
    Out,
    InOut,
    SplitInOut,
    Const,
    Sym,
    Label,
  };

  class Register
  {
  public:
    Register () {}
    virtual ~Register () = default;

    std::unique_ptr<Register> clone () const
    {
      return std::unique_ptr<Register> (clone_impl ());
    }

  protected:
    virtual Register *clone_impl () const = 0;
  };

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

    In (tl::optional<struct InlineAsmRegOrRegClass> &reg,
	std::unique_ptr<Expr> expr)
      : reg (reg), expr (std::move (expr))
    {
      rust_assert (this->expr != nullptr);
    }

    In (const In &other)
    {
      reg = other.reg;

      expr = other.expr->clone_expr ();
    }

    In operator= (const In &other)
    {
      reg = other.reg;
      expr = other.expr->clone_expr ();

      return *this;
    }

  private:
    In *clone_impl () const { return new In (*this); }
  };

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

    Out (tl::optional<struct InlineAsmRegOrRegClass> &reg, bool late,
	 std::unique_ptr<Expr> expr)
      : reg (reg), late (late), expr (std::move (expr))
    {
      rust_assert (this->expr != nullptr);
    }

    Out (const Out &other)
    {
      reg = other.reg;
      late = other.late;
      expr = other.expr->clone_expr ();
    }

    Out operator= (const Out &other)
    {
      reg = other.reg;
      late = other.late;
      expr = other.expr->clone_expr ();
      return *this;
    }

  private:
    Out *clone_impl () const { return new Out (*this); }
  };

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

    InOut (tl::optional<struct InlineAsmRegOrRegClass> &reg, bool late,
	   std::unique_ptr<Expr> expr)
      : reg (reg), late (late), expr (std::move (expr))
    {
      rust_assert (this->expr != nullptr);
    }

    InOut (const InOut &other)
    {
      reg = other.reg;
      late = other.late;
      expr = other.expr->clone_expr ();
    }

    InOut operator= (const InOut &other)
    {
      reg = other.reg;
      late = other.late;
      expr = other.expr->clone_expr ();

      return *this;
    }

  private:
    InOut *clone_impl () const { return new InOut (*this); }
  };

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

    SplitInOut (tl::optional<struct InlineAsmRegOrRegClass> &reg, bool late,
		std::unique_ptr<Expr> in_expr, std::unique_ptr<Expr> out_expr)
      : reg (reg), late (late), in_expr (std::move (in_expr)),
	out_expr (std::move (out_expr))
    {
      rust_assert (this->in_expr != nullptr);
      rust_assert (this->out_expr != nullptr);
    }

    SplitInOut (const SplitInOut &other)
    {
      reg = other.reg;
      late = other.late;
      in_expr = other.in_expr->clone_expr ();
      out_expr = other.out_expr->clone_expr ();
    }

    SplitInOut operator= (const SplitInOut &other)
    {
      reg = other.reg;
      late = other.late;
      in_expr = other.in_expr->clone_expr ();
      out_expr = other.out_expr->clone_expr ();

      return *this;
    }

  private:
    SplitInOut *clone_impl () const { return new SplitInOut (*this); }
  };

  class Const : public Register
  {
  public:
    AnonConst anon_const;

  private:
    Const *clone_impl () const { return new Const (*this); }
  };

  class Sym : public Register
  {
  public:
    std::unique_ptr<Expr> expr;

    Sym (std::unique_ptr<Expr> expr) : expr (std::move (expr))
    {
      rust_assert (this->expr != nullptr);
    }
    Sym (const Sym &other)
    {
      expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
    }

    Sym operator= (const Sym &other)
    {
      expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
      return *this;
    }

  private:
    Sym *clone_impl () const { return new Sym (*this); }
  };

  class Label : public Register
  {
  public:
    std::string label_name;
    std::unique_ptr<Expr> expr;

    Label (tl::optional<std::string> label_name, std::unique_ptr<Expr> expr)
      : expr (std::move (expr))
    {
      rust_assert (this->expr != nullptr);
      if (label_name.has_value ())
	this->label_name = label_name.value ();
    }
    Label (const Label &other)
    {
      expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
    }

    Label operator= (const Label &other)
    {
      expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
      return *this;
    }

  private:
    Label *clone_impl () const { return new Label (*this); }
  };

  InlineAsmOperand (const InlineAsmOperand &other)
    : register_type (other.register_type), locus (other.locus),
      reg (other.reg->clone ())
  {}

  InlineAsmOperand (const In &reg, location_t locus)
    : register_type (RegisterType::In), locus (locus), reg (new In (reg))
  {}
  InlineAsmOperand (const Out &reg, location_t locus)
    : register_type (RegisterType::Out), locus (locus), reg (new Out (reg))
  {}
  InlineAsmOperand (const InOut &reg, location_t locus)
    : register_type (RegisterType::InOut), locus (locus), reg (new InOut (reg))
  {}
  InlineAsmOperand (const SplitInOut &reg, location_t locus)
    : register_type (RegisterType::SplitInOut), locus (locus),
      reg (new SplitInOut (reg))
  {}
  InlineAsmOperand (const Const &reg, location_t locus)
    : register_type (RegisterType::Const), locus (locus), reg (new Const (reg))
  {}
  InlineAsmOperand (const Sym &reg, location_t locus)
    : register_type (RegisterType::Sym), locus (locus), reg (new Sym (reg))
  {}
  InlineAsmOperand (const Label &reg, location_t locus)
    : register_type (RegisterType::Label), locus (locus), reg (new Label (reg))
  {}

  location_t get_locus () const { return locus; }
  RegisterType get_register_type () const { return register_type; }

  // Potentially fail immediately if you don't use get_register_type() to
  // inspect the RegisterType first before calling the following functions Check
  // first
  In &get_in ()
  {
    rust_assert (register_type == RegisterType::In);
    return static_cast<In &> (*reg);
  }
  const In &get_in () const
  {
    rust_assert (register_type == RegisterType::In);
    return static_cast<const In &> (*reg);
  }

  Out &get_out ()
  {
    rust_assert (register_type == RegisterType::Out);
    return static_cast<Out &> (*reg);
  }
  const Out &get_out () const
  {
    rust_assert (register_type == RegisterType::Out);
    return static_cast<const Out &> (*reg);
  }

  InOut &get_in_out ()
  {
    rust_assert (register_type == RegisterType::InOut);
    return static_cast<InOut &> (*reg);
  }
  const InOut &get_in_out () const
  {
    rust_assert (register_type == RegisterType::InOut);
    return static_cast<const InOut &> (*reg);
  }

  SplitInOut &get_split_in_out ()
  {
    rust_assert (register_type == RegisterType::SplitInOut);
    return static_cast<SplitInOut &> (*reg);
  }
  const SplitInOut &get_split_in_out () const
  {
    rust_assert (register_type == RegisterType::SplitInOut);
    return static_cast<const SplitInOut &> (*reg);
  }

  Const &get_const ()
  {
    rust_assert (register_type == RegisterType::Const);
    return static_cast<Const &> (*reg);
  }
  const Const &get_const () const
  {
    rust_assert (register_type == RegisterType::Const);
    return static_cast<Const &> (*reg);
  }

  Sym &get_sym ()
  {
    rust_assert (register_type == RegisterType::Sym);
    return static_cast<Sym &> (*reg);
  }
  const Sym &get_sym () const
  {
    rust_assert (register_type == RegisterType::Sym);
    return static_cast<const Sym &> (*reg);
  }

  Label &get_label ()
  {
    rust_assert (register_type == RegisterType::Label);
    return static_cast<Label &> (*reg);
  }
  const Label &get_label () const
  {
    rust_assert (register_type == RegisterType::Label);
    return static_cast<const Label &> (*reg);
  }

private:
  RegisterType register_type;

  location_t locus;
  std::unique_ptr<Register> reg;
};

struct InlineAsmPlaceHolder
{
  size_t operand_idx;
  char modifier; // can be null
  location_t locus;
};

struct InlineAsmTemplatePiece
{
  bool is_placeholder;
  std::string string;
  InlineAsmPlaceHolder placeholder;
};

struct TupleClobber
{
  // as gccrs still doesn't contain a symbol class I have put them as strings
  std::string symbol;
  location_t loc;
};

struct TupleTemplateStr
{
  // as gccrs still doesn't contain a symbol class I have put them as strings
  location_t loc;
  std::string symbol;

  location_t get_locus () { return loc; }
  TupleTemplateStr (location_t loc, const std::string &symbol)
    : loc (loc), symbol (symbol)
  {}
};

// Inline Assembly Node
class InlineAsm : public ExprWithoutBlock
{
private:
  location_t locus;
  // TODO: Not sure how outer_attrs plays with InlineAsm, I put it here in order
  // to override, very hacky.
  std::vector<Attribute> outer_attrs;

public:
  // https://github.com/rust-lang/rust/blob/55cac26a9ef17da1c9c77c0816e88e178b7cc5dd/compiler/rustc_builtin_macros/src/asm.rs#L56C1-L64C7
  //   let mut args = AsmArgs {
  //     templates: vec![first_template],
  //     operands: vec![],
  //     named_args: Default::default(),
  //     reg_args: Default::default(),
  //     clobber_abis: Vec::new(),
  //     options: ast::InlineAsmOptions::empty(),
  //     options_spans: vec![],
  // };
  std::vector<InlineAsmTemplatePiece> template_;
  std::vector<TupleTemplateStr> template_strs;
  std::vector<InlineAsmOperand> operands;
  std::map<std::string, int> named_args;
  std::set<int> reg_args;
  std::vector<TupleClobber> clobber_abi;
  std::set<InlineAsmOption> options;

  std::vector<location_t> line_spans;

  bool is_global_asm;

  InlineAsm (location_t locus, bool is_global_asm)
    : locus (locus), is_global_asm (is_global_asm)
  {}

  void accept_vis (ASTVisitor &vis) override;
  std::string as_string () const override { return "InlineAsm AST Node"; }

  location_t get_locus () const override { return locus; }

  void mark_for_strip () override {}

  bool is_marked_for_strip () const override { return false; }

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

  void set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; }

  std::vector<InlineAsmTemplatePiece> get_template_ () { return template_; }

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

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

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

  std::set<InlineAsmOption> get_options () { return options; }

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

  Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; }
};

class LlvmInlineAsm : public ExprWithoutBlock
{
  // llvm_asm!("" :         : "r"(&mut dummy) : "memory" : "volatile");
  //           Asm, Outputs, Inputs,            Clobbers, Options,

public:
  enum class Dialect
  {
    Att,
    Intel,
  };

private:
  location_t locus;
  std::vector<Attribute> outer_attrs;
  std::vector<LlvmOperand> inputs;
  std::vector<LlvmOperand> outputs;
  std::vector<TupleTemplateStr> templates;
  std::vector<TupleClobber> clobbers;
  bool volatility;
  bool align_stack;
  Dialect dialect;

public:
  LlvmInlineAsm (location_t locus) : locus (locus) {}

  Dialect get_dialect () { return dialect; }

  location_t get_locus () const override { return locus; }

  void mark_for_strip () override {}

  bool is_marked_for_strip () const override { return false; }

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

  void accept_vis (ASTVisitor &vis) override;

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

  void set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; }

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

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

  Expr::Kind get_expr_kind () const override
  {
    return Expr::Kind::LlvmInlineAsm;
  }

  void set_align_stack (bool align_stack) { this->align_stack = align_stack; }
  bool is_stack_aligned () { return align_stack; }

  void set_volatile (bool volatility) { this->volatility = volatility; }
  bool is_volatile () { return volatility; }

  void set_dialect (Dialect dialect) { this->dialect = dialect; }

  void set_inputs (std::vector<LlvmOperand> operands) { inputs = operands; }
  void set_outputs (std::vector<LlvmOperand> operands) { outputs = operands; }

  std::vector<LlvmOperand> &get_inputs () { return inputs; }
  std::vector<LlvmOperand> &get_outputs () { return outputs; }

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

} // namespace AST
} // namespace Rust

#endif
