diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
new file mode 100644
index 000000000000..832785296460
--- /dev/null
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -0,0 +1,4194 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#ifndef RUST_HIR_EXPR_H
+#define RUST_HIR_EXPR_H
+
+#include "rust-common.h"
+#include "rust-ast-full-decls.h"
+#include "rust-hir.h"
+#include "rust-hir-path.h"
+#include "operator.h"
+
+namespace Rust {
+namespace HIR {
+
+// HIR node for an expression with an accompanying block - abstract
+class ExprWithBlock : public Expr
+{
+ // TODO: should this mean that a BlockExpr should be a member variable?
+protected:
+ ExprWithBlock (Analysis::NodeMapping mappings,
+ AST::AttrVec outer_attrs = AST::AttrVec ())
+ : Expr (std::move (mappings), std::move (outer_attrs))
+ {}
+
+ // pure virtual clone implementation
+ virtual ExprWithBlock *clone_expr_with_block_impl () const = 0;
+
+ // prevent having to define multiple clone expressions
+ ExprWithBlock *clone_expr_impl () const override
+ {
+ return clone_expr_with_block_impl ();
+ }
+
+public:
+ // Unique pointer custom clone function
+ std::unique_ptr clone_expr_with_block () const
+ {
+ return std::unique_ptr (clone_expr_with_block_impl ());
+ }
+
+ BlockType get_block_expr_type () const final override
+ {
+ return BlockType::WITH_BLOCK;
+ };
+};
+
+// Literals? Or literal base?
+class LiteralExpr : public ExprWithoutBlock
+{
+ Literal literal;
+ Location locus;
+
+public:
+ std::string as_string () const override
+ {
+ return "( " + literal.as_string () + " (" + get_mappings ().as_string ()
+ + "))";
+ }
+
+ Literal::LitType get_lit_type () const { return literal.get_lit_type (); }
+
+ LiteralExpr (Analysis::NodeMapping mappings, std::string value_as_string,
+ Literal::LitType type, PrimitiveCoreType type_hint,
+ Location locus, AST::AttrVec outer_attrs)
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)),
+ literal (std::move (value_as_string), type, type_hint), locus (locus)
+ {}
+
+ LiteralExpr (Analysis::NodeMapping mappings, Literal literal, Location locus,
+ AST::AttrVec outer_attrs)
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)),
+ literal (std::move (literal)), locus (locus)
+ {}
+
+ // Unique pointer custom clone function
+ std::unique_ptr clone_literal_expr () const
+ {
+ return std::unique_ptr (clone_literal_expr_impl ());
+ }
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Literal &get_literal () { return literal; }
+ const Literal &get_literal () const { return literal; }
+
+ ExprType get_expression_type () const override final { return ExprType::Lit; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ LiteralExpr *clone_expr_impl () const override
+ {
+ return new LiteralExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ LiteralExpr *clone_expr_without_block_impl () const override
+ {
+ return new LiteralExpr (*this);
+ }
+
+ /* not virtual as currently no subclasses of LiteralExpr, but could be in
+ * future */
+ /*virtual*/ LiteralExpr *clone_literal_expr_impl () const
+ {
+ return new LiteralExpr (*this);
+ }
+};
+
+/* Represents an expression using unary or binary operators as HIR node. Can be
+ * overloaded. */
+class OperatorExpr : public ExprWithoutBlock
+{
+ // TODO: create binary and unary operator subclasses?
+public:
+ Location locus;
+
+protected:
+ /* Variable must be protected to allow derived classes to use it as a first
+ * class citizen */
+ std::unique_ptr main_or_left_expr;
+
+ // Constructor (only for initialisation of expr purposes)
+ OperatorExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr main_or_left_expr,
+ AST::AttrVec outer_attribs, Location locus)
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+ locus (locus), main_or_left_expr (std::move (main_or_left_expr))
+ {}
+
+ // Copy constructor (only for initialisation of expr purposes)
+ OperatorExpr (OperatorExpr const &other)
+ : ExprWithoutBlock (other), locus (other.locus),
+ 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);
+ main_or_left_expr = other.main_or_left_expr->clone_expr ();
+ locus = other.locus;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ OperatorExpr (OperatorExpr &&other) = default;
+ OperatorExpr &operator= (OperatorExpr &&other) = default;
+
+public:
+ Location get_locus () const override final { return locus; }
+
+ std::unique_ptr &get_expr () { return main_or_left_expr; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Operator;
+ }
+};
+
+/* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be
+ * overloaded. */
+class BorrowExpr : public OperatorExpr
+{
+ Mutability mut;
+ bool double_borrow;
+
+public:
+ std::string as_string () const override;
+
+ BorrowExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr borrow_lvalue, Mutability mut,
+ bool is_double_borrow, AST::AttrVec outer_attribs, Location locus)
+ : OperatorExpr (std::move (mappings), std::move (borrow_lvalue),
+ std::move (outer_attribs), locus),
+ mut (mut), double_borrow (is_double_borrow)
+ {}
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Mutability get_mut () const { return mut; }
+ bool is_mut () const { return mut == Mutability::Mut; }
+ bool get_is_double_borrow () const { return double_borrow; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ BorrowExpr *clone_expr_impl () const override
+ {
+ return new BorrowExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ BorrowExpr *clone_expr_without_block_impl () const override
+ {
+ return new BorrowExpr (*this);
+ }
+};
+
+// Unary prefix * deference operator
+class DereferenceExpr : public OperatorExpr
+{
+public:
+ std::string as_string () const override;
+
+ // Constructor calls OperatorExpr's protected constructor
+ DereferenceExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr deref_lvalue,
+ AST::AttrVec outer_attribs, Location locus)
+ : OperatorExpr (std::move (mappings), std::move (deref_lvalue),
+ std::move (outer_attribs), locus)
+ {}
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ DereferenceExpr *clone_expr_impl () const override
+ {
+ return new DereferenceExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ DereferenceExpr *clone_expr_without_block_impl () const override
+ {
+ return new DereferenceExpr (*this);
+ }
+};
+
+// Unary postfix ? error propogation operator. Cannot be overloaded.
+class ErrorPropagationExpr : public OperatorExpr
+{
+public:
+ std::string as_string () const override;
+
+ // Constructor calls OperatorExpr's protected constructor
+ ErrorPropagationExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr potential_error_value,
+ AST::AttrVec outer_attribs, Location locus)
+ : OperatorExpr (std::move (mappings), std::move (potential_error_value),
+ std::move (outer_attribs), locus)
+ {}
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ErrorPropagationExpr *clone_expr_impl () const override
+ {
+ return new ErrorPropagationExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ErrorPropagationExpr *clone_expr_without_block_impl () const override
+ {
+ return new ErrorPropagationExpr (*this);
+ }
+};
+
+// Unary prefix - or ! negation or NOT operators.
+class NegationExpr : public OperatorExpr
+{
+public:
+ using ExprType = NegationOperator;
+
+private:
+ /* Note: overload negation via std::ops::Neg and not via std::ops::Not
+ * Negation only works for signed integer and floating-point types, NOT only
+ * works for boolean and integer types (via bitwise NOT) */
+ ExprType expr_type;
+
+public:
+ std::string as_string () const override;
+
+ ExprType get_expr_type () const { return expr_type; }
+
+ // Constructor calls OperatorExpr's protected constructor
+ NegationExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr negated_value, ExprType expr_kind,
+ AST::AttrVec outer_attribs, Location locus)
+ : OperatorExpr (std::move (mappings), std::move (negated_value),
+ std::move (outer_attribs), locus),
+ expr_type (expr_kind)
+ {}
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ NegationExpr *clone_expr_impl () const override
+ {
+ return new NegationExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ NegationExpr *clone_expr_without_block_impl () const override
+ {
+ return new NegationExpr (*this);
+ }
+};
+
+// Infix binary operators. +, -, *, /, %, &, |, ^, <<, >>
+class ArithmeticOrLogicalExpr : public OperatorExpr
+{
+public:
+ using ExprType = ArithmeticOrLogicalOperator;
+
+private:
+ // Note: overloading trait specified in comments
+ ExprType expr_type;
+
+ std::unique_ptr right_expr;
+
+public:
+ std::string as_string () const override;
+
+ ExprType get_expr_type () const { return expr_type; }
+
+ // Constructor calls OperatorExpr's protected constructor
+ ArithmeticOrLogicalExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr left_value,
+ std::unique_ptr right_value,
+ ExprType expr_kind, Location locus)
+ : OperatorExpr (std::move (mappings), std::move (left_value),
+ AST::AttrVec (), 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 (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); }
+ void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); }
+
+ Expr *get_lhs () { return main_or_left_expr.get (); }
+ Expr *get_rhs () { return right_expr.get (); }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ArithmeticOrLogicalExpr *clone_expr_impl () const override
+ {
+ return new ArithmeticOrLogicalExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ArithmeticOrLogicalExpr *clone_expr_without_block_impl () const override
+ {
+ return new ArithmeticOrLogicalExpr (*this);
+ }
+};
+
+// Infix binary comparison operators. ==, !=, <, <=, >, >=
+class ComparisonExpr : public OperatorExpr
+{
+public:
+ using ExprType = ComparisonOperator;
+
+private:
+ // Note: overloading trait specified in comments
+ ExprType expr_type;
+
+ std::unique_ptr right_expr;
+
+public:
+ std::string as_string () const override;
+
+ ExprType get_expr_type () const { return expr_type; }
+
+ // Constructor requires pointers for polymorphism
+ ComparisonExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr left_value,
+ std::unique_ptr right_value, ExprType comparison_kind,
+ Location locus)
+ : OperatorExpr (std::move (mappings), std::move (left_value),
+ AST::AttrVec (), 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 (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Expr *get_lhs () { return main_or_left_expr.get (); }
+ Expr *get_rhs () { return right_expr.get (); }
+
+ ExprType get_kind () { return expr_type; }
+
+ /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2)
+ * maybe? */
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ComparisonExpr *clone_expr_impl () const override
+ {
+ return new ComparisonExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ComparisonExpr *clone_expr_without_block_impl () const override
+ {
+ return new ComparisonExpr (*this);
+ }
+};
+
+// Infix binary lazy boolean logical operators && and ||.
+class LazyBooleanExpr : public OperatorExpr
+{
+public:
+ using ExprType = LazyBooleanOperator;
+
+private:
+ ExprType expr_type;
+
+ std::unique_ptr right_expr;
+
+public:
+ // Constructor calls OperatorExpr's protected constructor
+ LazyBooleanExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr left_bool_expr,
+ std::unique_ptr right_bool_expr, ExprType expr_kind,
+ Location locus)
+ : OperatorExpr (std::move (mappings), std::move (left_bool_expr),
+ AST::AttrVec (), 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 (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Expr *get_lhs () { return main_or_left_expr.get (); }
+
+ Expr *get_rhs () { return right_expr.get (); }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ LazyBooleanExpr *clone_expr_impl () const override
+ {
+ return new LazyBooleanExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ LazyBooleanExpr *clone_expr_without_block_impl () const override
+ {
+ return new LazyBooleanExpr (*this);
+ }
+};
+
+// Binary infix "as" chir expression.
+class TypeCastExpr : public OperatorExpr
+{
+ std::unique_ptr type_to_convert_to;
+
+ // Note: only certain type casts allowed, outlined in reference
+public:
+ std::string as_string () const override;
+
+ // Constructor requires calling protected constructor of OperatorExpr
+ TypeCastExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr expr_to_cast,
+ std::unique_ptr type_to_cast_to, Location locus)
+ : OperatorExpr (std::move (mappings), std::move (expr_to_cast),
+ AST::AttrVec (), 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 ())
+ {}
+
+ // 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 ();
+
+ return *this;
+ }
+
+ // move constructors as not supported in c++03
+ TypeCastExpr (TypeCastExpr &&other) = default;
+ TypeCastExpr &operator= (TypeCastExpr &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_casted_expr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
+ std::unique_ptr &get_type_to_convert_to ()
+ {
+ rust_assert (type_to_convert_to != nullptr);
+ return type_to_convert_to;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ TypeCastExpr *clone_expr_impl () const override
+ {
+ return new TypeCastExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ TypeCastExpr *clone_expr_without_block_impl () const override
+ {
+ return new TypeCastExpr (*this);
+ }
+};
+
+// Binary assignment expression.
+class AssignmentExpr : public OperatorExpr
+{
+ std::unique_ptr right_expr;
+
+public:
+ std::string as_string () const override;
+
+ // Call OperatorExpr constructor to initialise left_expr
+ AssignmentExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr value_to_assign_to,
+ std::unique_ptr value_to_assign, Location locus)
+ : OperatorExpr (std::move (mappings), std::move (value_to_assign_to),
+ AST::AttrVec (), 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 (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); }
+ void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); }
+
+ Expr *get_lhs () { return main_or_left_expr.get (); }
+ Expr *get_rhs () { return right_expr.get (); }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ AssignmentExpr *clone_expr_impl () const override
+ {
+ return new AssignmentExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ AssignmentExpr *clone_expr_without_block_impl () const override
+ {
+ return new AssignmentExpr (*this);
+ }
+};
+
+class CompoundAssignmentExpr : public OperatorExpr
+{
+public:
+ using ExprType = ArithmeticOrLogicalOperator;
+
+private:
+ // Note: overloading trait specified in comments
+ ExprType expr_type;
+ std::unique_ptr right_expr;
+
+public:
+ std::string as_string () const override;
+
+ ExprType get_expr_type () const { return expr_type; }
+
+ // Use pointers in constructor to enable polymorphism
+ CompoundAssignmentExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr value_to_assign_to,
+ std::unique_ptr value_to_assign,
+ ExprType expr_kind, Location locus)
+ : OperatorExpr (std::move (mappings), std::move (value_to_assign_to),
+ AST::AttrVec (), 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 (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_left_expr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
+ std::unique_ptr &get_right_expr ()
+ {
+ rust_assert (right_expr != nullptr);
+ return right_expr;
+ }
+
+ void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); }
+ void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); }
+
+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
+{
+ AST::AttrVec inner_attrs;
+ std::unique_ptr expr_in_parens;
+
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ AST::AttrVec get_inner_attrs () const { return inner_attrs; }
+
+ GroupedExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr parenthesised_expr,
+ AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
+ Location locus)
+ : ExprWithoutBlock (std::move (mappings), 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), inner_attrs (other.inner_attrs),
+ expr_in_parens (other.expr_in_parens->clone_expr ()), locus (other.locus)
+ {}
+
+ // Overloaded assignment operator to clone expr_in_parens
+ GroupedExpr &operator= (GroupedExpr const &other)
+ {
+ ExprWithoutBlock::operator= (other);
+ inner_attrs = other.inner_attrs;
+ expr_in_parens = other.expr_in_parens->clone_expr ();
+ locus = other.locus;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ GroupedExpr (GroupedExpr &&other) = default;
+ GroupedExpr &operator= (GroupedExpr &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_expr_in_parens ()
+ {
+ rust_assert (expr_in_parens != nullptr);
+ return expr_in_parens;
+ }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Grouped;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ GroupedExpr *clone_expr_impl () const override
+ {
+ return new GroupedExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ GroupedExpr *clone_expr_without_block_impl () const override
+ {
+ return new GroupedExpr (*this);
+ }
+};
+
+// Base array initialisation internal element representation thing (abstract)
+// aka ArrayElements
+class ArrayElems
+{
+public:
+ enum ArrayExprType
+ {
+ VALUES,
+ COPIED,
+ };
+
+ ArrayElems (Analysis::NodeMapping mappings) : mappings (mappings){};
+
+ virtual ~ArrayElems () {}
+
+ // Unique pointer custom clone ArrayElems function
+ std::unique_ptr clone_array_elems () const
+ {
+ return std::unique_ptr (clone_array_elems_impl ());
+ }
+
+ virtual std::string as_string () const = 0;
+
+ virtual void accept_vis (HIRFullVisitor &vis) = 0;
+
+ virtual ArrayExprType get_array_expr_type () const = 0;
+
+ Analysis::NodeMapping &get_mappings () { return mappings; }
+
+protected:
+ // pure virtual clone implementation
+ virtual ArrayElems *clone_array_elems_impl () const = 0;
+
+ Analysis::NodeMapping mappings;
+};
+
+// Value array elements
+class ArrayElemsValues : public ArrayElems
+{
+ std::vector > values;
+
+ // TODO: should this store location data?
+
+public:
+ ArrayElemsValues (Analysis::NodeMapping mappings,
+ std::vector > elems)
+ : ArrayElems (mappings), values (std::move (elems))
+ {}
+
+ // copy constructor with vector clone
+ ArrayElemsValues (ArrayElemsValues const &other) : ArrayElems (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 (HIRFullVisitor &vis) override;
+
+ size_t get_num_elements () const { return values.size (); }
+
+ std::vector > &get_values () { return values; }
+
+ ArrayElems::ArrayExprType get_array_expr_type () const override final
+ {
+ return ArrayElems::ArrayExprType::VALUES;
+ }
+
+protected:
+ ArrayElemsValues *clone_array_elems_impl () const override
+ {
+ return new ArrayElemsValues (*this);
+ }
+};
+
+// Copied array element and number of copies
+class ArrayElemsCopied : public ArrayElems
+{
+ std::unique_ptr elem_to_copy;
+ std::unique_ptr num_copies;
+
+public:
+ // Constructor requires pointers for polymorphism
+ ArrayElemsCopied (Analysis::NodeMapping mappings,
+ std::unique_ptr copied_elem,
+ std::unique_ptr copy_amount)
+ : ArrayElems (mappings), elem_to_copy (std::move (copied_elem)),
+ num_copies (std::move (copy_amount))
+ {}
+
+ // Copy constructor required due to unique_ptr - uses custom clone
+ ArrayElemsCopied (ArrayElemsCopied const &other)
+ : ArrayElems (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 (HIRFullVisitor &vis) override;
+
+ Expr *get_elem_to_copy () { return elem_to_copy.get (); }
+
+ Expr *get_num_copies_expr () { return num_copies.get (); }
+
+ ArrayElems::ArrayExprType get_array_expr_type () const override final
+ {
+ return ArrayElems::ArrayExprType::COPIED;
+ }
+
+protected:
+ ArrayElemsCopied *clone_array_elems_impl () const override
+ {
+ return new ArrayElemsCopied (*this);
+ }
+};
+
+// Array definition-ish expression
+class ArrayExpr : public ExprWithoutBlock
+{
+ AST::AttrVec inner_attrs;
+ std::unique_ptr internal_elements;
+
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ AST::AttrVec get_inner_attrs () const { return inner_attrs; }
+
+ // Returns whether array expr has array elems or if it is just empty.
+ bool has_array_elems () const { return internal_elements != nullptr; }
+
+ // Constructor requires ArrayElems pointer
+ ArrayExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr array_elems,
+ AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
+ Location locus)
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+ inner_attrs (std::move (inner_attribs)),
+ internal_elements (std::move (array_elems)), locus (locus)
+ {}
+
+ // Copy constructor requires cloning ArrayElems for polymorphism to hold
+ ArrayExpr (ArrayExpr const &other)
+ : ExprWithoutBlock (other), inner_attrs (other.inner_attrs),
+ locus (other.locus)
+ {
+ if (other.has_array_elems ())
+ internal_elements = other.internal_elements->clone_array_elems ();
+ }
+
+ // Overload assignment operator to clone internal_elements
+ ArrayExpr &operator= (ArrayExpr const &other)
+ {
+ ExprWithoutBlock::operator= (other);
+ inner_attrs = other.inner_attrs;
+ if (other.has_array_elems ())
+ internal_elements = other.internal_elements->clone_array_elems ();
+ locus = other.locus;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ ArrayExpr (ArrayExpr &&other) = default;
+ ArrayExpr &operator= (ArrayExpr &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ ArrayElems *get_internal_elements () { return internal_elements.get (); };
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Array;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ArrayExpr *clone_expr_impl () const override { return new ArrayExpr (*this); }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ArrayExpr *clone_expr_without_block_impl () const override
+ {
+ return new ArrayExpr (*this);
+ }
+};
+
+class ArrayIndexExpr : public ExprWithoutBlock
+{
+ std::unique_ptr array_expr;
+ std::unique_ptr index_expr;
+
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ ArrayIndexExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr array_expr,
+ std::unique_ptr array_index_expr,
+ AST::AttrVec outer_attribs, Location locus)
+ : ExprWithoutBlock (std::move (mappings), 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), array_expr (other.array_expr->clone_expr ()),
+ index_expr (other.index_expr->clone_expr ()), locus (other.locus)
+ {}
+
+ // Overload assignment operator to clone unique_ptrs
+ ArrayIndexExpr &operator= (ArrayIndexExpr const &other)
+ {
+ ExprWithoutBlock::operator= (other);
+ array_expr = other.array_expr->clone_expr ();
+ index_expr = other.index_expr->clone_expr ();
+ // outer_attrs = other.outer_attrs;
+ locus = other.locus;
+
+ return *this;
+ }
+
+ // move constructors
+ ArrayIndexExpr (ArrayIndexExpr &&other) = default;
+ ArrayIndexExpr &operator= (ArrayIndexExpr &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Expr *get_array_expr () { return array_expr.get (); }
+ Expr *get_index_expr () { return index_expr.get (); }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::ArrayIndex;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ArrayIndexExpr *clone_expr_impl () const override
+ {
+ return new ArrayIndexExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ArrayIndexExpr *clone_expr_without_block_impl () const override
+ {
+ return new ArrayIndexExpr (*this);
+ }
+};
+
+// HIR representation of a tuple
+class TupleExpr : public ExprWithoutBlock
+{
+ AST::AttrVec inner_attrs;
+
+ std::vector > tuple_elems;
+ // replaces (inlined version of) TupleElements
+
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ AST::AttrVec get_inner_attrs () const { return inner_attrs; }
+
+ TupleExpr (Analysis::NodeMapping mappings,
+ std::vector > tuple_elements,
+ AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
+ Location locus)
+ : ExprWithoutBlock (std::move (mappings), 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), inner_attrs (other.inner_attrs),
+ locus (other.locus)
+ {
+ 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);
+ inner_attrs = other.inner_attrs;
+ locus = other.locus;
+
+ 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 get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ const std::vector > &get_tuple_elems () const
+ {
+ return tuple_elems;
+ }
+ std::vector > &get_tuple_elems ()
+ {
+ return tuple_elems;
+ }
+
+ bool is_unit () const { return tuple_elems.size () == 0; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Tuple;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ TupleExpr *clone_expr_impl () const override { return new TupleExpr (*this); }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ TupleExpr *clone_expr_without_block_impl () const override
+ {
+ return new TupleExpr (*this);
+ }
+};
+
+class TupleIndexExpr : public ExprWithoutBlock
+{
+ std::unique_ptr tuple_expr;
+ TupleIndex tuple_index;
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ TupleIndex get_tuple_index () const { return tuple_index; }
+
+ TupleIndexExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr tuple_expr, TupleIndex index,
+ AST::AttrVec outer_attribs, Location locus)
+ : ExprWithoutBlock (std::move (mappings), 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), tuple_expr (other.tuple_expr->clone_expr ()),
+ tuple_index (other.tuple_index), locus (other.locus)
+ {}
+
+ // Overload assignment operator in order to clone
+ TupleIndexExpr &operator= (TupleIndexExpr const &other)
+ {
+ ExprWithoutBlock::operator= (other);
+ tuple_expr = other.tuple_expr->clone_expr ();
+ tuple_index = other.tuple_index;
+ locus = other.locus;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ TupleIndexExpr (TupleIndexExpr &&other) = default;
+ TupleIndexExpr &operator= (TupleIndexExpr &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_tuple_expr ()
+ {
+ rust_assert (tuple_expr != nullptr);
+ return tuple_expr;
+ }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::TupleIdx;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ TupleIndexExpr *clone_expr_impl () const override
+ {
+ return new TupleIndexExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ TupleIndexExpr *clone_expr_without_block_impl () const override
+ {
+ return new TupleIndexExpr (*this);
+ }
+};
+
+// Base struct/tuple/union value creator HIR node (abstract)
+class StructExpr : public ExprWithoutBlock
+{
+protected:
+ PathInExpression struct_name;
+
+ // Protected constructor to allow initialising struct_name
+ StructExpr (Analysis::NodeMapping mappings, PathInExpression struct_path,
+ AST::AttrVec outer_attribs)
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+ struct_name (std::move (struct_path))
+ {}
+
+public:
+ PathInExpression &get_struct_name () { return struct_name; }
+
+ std::string as_string () const override;
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Struct;
+ }
+};
+
+// Actual HIR node of the struct creator (with no fields). Not abstract!
+class StructExprStruct : public StructExpr
+{
+ AST::AttrVec inner_attrs;
+
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ AST::AttrVec get_inner_attrs () const { return inner_attrs; }
+
+ // Constructor has to call protected constructor of base class
+ StructExprStruct (Analysis::NodeMapping mappings,
+ PathInExpression struct_path, AST::AttrVec inner_attribs,
+ AST::AttrVec outer_attribs, Location locus)
+ : StructExpr (std::move (mappings), std::move (struct_path),
+ std::move (outer_attribs)),
+ inner_attrs (std::move (inner_attribs)), locus (locus)
+ {}
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ StructExprStruct *clone_expr_impl () const override
+ {
+ return new StructExprStruct (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ StructExprStruct *clone_expr_without_block_impl () const override
+ {
+ return new StructExprStruct (*this);
+ }
+};
+
+/* HIR node representing expression used to fill a struct's fields from another
+ * struct */
+struct StructBase
+{
+public:
+ std::unique_ptr base_struct;
+
+ // TODO: should this store location data?
+ StructBase (std::unique_ptr base_struct_ptr)
+ : base_struct (std::move (base_struct_ptr))
+ {}
+
+ // 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)
+ other.base_struct->clone_expr ();
+ }
+
+ // Destructor
+ ~StructBase () = default;
+
+ // Overload assignment operator to clone base_struct
+ StructBase &operator= (StructBase const &other)
+ {
+ base_struct = other.base_struct->clone_expr ();
+
+ 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); }
+
+ // Returns whether StructBase is in error state
+ bool is_invalid () const { return base_struct == nullptr; }
+
+ std::string as_string () const;
+
+ Expr *get_base () { return base_struct.get (); }
+};
+
+/* Base HIR node for a single struct expression field (in struct instance
+ * creation) - abstract */
+class StructExprField
+{
+public:
+ enum StructExprFieldKind
+ {
+ IDENTIFIER_VALUE,
+ IDENTIFIER,
+ INDEX_VALUE,
+ };
+
+ virtual ~StructExprField () {}
+
+ // Unique pointer custom clone function
+ std::unique_ptr clone_struct_expr_field () const
+ {
+ return std::unique_ptr (clone_struct_expr_field_impl ());
+ }
+
+ virtual std::string as_string () const = 0;
+
+ virtual void accept_vis (HIRFullVisitor &vis) = 0;
+ virtual void accept_vis (HIRExpressionVisitor &vis) = 0;
+
+ Analysis::NodeMapping &get_mappings () { return mappings; }
+
+ Location get_locus () { return locus; }
+
+ virtual StructExprFieldKind get_kind () const = 0;
+
+protected:
+ // pure virtual clone implementation
+ virtual StructExprField *clone_struct_expr_field_impl () const = 0;
+
+ StructExprField (Analysis::NodeMapping mapping, Location locus)
+ : mappings (mapping), locus (locus)
+ {}
+
+ Analysis::NodeMapping mappings;
+ Location locus;
+};
+
+// Identifier-only variant of StructExprField HIR node
+class StructExprFieldIdentifier : public StructExprField
+{
+private:
+ Identifier field_name;
+
+ // TODO: should this store location data?
+public:
+ StructExprFieldIdentifier (Analysis::NodeMapping mapping,
+ Identifier field_identifier, Location locus)
+ : StructExprField (mapping, locus),
+ field_name (std::move (field_identifier))
+ {}
+
+ std::string as_string () const override { return field_name; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Identifier get_field_name () const { return field_name; }
+
+ StructExprFieldKind get_kind () const override
+ {
+ return StructExprFieldKind::IDENTIFIER;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ StructExprFieldIdentifier *clone_struct_expr_field_impl () const override
+ {
+ return new StructExprFieldIdentifier (*this);
+ }
+};
+
+/* Base HIR node for a single struct expression field with an assigned value -
+ * abstract */
+class StructExprFieldWithVal : public StructExprField
+{
+ std::unique_ptr value;
+
+protected:
+ StructExprFieldWithVal (Analysis::NodeMapping mapping,
+ std::unique_ptr field_value, Location locus)
+ : StructExprField (mapping, locus), value (std::move (field_value))
+ {}
+
+ // Copy constructor requires clone
+ StructExprFieldWithVal (StructExprFieldWithVal const &other)
+ : StructExprField (other.mappings, other.locus),
+ value (other.value->clone_expr ())
+ {}
+
+ // Overload assignment operator to clone unique_ptr
+ StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other)
+ {
+ value = other.value->clone_expr ();
+ mappings = other.mappings;
+ locus = other.locus;
+
+ return *this;
+ }
+
+ // move constructors
+ StructExprFieldWithVal (StructExprFieldWithVal &&other) = default;
+ StructExprFieldWithVal &operator= (StructExprFieldWithVal &&other) = default;
+
+public:
+ std::string as_string () const override;
+
+ Expr *get_value () { return value.get (); }
+};
+
+// Identifier and value variant of StructExprField HIR node
+class StructExprFieldIdentifierValue : public StructExprFieldWithVal
+{
+public:
+ Identifier field_name;
+
+ // TODO: should this store location data?
+
+ StructExprFieldIdentifierValue (Analysis::NodeMapping mapping,
+ Identifier field_identifier,
+ std::unique_ptr field_value,
+ Location locus)
+ : StructExprFieldWithVal (mapping, std::move (field_value), locus),
+ field_name (std::move (field_identifier))
+ {}
+
+ std::string as_string () const override;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ StructExprFieldKind get_kind () const override
+ {
+ return StructExprFieldKind::IDENTIFIER_VALUE;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ StructExprFieldIdentifierValue *clone_struct_expr_field_impl () const override
+ {
+ return new StructExprFieldIdentifierValue (*this);
+ }
+};
+
+// Tuple index and value variant of StructExprField HIR node
+class StructExprFieldIndexValue : public StructExprFieldWithVal
+{
+public:
+ TupleIndex index;
+
+ // TODO: should this store location data?
+
+ StructExprFieldIndexValue (Analysis::NodeMapping mapping,
+ TupleIndex tuple_index,
+ std::unique_ptr field_value, Location locus)
+ : StructExprFieldWithVal (mapping, std::move (field_value), locus),
+ index (tuple_index)
+ {}
+
+ std::string as_string () const override;
+
+ TupleIndex get_tuple_index () const { return index; };
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ StructExprFieldKind get_kind () const override
+ {
+ return StructExprFieldKind::INDEX_VALUE;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ StructExprFieldIndexValue *clone_struct_expr_field_impl () const override
+ {
+ return new StructExprFieldIndexValue (*this);
+ }
+};
+
+// HIR node of a struct creator with fields
+class StructExprStructFields : public StructExprStruct
+{
+public:
+ // std::vector fields;
+ std::vector > fields;
+
+ // bool has_struct_base;
+ // FIXME make unique_ptr
+ StructBase *struct_base;
+
+ // For unions there is just one field, the index
+ // is set when type checking
+ int union_index = -1;
+
+ std::string as_string () const override;
+
+ bool has_struct_base () const { return struct_base != nullptr; }
+
+ // Constructor for StructExprStructFields when no struct base is used
+ StructExprStructFields (
+ Analysis::NodeMapping mappings, PathInExpression struct_path,
+ std::vector > expr_fields, Location locus,
+ StructBase *base_struct, AST::AttrVec inner_attribs = AST::AttrVec (),
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : StructExprStruct (std::move (mappings), std::move (struct_path),
+ std::move (inner_attribs), std::move (outer_attribs),
+ locus),
+ fields (std::move (expr_fields)), struct_base (base_struct)
+ {}
+
+ // copy constructor with vector clone
+ StructExprStructFields (StructExprStructFields const &other)
+ : StructExprStruct (other), struct_base (other.struct_base),
+ union_index (other.union_index)
+ {
+ 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;
+ union_index = other.union_index;
+
+ 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 (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::vector > &get_fields ()
+ {
+ return fields;
+ };
+
+ const std::vector > &get_fields () const
+ {
+ return fields;
+ };
+
+ void set_fields_as_owner (
+ std::vector > new_fields)
+ {
+ fields = std::move (new_fields);
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ StructExprStructFields *clone_expr_impl () const override
+ {
+ return new StructExprStructFields (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ StructExprStructFields *clone_expr_without_block_impl () const override
+ {
+ return new StructExprStructFields (*this);
+ }
+};
+
+// HIR node of the functional update struct creator
+class StructExprStructBase : public StructExprStruct
+{
+ StructBase struct_base;
+
+public:
+ std::string as_string () const override;
+
+ /*inline StructBase get_struct_base() const {
+ return struct_base;
+ }*/
+
+ StructExprStructBase (Analysis::NodeMapping mappings,
+ PathInExpression struct_path, StructBase base_struct,
+ AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
+ Location locus)
+ : StructExprStruct (std::move (mappings), std::move (struct_path),
+ std::move (inner_attribs), std::move (outer_attribs),
+ locus),
+ struct_base (std::move (base_struct))
+ {}
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ StructBase *get_struct_base () { return &struct_base; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ StructExprStructBase *clone_expr_impl () const override
+ {
+ return new StructExprStructBase (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ StructExprStructBase *clone_expr_without_block_impl () const override
+ {
+ return new StructExprStructBase (*this);
+ }
+};
+
+// Function call expression HIR node
+class CallExpr : public ExprWithoutBlock
+{
+ std::unique_ptr function;
+ std::vector > params;
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ CallExpr (Analysis::NodeMapping mappings, std::unique_ptr function_expr,
+ std::vector > function_params,
+ AST::AttrVec outer_attribs, Location locus)
+ : ExprWithoutBlock (std::move (mappings), 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), function (other.function->clone_expr ()),
+ locus (other.locus)
+ /*, params(other.params),*/ {
+ 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);
+ function = other.function->clone_expr ();
+ locus = other.locus;
+ // params = other.params;
+ // outer_attrs = other.outer_attrs;
+
+ 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 get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Expr *get_fnexpr () { return function.get (); }
+
+ size_t num_params () const { return params.size (); }
+
+ std::vector > &get_arguments () { return params; }
+
+ const std::vector > &get_arguments () const
+ {
+ return params;
+ }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Call;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ CallExpr *clone_expr_impl () const override { return new CallExpr (*this); }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ CallExpr *clone_expr_without_block_impl () const override
+ {
+ return new CallExpr (*this);
+ }
+};
+
+// Method call expression HIR node
+class MethodCallExpr : public ExprWithoutBlock
+{
+ std::unique_ptr receiver;
+ PathExprSegment method_name;
+ std::vector > params;
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ MethodCallExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr call_receiver,
+ PathExprSegment method_path,
+ std::vector > method_params,
+ AST::AttrVec outer_attribs, Location locus)
+ : ExprWithoutBlock (std::move (mappings), 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), receiver (other.receiver->clone_expr ()),
+ method_name (other.method_name), locus (other.locus)
+ /*, params(other.params),*/ {
+ 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);
+ receiver = other.receiver->clone_expr ();
+ method_name = other.method_name;
+ locus = other.locus;
+ // params = other.params;
+ // outer_attrs = other.outer_attrs;
+
+ 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 get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_receiver () { return receiver; }
+
+ PathExprSegment get_method_name () const { return method_name; };
+
+ size_t num_params () const { return params.size (); }
+
+ std::vector > &get_arguments () { return params; }
+
+ const std::vector > &get_arguments () const
+ {
+ return params;
+ }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::MethodCall;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ MethodCallExpr *clone_expr_impl () const override
+ {
+ return new MethodCallExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ MethodCallExpr *clone_expr_without_block_impl () const override
+ {
+ return new MethodCallExpr (*this);
+ }
+};
+
+// aka FieldExpression
+// Struct or union field access expression HIR node
+class FieldAccessExpr : public ExprWithoutBlock
+{
+ std::unique_ptr receiver;
+ Identifier field;
+
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ FieldAccessExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr field_access_receiver,
+ Identifier field_name, AST::AttrVec outer_attribs,
+ Location locus)
+ : ExprWithoutBlock (std::move (mappings), 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), receiver (other.receiver->clone_expr ()),
+ field (other.field), locus (other.locus)
+ {}
+
+ // Overload assignment operator to clone unique_ptr
+ FieldAccessExpr &operator= (FieldAccessExpr const &other)
+ {
+ ExprWithoutBlock::operator= (other);
+ receiver = other.receiver->clone_expr ();
+ field = other.field;
+ locus = other.locus;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ FieldAccessExpr (FieldAccessExpr &&other) = default;
+ FieldAccessExpr &operator= (FieldAccessExpr &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_receiver_expr ()
+ {
+ rust_assert (receiver != nullptr);
+ return receiver;
+ }
+
+ Identifier get_field_name () const { return field; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::FieldAccess;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ FieldAccessExpr *clone_expr_impl () const override
+ {
+ return new FieldAccessExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ FieldAccessExpr *clone_expr_without_block_impl () const override
+ {
+ return new FieldAccessExpr (*this);
+ }
+};
+
+// Closure parameter data structure
+struct ClosureParam
+{
+private:
+ std::unique_ptr pattern;
+
+ // bool has_type_given;
+ std::unique_ptr type;
+
+ // TODO: should this store location data?
+
+public:
+ // Returns whether the type of the parameter has been given.
+ bool has_type_given () const { return type != nullptr; }
+
+ // Constructor for closure parameter
+ ClosureParam (std::unique_ptr param_pattern,
+ std::unique_ptr param_type = nullptr)
+ : pattern (std::move (param_pattern)), type (std::move (param_type))
+ {}
+
+ // Copy constructor required due to cloning as a result of unique_ptrs
+ ClosureParam (ClosureParam const &other)
+ : pattern (other.pattern->clone_pattern ())
+ {
+ // guard to protect from null pointer dereference
+ 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)
+ {
+ pattern = other.pattern->clone_pattern ();
+ type = other.type->clone_type ();
+
+ 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); }
+
+ std::string as_string () const;
+};
+
+// Base closure definition expression HIR node - abstract
+class ClosureExpr : public ExprWithoutBlock
+{
+ bool has_move;
+ std::vector params;
+ Location locus;
+
+protected:
+ ClosureExpr (Analysis::NodeMapping mappings,
+ std::vector closure_params, bool has_move,
+ AST::AttrVec outer_attribs, Location locus)
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+ has_move (has_move), params (std::move (closure_params)), locus (locus)
+ {}
+
+public:
+ std::string as_string () const override;
+
+ Location get_locus () const override final { return locus; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Closure;
+ }
+};
+
+// Represents a non-type-specified closure expression HIR node
+class ClosureExprInner : public ClosureExpr
+{
+ std::unique_ptr closure_inner;
+
+public:
+ std::string as_string () const override;
+
+ // Constructor for a ClosureExprInner
+ ClosureExprInner (Analysis::NodeMapping mappings,
+ std::unique_ptr closure_inner_expr,
+ std::vector closure_params, Location locus,
+ bool is_move = false,
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : ClosureExpr (std::move (mappings), 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), closure_inner (other.closure_inner->clone_expr ())
+ {}
+
+ // Overload assignment operator to clone closure_inner
+ ClosureExprInner &operator= (ClosureExprInner const &other)
+ {
+ ClosureExpr::operator= (other);
+ closure_inner = other.closure_inner->clone_expr ();
+ // params = other.params;
+ // has_move = other.has_move;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ ClosureExprInner (ClosureExprInner &&other) = default;
+ ClosureExprInner &operator= (ClosureExprInner &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ClosureExprInner *clone_expr_impl () const override
+ {
+ return new ClosureExprInner (*this);
+ }
+
+ /* 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 HIR node
+class BlockExpr : public ExprWithBlock
+{
+public:
+ AST::AttrVec inner_attrs;
+ std::vector > statements;
+ std::unique_ptr expr;
+ bool tail_reachable;
+ Location start_locus;
+ Location end_locus;
+
+ std::string as_string () const override;
+
+ // Returns whether the block contains statements.
+ bool has_statements () const { return !statements.empty (); }
+
+ // Returns whether the block contains an expression
+ bool has_expr () const { return expr != nullptr; }
+
+ bool is_tail_reachable () const { return tail_reachable; }
+
+ BlockExpr (Analysis::NodeMapping mappings,
+ std::vector > block_statements,
+ std::unique_ptr block_expr, bool tail_reachable,
+ AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
+ Location start_locus, Location end_locus)
+ : ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
+ inner_attrs (std::move (inner_attribs)),
+ statements (std::move (block_statements)), expr (std::move (block_expr)),
+ tail_reachable (tail_reachable), start_locus (start_locus),
+ end_locus (end_locus)
+ {}
+
+ // Copy constructor with clone
+ BlockExpr (BlockExpr const &other)
+ : ExprWithBlock (other), /*statements(other.statements),*/
+ inner_attrs (other.inner_attrs), start_locus (other.start_locus),
+ end_locus (other.end_locus)
+ {
+ // 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);
+ // statements = other.statements;
+ expr = other.expr->clone_expr ();
+ inner_attrs = other.inner_attrs;
+ start_locus = other.end_locus;
+ end_locus = other.end_locus;
+ // outer_attrs = other.outer_attrs;
+
+ 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 clone_block_expr () const
+ {
+ return std::unique_ptr (clone_block_expr_impl ());
+ }
+
+ Location get_locus () const override final { return start_locus; }
+
+ Location get_start_locus () const { return start_locus; }
+
+ Location get_end_locus () const { return end_locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ bool is_final_stmt (Stmt *stmt) { return statements.back ().get () == stmt; }
+
+ std::unique_ptr &get_final_expr () { return expr; }
+
+ std::vector > &get_statements () { return statements; }
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Block;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ BlockExpr *clone_expr_impl () const override
+ {
+ return clone_block_expr_impl ();
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ BlockExpr *clone_expr_with_block_impl () const override
+ {
+ return clone_block_expr_impl ();
+ }
+
+ /* This is the base method as not an abstract class - not virtual but could be
+ * in future if required. */
+ /*virtual*/ BlockExpr *clone_block_expr_impl () const
+ {
+ return new BlockExpr (*this);
+ }
+};
+
+// Represents a type-specified closure expression HIR node
+class ClosureExprInnerTyped : public ClosureExpr
+{
+ std::unique_ptr return_type;
+ std::unique_ptr
+ expr; // only used because may be polymorphic in future
+
+public:
+ std::string as_string () const override;
+
+ // Constructor potentially with a move
+ ClosureExprInnerTyped (Analysis::NodeMapping mappings,
+ std::unique_ptr closure_return_type,
+ std::unique_ptr closure_expr,
+ std::vector closure_params,
+ Location locus, bool is_move = false,
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : ClosureExpr (std::move (mappings), 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), return_type (other.return_type->clone_type ()),
+ expr (other.expr->clone_block_expr ())
+ {}
+
+ // Overload assignment operator to clone unique_ptrs
+ ClosureExprInnerTyped &operator= (ClosureExprInnerTyped const &other)
+ {
+ ClosureExpr::operator= (other);
+ return_type = other.return_type->clone_type ();
+ expr = other.expr->clone_block_expr ();
+ // params = other.params;
+ // has_move = other.has_move;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ ClosureExprInnerTyped (ClosureExprInnerTyped &&other) = default;
+ ClosureExprInnerTyped &operator= (ClosureExprInnerTyped &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ClosureExprInnerTyped *clone_expr_impl () const override
+ {
+ return new ClosureExprInnerTyped (*this);
+ }
+
+ /* 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);
+ }
+};
+
+// HIR node representing continue expression within loops
+class ContinueExpr : public ExprWithoutBlock
+{
+ Lifetime label;
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ // Returns true if the continue expr has a label.
+ bool has_label () const { return !label.is_error (); }
+
+ // Constructor for a ContinueExpr with a label.
+ ContinueExpr (Analysis::NodeMapping mappings, Location locus, Lifetime label,
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+ label (std::move (label)), locus (locus)
+ {}
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Lifetime &get_label () { return label; }
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Continue;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ContinueExpr *clone_expr_impl () const override
+ {
+ return new ContinueExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ContinueExpr *clone_expr_without_block_impl () const override
+ {
+ return new ContinueExpr (*this);
+ }
+};
+
+// HIR node representing break expression within loops
+class BreakExpr : public ExprWithoutBlock
+{
+ // bool has_label;
+ Lifetime label;
+
+ // bool has_break_expr;
+ std::unique_ptr break_expr;
+
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ // Returns whether the break expression has a label or not.
+ bool has_label () const { return !label.is_error (); }
+
+ /* Returns whether the break expression has an expression used in the break or
+ * not. */
+ bool has_break_expr () const { return break_expr != nullptr; }
+
+ // Constructor for a break expression
+ BreakExpr (Analysis::NodeMapping mappings, Location locus,
+ Lifetime break_label,
+ std::unique_ptr expr_in_break = nullptr,
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : ExprWithoutBlock (std::move (mappings), 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), label (other.label), locus (other.locus)
+ {
+ // 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;
+ break_expr = other.break_expr->clone_expr ();
+ locus = other.locus;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ BreakExpr (BreakExpr &&other) = default;
+ BreakExpr &operator= (BreakExpr &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Lifetime &get_label () { return label; }
+
+ std::unique_ptr &get_expr () { return break_expr; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Break;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ BreakExpr *clone_expr_impl () const override { return new BreakExpr (*this); }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ BreakExpr *clone_expr_without_block_impl () const override
+ {
+ return new BreakExpr (*this);
+ }
+};
+
+// Base range expression HIR node object - abstract
+class RangeExpr : public ExprWithoutBlock
+{
+ Location locus;
+
+protected:
+ // outer attributes not allowed before range expressions
+ RangeExpr (Analysis::NodeMapping mappings, Location locus)
+ : ExprWithoutBlock (std::move (mappings), AST::AttrVec ()), locus (locus)
+ {}
+
+public:
+ Location get_locus () const override final { return locus; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Range;
+ }
+};
+
+// Range from (inclusive) and to (exclusive) expression HIR node object
+// aka RangeExpr; constructs a std::ops::Range object
+class RangeFromToExpr : public RangeExpr
+{
+ std::unique_ptr from;
+ std::unique_ptr to;
+
+public:
+ std::string as_string () const override;
+
+ RangeFromToExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr range_from,
+ std::unique_ptr range_to, Location locus)
+ : RangeExpr (std::move (mappings), locus), from (std::move (range_from)),
+ to (std::move (range_to))
+ {}
+
+ // Copy constructor with cloning
+ RangeFromToExpr (RangeFromToExpr const &other)
+ : RangeExpr (other), from (other.from->clone_expr ()),
+ to (other.to->clone_expr ())
+ {}
+
+ // Overload assignment operator to clone unique pointers
+ RangeFromToExpr &operator= (RangeFromToExpr const &other)
+ {
+ RangeExpr::operator= (other);
+ from = other.from->clone_expr ();
+ to = other.to->clone_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ RangeFromToExpr (RangeFromToExpr &&other) = default;
+ RangeFromToExpr &operator= (RangeFromToExpr &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_from_expr () { return from; }
+ std::unique_ptr &get_to_expr () { return to; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeFromToExpr *clone_expr_impl () const override
+ {
+ return new RangeFromToExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeFromToExpr *clone_expr_without_block_impl () const override
+ {
+ return new RangeFromToExpr (*this);
+ }
+};
+
+// Range from (inclusive) expression HIR node object
+// constructs a std::ops::RangeFrom object
+class RangeFromExpr : public RangeExpr
+{
+ std::unique_ptr from;
+
+public:
+ std::string as_string () const override;
+
+ RangeFromExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr range_from, Location locus)
+ : RangeExpr (std::move (mappings), locus), from (std::move (range_from))
+ {}
+
+ // Copy constructor with clone
+ RangeFromExpr (RangeFromExpr const &other)
+ : RangeExpr (other), from (other.from->clone_expr ())
+ {}
+
+ // Overload assignment operator to clone unique_ptr
+ RangeFromExpr &operator= (RangeFromExpr const &other)
+ {
+ RangeExpr::operator= (other);
+ from = other.from->clone_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ RangeFromExpr (RangeFromExpr &&other) = default;
+ RangeFromExpr &operator= (RangeFromExpr &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_from_expr () { return from; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeFromExpr *clone_expr_impl () const override
+ {
+ return new RangeFromExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeFromExpr *clone_expr_without_block_impl () const override
+ {
+ return new RangeFromExpr (*this);
+ }
+};
+
+// Range to (exclusive) expression HIR node object
+// constructs a std::ops::RangeTo object
+class RangeToExpr : public RangeExpr
+{
+ std::unique_ptr to;
+
+public:
+ std::string as_string () const override;
+
+ // outer attributes not allowed
+ RangeToExpr (Analysis::NodeMapping mappings, std::unique_ptr range_to,
+ Location locus)
+ : RangeExpr (std::move (mappings), locus), to (std::move (range_to))
+ {}
+
+ // Copy constructor with clone
+ RangeToExpr (RangeToExpr const &other)
+ : RangeExpr (other), to (other.to->clone_expr ())
+ {}
+
+ // Overload assignment operator to clone unique_ptr
+ RangeToExpr &operator= (RangeToExpr const &other)
+ {
+ RangeExpr::operator= (other);
+ to = other.to->clone_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ RangeToExpr (RangeToExpr &&other) = default;
+ RangeToExpr &operator= (RangeToExpr &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_to_expr () { return to; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeToExpr *clone_expr_impl () const override
+ {
+ return new RangeToExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeToExpr *clone_expr_without_block_impl () const override
+ {
+ return new RangeToExpr (*this);
+ }
+};
+
+// Full range expression HIR node object
+// constructs a std::ops::RangeFull object
+class RangeFullExpr : public RangeExpr
+{
+public:
+ std::string as_string () const override;
+
+ RangeFullExpr (Analysis::NodeMapping mappings, Location locus)
+ : RangeExpr (std::move (mappings), locus)
+ {}
+ // outer attributes not allowed
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeFullExpr *clone_expr_impl () const override
+ {
+ return new RangeFullExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeFullExpr *clone_expr_without_block_impl () const override
+ {
+ return new RangeFullExpr (*this);
+ }
+};
+
+// Range from (inclusive) and to (inclusive) expression HIR node object
+// aka RangeInclusiveExpr; constructs a std::ops::RangeInclusive object
+class RangeFromToInclExpr : public RangeExpr
+{
+ std::unique_ptr from;
+ std::unique_ptr to;
+
+public:
+ std::string as_string () const override;
+
+ RangeFromToInclExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr range_from,
+ std::unique_ptr range_to, Location locus)
+ : RangeExpr (std::move (mappings), 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), from (other.from->clone_expr ()),
+ to (other.to->clone_expr ())
+ {}
+
+ // Overload assignment operator to use clone
+ RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other)
+ {
+ RangeExpr::operator= (other);
+ from = other.from->clone_expr ();
+ to = other.to->clone_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ RangeFromToInclExpr (RangeFromToInclExpr &&other) = default;
+ RangeFromToInclExpr &operator= (RangeFromToInclExpr &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_from_expr () { return from; }
+ std::unique_ptr &get_to_expr () { return to; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeFromToInclExpr *clone_expr_impl () const override
+ {
+ return new RangeFromToInclExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeFromToInclExpr *clone_expr_without_block_impl () const override
+ {
+ return new RangeFromToInclExpr (*this);
+ }
+};
+
+// Range to (inclusive) expression HIR node object
+// aka RangeToInclusiveExpr; constructs a std::ops::RangeToInclusive object
+class RangeToInclExpr : public RangeExpr
+{
+ std::unique_ptr to;
+
+public:
+ std::string as_string () const override;
+
+ RangeToInclExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr range_to, Location locus)
+ : RangeExpr (std::move (mappings), locus), to (std::move (range_to))
+ {}
+ // outer attributes not allowed
+
+ // Copy constructor with clone
+ RangeToInclExpr (RangeToInclExpr const &other)
+ : RangeExpr (other), to (other.to->clone_expr ())
+ {}
+
+ // Overload assignment operator to clone pointer
+ RangeToInclExpr &operator= (RangeToInclExpr const &other)
+ {
+ RangeExpr::operator= (other);
+ to = other.to->clone_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ RangeToInclExpr (RangeToInclExpr &&other) = default;
+ RangeToInclExpr &operator= (RangeToInclExpr &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_to_expr () { return to; };
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeToInclExpr *clone_expr_impl () const override
+ {
+ return new RangeToInclExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ RangeToInclExpr *clone_expr_without_block_impl () const override
+ {
+ return new RangeToInclExpr (*this);
+ }
+};
+
+// Return expression HIR node representation
+class ReturnExpr : public ExprWithoutBlock
+{
+public:
+ std::unique_ptr return_expr;
+
+ Location locus;
+
+ std::string as_string () const override;
+
+ /* Returns whether the object has an expression returned (i.e. not void return
+ * type). */
+ bool has_return_expr () const { return return_expr != nullptr; }
+
+ // Constructor for ReturnExpr.
+ ReturnExpr (Analysis::NodeMapping mappings, Location locus,
+ std::unique_ptr returned_expr = nullptr,
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+ return_expr (std::move (returned_expr)), locus (locus)
+ {}
+
+ // Copy constructor with clone
+ ReturnExpr (ReturnExpr const &other)
+ : ExprWithoutBlock (other), locus (other.locus)
+ {
+ // 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);
+ return_expr = other.return_expr->clone_expr ();
+ locus = other.locus;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ ReturnExpr (ReturnExpr &&other) = default;
+ ReturnExpr &operator= (ReturnExpr &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Expr *get_expr () { return return_expr.get (); }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::Return;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ReturnExpr *clone_expr_impl () const override
+ {
+ return new ReturnExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ReturnExpr *clone_expr_without_block_impl () const override
+ {
+ return new ReturnExpr (*this);
+ }
+};
+
+// An unsafe block HIR node
+class UnsafeBlockExpr : public ExprWithBlock
+{
+ // Or just have it extend BlockExpr
+ std::unique_ptr expr;
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ UnsafeBlockExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr block_expr,
+ AST::AttrVec outer_attribs, Location locus)
+ : ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
+ expr (std::move (block_expr)), locus (locus)
+ {}
+
+ // Copy constructor with clone
+ UnsafeBlockExpr (UnsafeBlockExpr const &other)
+ : ExprWithBlock (other), expr (other.expr->clone_block_expr ()),
+ locus (other.locus)
+ {}
+
+ // Overloaded assignment operator to clone
+ UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other)
+ {
+ ExprWithBlock::operator= (other);
+ expr = other.expr->clone_block_expr ();
+ locus = other.locus;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ UnsafeBlockExpr (UnsafeBlockExpr &&other) = default;
+ UnsafeBlockExpr &operator= (UnsafeBlockExpr &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_block_expr () { return expr; }
+
+ ExprType get_expression_type () const override final
+ {
+ return ExprType::UnsafeBlock;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ UnsafeBlockExpr *clone_expr_impl () const override
+ {
+ return new UnsafeBlockExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ UnsafeBlockExpr *clone_expr_with_block_impl () const override
+ {
+ return new UnsafeBlockExpr (*this);
+ }
+};
+
+// Loop label expression HIR node used with break and continue expressions
+// TODO: inline?
+class LoopLabel /*: public Node*/
+{
+ Lifetime label; // or type LIFETIME_OR_LABEL
+
+ Location locus;
+
+ Analysis::NodeMapping mappings;
+
+public:
+ std::string as_string () const;
+
+ LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label, Location locus)
+ : label (std::move (loop_label)), locus (locus), mappings (mapping)
+ {}
+
+ // Returns whether the LoopLabel is in an error state.
+ bool is_error () const { return label.is_error (); }
+
+ Location get_locus () const { return locus; }
+
+ Analysis::NodeMapping &get_mappings () { return mappings; }
+
+ Lifetime &get_lifetime () { return label; }
+};
+
+// Base loop expression HIR node - aka LoopExpr
+class BaseLoopExpr : public ExprWithBlock
+{
+protected:
+ LoopLabel loop_label;
+ std::unique_ptr loop_block;
+
+private:
+ Location locus;
+
+protected:
+ // Constructor for BaseLoopExpr
+ BaseLoopExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr loop_block, Location locus,
+ LoopLabel loop_label,
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : ExprWithBlock (std::move (mappings), 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), loop_label (other.loop_label),
+ loop_block (other.loop_block->clone_block_expr ()), locus (other.locus)
+ {}
+
+ // Overloaded assignment operator to clone
+ BaseLoopExpr &operator= (BaseLoopExpr const &other)
+ {
+ ExprWithBlock::operator= (other);
+ loop_block = other.loop_block->clone_block_expr ();
+ loop_label = other.loop_label;
+ locus = other.locus;
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ BaseLoopExpr (BaseLoopExpr &&other) = default;
+ BaseLoopExpr &operator= (BaseLoopExpr &&other) = default;
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::BaseLoop;
+ }
+
+public:
+ bool has_loop_label () const { return !loop_label.is_error (); }
+
+ Location get_locus () const override final { return locus; }
+
+ std::unique_ptr &get_loop_block () { return loop_block; };
+
+ LoopLabel &get_loop_label () { return loop_label; }
+};
+
+// 'Loop' expression (i.e. the infinite loop) HIR node
+class LoopExpr : public BaseLoopExpr
+{
+public:
+ std::string as_string () const override;
+
+ // Constructor for LoopExpr
+ LoopExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr loop_block, Location locus,
+ LoopLabel loop_label, AST::AttrVec outer_attribs = AST::AttrVec ())
+ : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
+ std::move (loop_label), std::move (outer_attribs))
+ {}
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ LoopExpr *clone_expr_impl () const override { return new LoopExpr (*this); }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ LoopExpr *clone_expr_with_block_impl () const override
+ {
+ return new LoopExpr (*this);
+ }
+};
+
+// While loop expression HIR node (predicate loop)
+class WhileLoopExpr : public BaseLoopExpr
+{
+ std::unique_ptr condition;
+
+public:
+ std::string as_string () const override;
+
+ // Constructor for while loop with loop label
+ WhileLoopExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr loop_condition,
+ std::unique_ptr loop_block, Location locus,
+ LoopLabel loop_label,
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : BaseLoopExpr (std::move (mappings), 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 (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_predicate_expr () { return condition; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ WhileLoopExpr *clone_expr_impl () const override
+ {
+ return new WhileLoopExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ WhileLoopExpr *clone_expr_with_block_impl () const override
+ {
+ return new WhileLoopExpr (*this);
+ }
+};
+
+// While let loop expression HIR node (predicate pattern loop)
+class WhileLetLoopExpr : public BaseLoopExpr
+{
+ // MatchArmPatterns patterns;
+ std::vector > match_arm_patterns; // inlined
+ std::unique_ptr condition;
+
+public:
+ std::string as_string () const override;
+
+ // Constructor with a loop label
+ WhileLetLoopExpr (Analysis::NodeMapping mappings,
+ std::vector > match_arm_patterns,
+ std::unique_ptr condition,
+ std::unique_ptr loop_block, Location locus,
+ LoopLabel loop_label,
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
+ std::move (loop_label), std::move (outer_attribs)),
+ match_arm_patterns (std::move (match_arm_patterns)),
+ condition (std::move (condition))
+ {}
+
+ // Copy constructor with clone
+ WhileLetLoopExpr (WhileLetLoopExpr const &other)
+ : BaseLoopExpr (other),
+ /*match_arm_patterns(other.match_arm_patterns),*/ condition (
+ other.condition->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;
+ condition = other.condition->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 (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_cond () { return condition; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ WhileLetLoopExpr *clone_expr_impl () const override
+ {
+ return new WhileLetLoopExpr (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ WhileLetLoopExpr *clone_expr_with_block_impl () const override
+ {
+ return new WhileLetLoopExpr (*this);
+ }
+};
+
+// For loop expression HIR node (iterator loop)
+class ForLoopExpr : public BaseLoopExpr
+{
+ std::unique_ptr pattern;
+ std::unique_ptr iterator_expr;
+
+public:
+ std::string as_string () const override;
+
+ // Constructor with loop label
+ ForLoopExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr loop_pattern,
+ std::unique_ptr iterator_expr,
+ std::unique_ptr loop_body, Location locus,
+ LoopLabel loop_label,
+ AST::AttrVec outer_attribs = AST::AttrVec ())
+ : BaseLoopExpr (std::move (mappings), 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 (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_iterator_expr () { return iterator_expr; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ ForLoopExpr *clone_expr_impl () const override
+ {
+ return new ForLoopExpr (*this);
+ }
+
+ /* 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" HIR node
+class IfExpr : public ExprWithBlock
+{
+ std::unique_ptr condition;
+ std::unique_ptr if_block;
+
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ IfExpr (Analysis::NodeMapping mappings, std::unique_ptr condition,
+ std::unique_ptr if_block, Location locus)
+ : ExprWithBlock (std::move (mappings), AST::AttrVec ()),
+ 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), condition (other.condition->clone_expr ()),
+ if_block (other.if_block->clone_block_expr ()), locus (other.locus)
+ {}
+
+ // Overloaded assignment operator to clone expressions
+ IfExpr &operator= (IfExpr const &other)
+ {
+ ExprWithBlock::operator= (other);
+ condition = other.condition->clone_expr ();
+ if_block = other.if_block->clone_block_expr ();
+ locus = other.locus;
+
+ return *this;
+ }
+
+ // move constructors
+ IfExpr (IfExpr &&other) = default;
+ IfExpr &operator= (IfExpr &&other) = default;
+
+ // Unique pointer custom clone function
+ std::unique_ptr clone_if_expr () const
+ {
+ return std::unique_ptr (clone_if_expr_impl ());
+ }
+
+ /* Note that multiple "else if"s are handled via nested HIRs rather than a
+ * vector of else ifs - i.e. not like a switch statement. TODO - is this a
+ * better approach? or does it not parse correctly and have downsides? */
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ void vis_if_condition (HIRFullVisitor &vis) { condition->accept_vis (vis); }
+ void vis_if_block (HIRFullVisitor &vis) { if_block->accept_vis (vis); }
+
+ Expr *get_if_condition () { return condition.get (); }
+ BlockExpr *get_if_block () { return if_block.get (); }
+
+ ExprType get_expression_type () const final override { return ExprType::If; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExpr *clone_expr_impl () const override { return new IfExpr (*this); }
+
+ // Base clone function but still concrete as concrete base class
+ virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExpr *clone_expr_with_block_impl () const override
+ {
+ return new IfExpr (*this);
+ }
+};
+
+// If expression with an ending "else" expression HIR node (trailing)
+class IfExprConseqElse : public IfExpr
+{
+ std::unique_ptr else_block;
+
+public:
+ std::string as_string () const override;
+
+ IfExprConseqElse (Analysis::NodeMapping mappings,
+ std::unique_ptr condition,
+ std::unique_ptr if_block,
+ std::unique_ptr else_block, Location locus)
+ : IfExpr (std::move (mappings), std::move (condition), std::move (if_block),
+ 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_block_expr ())
+ {}
+
+ // 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_block_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ IfExprConseqElse (IfExprConseqElse &&other) = default;
+ IfExprConseqElse &operator= (IfExprConseqElse &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ void vis_else_block (HIRFullVisitor &vis) { else_block->accept_vis (vis); }
+
+ BlockExpr *get_else_block () { return else_block.get (); }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExprConseqElse *clone_expr_impl () const override
+ {
+ return new IfExprConseqElse (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExprConseqElse *clone_expr_with_block_impl () const override
+ {
+ return new IfExprConseqElse (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExprConseqElse *clone_if_expr_impl () const override
+ {
+ return new IfExprConseqElse (*this);
+ }
+};
+
+// If expression with an ending "else if" expression HIR node
+class IfExprConseqIf : public IfExpr
+{
+ std::unique_ptr conseq_if_expr;
+
+public:
+ std::string as_string () const override;
+
+ IfExprConseqIf (Analysis::NodeMapping mappings,
+ std::unique_ptr condition,
+ std::unique_ptr if_block,
+ std::unique_ptr conseq_if_expr, Location locus)
+ : IfExpr (std::move (mappings), std::move (condition), std::move (if_block),
+ locus),
+ conseq_if_expr (std::move (conseq_if_expr))
+ {}
+ // outer attributes not allowed
+
+ // Copy constructor with clone
+ IfExprConseqIf (IfExprConseqIf const &other)
+ : IfExpr (other), conseq_if_expr (other.conseq_if_expr->clone_if_expr ())
+ {}
+
+ // Overloaded assignment operator to use clone
+ IfExprConseqIf &operator= (IfExprConseqIf const &other)
+ {
+ IfExpr::operator= (other);
+ // condition = other.condition->clone_expr();
+ // if_block = other.if_block->clone_block_expr();
+ conseq_if_expr = other.conseq_if_expr->clone_if_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ IfExprConseqIf (IfExprConseqIf &&other) = default;
+ IfExprConseqIf &operator= (IfExprConseqIf &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ void vis_conseq_if_expr (HIRFullVisitor &vis)
+ {
+ conseq_if_expr->accept_vis (vis);
+ }
+
+ IfExpr *get_conseq_if_expr () { return conseq_if_expr.get (); }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExprConseqIf *clone_expr_impl () const override
+ {
+ return new IfExprConseqIf (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExprConseqIf *clone_expr_with_block_impl () const override
+ {
+ return new IfExprConseqIf (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExprConseqIf *clone_if_expr_impl () const override
+ {
+ return new IfExprConseqIf (*this);
+ }
+};
+
+// Basic "if let" expression HIR node with no else
+class IfLetExpr : public ExprWithBlock
+{
+ // MatchArmPatterns patterns;
+ std::vector > match_arm_patterns; // inlined
+ std::unique_ptr value;
+ std::unique_ptr if_block;
+
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ IfLetExpr (Analysis::NodeMapping mappings,
+ std::vector > match_arm_patterns,
+ std::unique_ptr value, std::unique_ptr if_block,
+ Location locus)
+ : ExprWithBlock (std::move (mappings), AST::AttrVec ()),
+ match_arm_patterns (std::move (match_arm_patterns)),
+ value (std::move (value)), if_block (std::move (if_block)), locus (locus)
+ {}
+ // outer attributes not allowed on if let exprs either
+
+ // copy constructor with clone
+ IfLetExpr (IfLetExpr const &other)
+ : ExprWithBlock (other),
+ /*match_arm_patterns(other.match_arm_patterns),*/ value (
+ other.value->clone_expr ()),
+ if_block (other.if_block->clone_block_expr ()), locus (other.locus)
+ {
+ 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);
+ // match_arm_patterns = other.match_arm_patterns;
+ value = other.value->clone_expr ();
+ if_block = other.if_block->clone_block_expr ();
+ locus = other.locus;
+
+ 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 clone_if_let_expr () const
+ {
+ return std::unique_ptr (clone_if_let_expr_impl ());
+ }
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_scrutinee_expr ()
+ {
+ rust_assert (value != nullptr);
+ return value;
+ }
+
+ std::vector > &get_patterns ()
+ {
+ return match_arm_patterns;
+ }
+
+ BlockExpr *get_if_block () { return if_block.get (); }
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::IfLet;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExpr *clone_expr_impl () const override { return new IfLetExpr (*this); }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExpr *clone_expr_with_block_impl () const override
+ {
+ return new IfLetExpr (*this);
+ }
+
+ // Base clone function but still concrete as concrete base class
+ virtual IfLetExpr *clone_if_let_expr_impl () const
+ {
+ return new IfLetExpr (*this);
+ }
+};
+
+// If expression with an ending "else if let" expression HIR node
+class IfExprConseqIfLet : public IfExpr
+{
+ std::unique_ptr if_let_expr;
+
+public:
+ std::string as_string () const override;
+
+ IfExprConseqIfLet (Analysis::NodeMapping mappings,
+ std::unique_ptr condition,
+ std::unique_ptr if_block,
+ std::unique_ptr conseq_if_let_expr,
+ Location locus)
+ : IfExpr (std::move (mappings), std::move (condition), std::move (if_block),
+ locus),
+ if_let_expr (std::move (conseq_if_let_expr))
+ {}
+ // outer attributes not allowed
+
+ // Copy constructor with clone
+ IfExprConseqIfLet (IfExprConseqIfLet const &other)
+ : IfExpr (other), if_let_expr (other.if_let_expr->clone_if_let_expr ())
+ {}
+
+ // Overloaded assignment operator to use clone
+ IfExprConseqIfLet &operator= (IfExprConseqIfLet const &other)
+ {
+ IfExpr::operator= (other);
+ // condition = other.condition->clone_expr();
+ // if_block = other.if_block->clone_block_expr();
+ if_let_expr = other.if_let_expr->clone_if_let_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ IfExprConseqIfLet (IfExprConseqIfLet &&other) = default;
+ IfExprConseqIfLet &operator= (IfExprConseqIfLet &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExprConseqIfLet *clone_expr_impl () const override
+ {
+ return new IfExprConseqIfLet (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExprConseqIfLet *clone_expr_with_block_impl () const override
+ {
+ return new IfExprConseqIfLet (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfExprConseqIfLet *clone_if_expr_impl () const override
+ {
+ return new IfExprConseqIfLet (*this);
+ }
+};
+
+/* HIR node representing "if let" expression with an "else" expression at the
+ * end */
+class IfLetExprConseqElse : public IfLetExpr
+{
+ std::unique_ptr else_block;
+
+public:
+ std::string as_string () const override;
+
+ IfLetExprConseqElse (
+ Analysis::NodeMapping mappings,
+ std::vector > match_arm_patterns,
+ std::unique_ptr value, std::unique_ptr if_block,
+ std::unique_ptr else_block, Location locus)
+ : IfLetExpr (std::move (mappings), std::move (match_arm_patterns),
+ std::move (value), std::move (if_block), 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_block_expr ())
+ {}
+
+ // 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_block_expr ();
+ // outer_attrs = other.outer_attrs;
+
+ return *this;
+ }
+
+ // move constructors
+ IfLetExprConseqElse (IfLetExprConseqElse &&other) = default;
+ IfLetExprConseqElse &operator= (IfLetExprConseqElse &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExprConseqElse *clone_expr_impl () const override
+ {
+ return new IfLetExprConseqElse (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExprConseqElse *clone_expr_with_block_impl () const override
+ {
+ return new IfLetExprConseqElse (*this);
+ }
+
+ /* 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);
+ }
+};
+
+/* HIR node representing "if let" expression with an "else if" expression at the
+ * end */
+class IfLetExprConseqIf : public IfLetExpr
+{
+ std::unique_ptr if_expr;
+
+public:
+ std::string as_string () const override;
+
+ IfLetExprConseqIf (Analysis::NodeMapping mappings,
+ std::vector > match_arm_patterns,
+ std::unique_ptr value,
+ std::unique_ptr if_block,
+ std::unique_ptr if_expr, Location locus)
+ : IfLetExpr (std::move (mappings), std::move (match_arm_patterns),
+ std::move (value), std::move (if_block), locus),
+ if_expr (std::move (if_expr))
+ {}
+ // again, outer attributes not allowed
+
+ // copy constructor with clone
+ IfLetExprConseqIf (IfLetExprConseqIf const &other)
+ : IfLetExpr (other), if_expr (other.if_expr->clone_if_expr ())
+ {}
+
+ // overload assignment operator to clone
+ IfLetExprConseqIf &operator= (IfLetExprConseqIf 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();
+ if_expr = other.if_expr->clone_if_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ IfLetExprConseqIf (IfLetExprConseqIf &&other) = default;
+ IfLetExprConseqIf &operator= (IfLetExprConseqIf &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExprConseqIf *clone_expr_impl () const override
+ {
+ return new IfLetExprConseqIf (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExprConseqIf *clone_expr_with_block_impl () const override
+ {
+ return new IfLetExprConseqIf (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExprConseqIf *clone_if_let_expr_impl () const override
+ {
+ return new IfLetExprConseqIf (*this);
+ }
+};
+
+/* HIR node representing "if let" expression with an "else if let" expression at
+ * the end */
+class IfLetExprConseqIfLet : public IfLetExpr
+{
+ std::unique_ptr if_let_expr;
+
+public:
+ std::string as_string () const override;
+
+ IfLetExprConseqIfLet (
+ Analysis::NodeMapping mappings,
+ std::vector > match_arm_patterns,
+ std::unique_ptr value, std::unique_ptr if_block,
+ std::unique_ptr if_let_expr, Location locus)
+ : IfLetExpr (std::move (mappings), std::move (match_arm_patterns),
+ std::move (value), std::move (if_block), locus),
+ if_let_expr (std::move (if_let_expr))
+ {}
+ // outer attributes not allowed
+
+ // copy constructor with clone
+ IfLetExprConseqIfLet (IfLetExprConseqIfLet const &other)
+ : IfLetExpr (other), if_let_expr (other.if_let_expr->clone_if_let_expr ())
+ {}
+
+ // overload assignment operator to clone
+ IfLetExprConseqIfLet &operator= (IfLetExprConseqIfLet 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();
+ if_let_expr = other.if_let_expr->clone_if_let_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ IfLetExprConseqIfLet (IfLetExprConseqIfLet &&other) = default;
+ IfLetExprConseqIfLet &operator= (IfLetExprConseqIfLet &&other) = default;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExprConseqIfLet *clone_expr_impl () const override
+ {
+ return new IfLetExprConseqIfLet (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExprConseqIfLet *clone_expr_with_block_impl () const override
+ {
+ return new IfLetExprConseqIfLet (*this);
+ }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ IfLetExprConseqIfLet *clone_if_let_expr_impl () const override
+ {
+ return new IfLetExprConseqIfLet (*this);
+ }
+};
+
+// Match arm expression
+struct MatchArm
+{
+private:
+ AST::AttrVec outer_attrs;
+ std::vector > match_arm_patterns;
+ std::unique_ptr guard_expr;
+ Location 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 > match_arm_patterns,
+ Location locus, std::unique_ptr guard_expr = nullptr,
+ AST::AttrVec outer_attrs = AST::AttrVec ())
+ : 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 ();
+
+ match_arm_patterns.clear ();
+ 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 locus = Location ();
+ return MatchArm (std::vector > (), locus);
+ }
+
+ std::string as_string () const;
+
+ std::vector > &get_patterns ()
+ {
+ return match_arm_patterns;
+ }
+
+ std::unique_ptr &get_guard_expr ()
+ {
+ rust_assert (has_match_arm_guard ());
+ return guard_expr;
+ }
+
+ Location get_locus () const { return locus; }
+};
+
+/* A "match case" - a correlated match arm and resulting expression. Not
+ * abstract. */
+struct MatchCase
+{
+private:
+ Analysis::NodeMapping mappings;
+ MatchArm arm;
+ std::unique_ptr expr;
+
+public:
+ MatchCase (Analysis::NodeMapping mappings, MatchArm arm,
+ std::unique_ptr expr)
+ : mappings (mappings), arm (std::move (arm)), expr (std::move (expr))
+ {}
+
+ MatchCase (const MatchCase &other)
+ : mappings (other.mappings), arm (other.arm),
+ expr (other.expr->clone_expr ())
+ {}
+
+ MatchCase &operator= (const MatchCase &other)
+ {
+ mappings = other.mappings;
+ arm = other.arm;
+ expr = other.expr->clone_expr ();
+
+ return *this;
+ }
+
+ MatchCase (MatchCase &&other) = default;
+ MatchCase &operator= (MatchCase &&other) = default;
+
+ ~MatchCase () = default;
+
+ std::string as_string () const;
+
+ Analysis::NodeMapping get_mappings () const { return mappings; }
+
+ MatchArm &get_arm () { return arm; }
+ std::unique_ptr &get_expr () { return expr; }
+};
+
+// Match expression HIR node
+class MatchExpr : public ExprWithBlock
+{
+ std::unique_ptr branch_value;
+ AST::AttrVec inner_attrs;
+ std::vector match_arms;
+ Location locus;
+
+public:
+ std::string as_string () const override;
+
+ bool has_match_arms () const { return !match_arms.empty (); }
+
+ MatchExpr (Analysis::NodeMapping mappings, std::unique_ptr branch_value,
+ std::vector match_arms, AST::AttrVec inner_attrs,
+ AST::AttrVec outer_attrs, Location locus)
+ : ExprWithBlock (std::move (mappings), 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), branch_value (other.branch_value->clone_expr ()),
+ inner_attrs (other.inner_attrs), match_arms (other.match_arms),
+ locus (other.locus)
+ {
+ /*match_arms.reserve (other.match_arms.size ());
+ for (const auto &e : other.match_arms)
+ match_arms.push_back (e->clone_match_case ());*/
+ }
+
+ // Overloaded assignment operator to clone due to unique_ptr
+ MatchExpr &operator= (MatchExpr const &other)
+ {
+ ExprWithBlock::operator= (other);
+ branch_value = other.branch_value->clone_expr ();
+ inner_attrs = other.inner_attrs;
+ match_arms = other.match_arms;
+ // outer_attrs = other.outer_attrs;
+ locus = other.locus;
+
+ /*match_arms.reserve (other.match_arms.size ());
+ for (const auto &e : other.match_arms)
+ match_arms.push_back (e->clone_match_case ());*/
+
+ return *this;
+ }
+
+ // move constructors
+ MatchExpr (MatchExpr &&other) = default;
+ MatchExpr &operator= (MatchExpr &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::unique_ptr &get_scrutinee_expr ()
+ {
+ rust_assert (branch_value != nullptr);
+ return branch_value;
+ }
+
+ const std::vector &get_match_cases () const { return match_arms; }
+ std::vector &get_match_cases () { return match_arms; }
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Match;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ MatchExpr *clone_expr_impl () const override { return new MatchExpr (*this); }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ MatchExpr *clone_expr_with_block_impl () const override
+ {
+ return new MatchExpr (*this);
+ }
+};
+
+// Await expression HIR node (pseudo-member variable access)
+class AwaitExpr : public ExprWithoutBlock
+{
+ std::unique_ptr awaited_expr;
+ Location locus;
+
+public:
+ // TODO: ensure outer attributes are actually allowed
+ AwaitExpr (Analysis::NodeMapping mappings, std::unique_ptr awaited_expr,
+ AST::AttrVec outer_attrs, Location locus)
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)),
+ awaited_expr (std::move (awaited_expr)), locus (locus)
+ {}
+
+ // copy constructor with clone
+ AwaitExpr (AwaitExpr const &other)
+ : ExprWithoutBlock (other),
+ awaited_expr (other.awaited_expr->clone_expr ()), locus (other.locus)
+ {}
+
+ // overloaded assignment operator with clone
+ AwaitExpr &operator= (AwaitExpr const &other)
+ {
+ ExprWithoutBlock::operator= (other);
+ awaited_expr = other.awaited_expr->clone_expr ();
+ locus = other.locus;
+
+ return *this;
+ }
+
+ // move constructors
+ AwaitExpr (AwaitExpr &&other) = default;
+ AwaitExpr &operator= (AwaitExpr &&other) = default;
+
+ std::string as_string () const override;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::Await;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ AwaitExpr *clone_expr_without_block_impl () const override
+ {
+ return new AwaitExpr (*this);
+ }
+};
+
+// Async block expression HIR node (block expr that evaluates to a future)
+class AsyncBlockExpr : public ExprWithBlock
+{
+ bool has_move;
+ std::unique_ptr block_expr;
+ Location locus;
+
+public:
+ AsyncBlockExpr (Analysis::NodeMapping mappings,
+ std::unique_ptr block_expr, bool has_move,
+ AST::AttrVec outer_attrs, Location locus)
+ : ExprWithBlock (std::move (mappings), 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), has_move (other.has_move),
+ block_expr (other.block_expr->clone_block_expr ()), locus (other.locus)
+ {}
+
+ // overloaded assignment operator to clone
+ AsyncBlockExpr &operator= (AsyncBlockExpr const &other)
+ {
+ ExprWithBlock::operator= (other);
+ has_move = other.has_move;
+ block_expr = other.block_expr->clone_block_expr ();
+ locus = other.locus;
+
+ return *this;
+ }
+
+ // move constructors
+ AsyncBlockExpr (AsyncBlockExpr &&other) = default;
+ AsyncBlockExpr &operator= (AsyncBlockExpr &&other) = default;
+
+ std::string as_string () const override;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::AsyncBlock;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ AsyncBlockExpr *clone_expr_with_block_impl () const override
+ {
+ return new AsyncBlockExpr (*this);
+ }
+};
+
+// this is a utility helper class for type-checking and code-generation
+class OperatorExprMeta
+{
+public:
+ OperatorExprMeta (HIR::CompoundAssignmentExpr &expr)
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
+ {}
+
+ OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr)
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
+ {}
+
+ OperatorExprMeta (HIR::NegationExpr &expr)
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
+ {}
+
+ OperatorExprMeta (HIR::DereferenceExpr &expr)
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
+ {}
+
+ OperatorExprMeta (HIR::ArrayIndexExpr &expr)
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_array_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
+ {}
+
+ const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
+
+ const Analysis::NodeMapping &get_lvalue_mappings () const
+ {
+ return lvalue_mappings;
+ }
+
+ Location get_locus () const { return locus; }
+
+private:
+ const Analysis::NodeMapping node_mappings;
+ const Analysis::NodeMapping lvalue_mappings;
+ Location locus;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
new file mode 100644
index 000000000000..394b04f6c7fa
--- /dev/null
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -0,0 +1,3207 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#ifndef RUST_HIR_ITEM_H
+#define RUST_HIR_ITEM_H
+
+#include "rust-abi.h"
+#include "rust-ast-full-decls.h"
+#include "rust-common.h"
+#include "rust-hir.h"
+#include "rust-hir-path.h"
+
+namespace Rust {
+namespace HIR {
+// forward decls
+class BlockExpr;
+class TypePath;
+
+// A type generic parameter (as opposed to a lifetime generic parameter)
+class TypeParam : public GenericParam
+{
+ // bool has_outer_attribute;
+ // std::unique_ptr outer_attr;
+ AST::Attribute outer_attr;
+
+ Identifier type_representation;
+
+ // bool has_type_param_bounds;
+ // TypeParamBounds type_param_bounds;
+ std::vector>
+ type_param_bounds; // inlined form
+
+ // bool has_type;
+ std::unique_ptr type;
+
+ Location locus;
+
+public:
+ // Returns whether the type of the type param has been specified.
+ bool has_type () const { return type != nullptr; }
+
+ // Returns whether the type param has type param bounds.
+ bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
+
+ // Returns whether the type param has an outer attribute.
+ bool has_outer_attribute () const { return !outer_attr.is_empty (); }
+
+ TypeParam (Analysis::NodeMapping mappings, Identifier type_representation,
+ Location locus = Location (),
+ std::vector> type_param_bounds
+ = std::vector> (),
+ std::unique_ptr type = nullptr,
+ AST::Attribute outer_attr = AST::Attribute::create_empty ())
+ : GenericParam (mappings), outer_attr (std::move (outer_attr)),
+ type_representation (std::move (type_representation)),
+ type_param_bounds (std::move (type_param_bounds)),
+ type (std::move (type)), locus (locus)
+ {}
+
+ // Copy constructor uses clone
+ TypeParam (TypeParam const &other)
+ : GenericParam (other.mappings), outer_attr (other.outer_attr),
+ type_representation (other.type_representation), locus (other.locus)
+ {
+ // guard to prevent null pointer dereference
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+
+ type_param_bounds.reserve (other.type_param_bounds.size ());
+ for (const auto &e : other.type_param_bounds)
+ type_param_bounds.push_back (e->clone_type_param_bound ());
+ }
+
+ // Overloaded assignment operator to clone
+ TypeParam &operator= (TypeParam const &other)
+ {
+ type_representation = other.type_representation;
+ outer_attr = other.outer_attr;
+ locus = other.locus;
+ mappings = other.mappings;
+
+ // guard to prevent null pointer dereference
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
+ type_param_bounds.reserve (other.type_param_bounds.size ());
+ for (const auto &e : other.type_param_bounds)
+ type_param_bounds.push_back (e->clone_type_param_bound ());
+
+ return *this;
+ }
+ // move constructors
+ TypeParam (TypeParam &&other) = default;
+ TypeParam &operator= (TypeParam &&other) = default;
+
+ std::string as_string () const override;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+
+ Identifier get_type_representation () const { return type_representation; }
+
+ std::unique_ptr &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
+ Analysis::NodeMapping get_type_mappings () const
+ {
+ rust_assert (type != nullptr);
+ return type->get_mappings ();
+ }
+
+ std::vector> &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+
+protected:
+ // Clone function implementation as (not pure) virtual method
+ TypeParam *clone_generic_param_impl () const override
+ {
+ return new TypeParam (*this);
+ }
+};
+
+/* "where" clause item base. Abstract - use LifetimeWhereClauseItem,
+ * TypeBoundWhereClauseItem */
+class WhereClauseItem
+{
+public:
+ enum ItemType
+ {
+ LIFETIME,
+ TYPE_BOUND,
+ };
+
+ virtual ~WhereClauseItem () {}
+
+ // Unique pointer custom clone function
+ std::unique_ptr clone_where_clause_item () const
+ {
+ return std::unique_ptr (clone_where_clause_item_impl ());
+ }
+
+ virtual std::string as_string () const = 0;
+
+ virtual void accept_vis (HIRFullVisitor &vis) = 0;
+
+ virtual Analysis::NodeMapping get_mappings () const = 0;
+
+ virtual ItemType get_item_type () const = 0;
+
+protected:
+ // Clone function implementation as pure virtual method
+ virtual WhereClauseItem *clone_where_clause_item_impl () const = 0;
+};
+
+// A lifetime where clause item
+class LifetimeWhereClauseItem : public WhereClauseItem
+{
+ Lifetime lifetime;
+ std::vector lifetime_bounds;
+ Location locus;
+ Analysis::NodeMapping mappings;
+
+public:
+ LifetimeWhereClauseItem (Analysis::NodeMapping mappings, Lifetime lifetime,
+ std::vector lifetime_bounds,
+ Location locus)
+ : lifetime (std::move (lifetime)),
+ lifetime_bounds (std::move (lifetime_bounds)), locus (locus),
+ mappings (std::move (mappings))
+ {}
+
+ std::string as_string () const override;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+
+ Lifetime &get_lifetime () { return lifetime; }
+
+ std::vector &get_lifetime_bounds () { return lifetime_bounds; }
+
+ Analysis::NodeMapping get_mappings () const override final
+ {
+ return mappings;
+ };
+
+ ItemType get_item_type () const override final
+ {
+ return WhereClauseItem::ItemType::LIFETIME;
+ }
+
+protected:
+ // Clone function implementation as (not pure) virtual method
+ LifetimeWhereClauseItem *clone_where_clause_item_impl () const override
+ {
+ return new LifetimeWhereClauseItem (*this);
+ }
+};
+
+// A type bound where clause item
+class TypeBoundWhereClauseItem : public WhereClauseItem
+{
+ std::vector for_lifetimes;
+ std::unique_ptr bound_type;
+ std::vector> type_param_bounds;
+ Analysis::NodeMapping mappings;
+ Location locus;
+
+public:
+ // Returns whether the item has ForLifetimes
+ bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
+
+ // Returns whether the item has type param bounds
+ bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
+
+ TypeBoundWhereClauseItem (
+ Analysis::NodeMapping mappings, std::vector for_lifetimes,
+ std::unique_ptr bound_type,
+ std::vector> type_param_bounds,
+ Location locus)
+ : for_lifetimes (std::move (for_lifetimes)),
+ bound_type (std::move (bound_type)),
+ type_param_bounds (std::move (type_param_bounds)),
+ mappings (std::move (mappings)), locus (locus)
+ {}
+
+ // Copy constructor requires clone
+ TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other)
+ : for_lifetimes (other.for_lifetimes),
+ bound_type (other.bound_type->clone_type ()), mappings (other.mappings)
+ {
+ type_param_bounds.reserve (other.type_param_bounds.size ());
+ for (const auto &e : other.type_param_bounds)
+ type_param_bounds.push_back (e->clone_type_param_bound ());
+ }
+
+ // Overload assignment operator to clone
+ TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other)
+ {
+ mappings = other.mappings;
+ for_lifetimes = other.for_lifetimes;
+ bound_type = other.bound_type->clone_type ();
+ type_param_bounds.reserve (other.type_param_bounds.size ());
+ for (const auto &e : other.type_param_bounds)
+ type_param_bounds.push_back (e->clone_type_param_bound ());
+
+ return *this;
+ }
+
+ // move constructors
+ TypeBoundWhereClauseItem (TypeBoundWhereClauseItem &&other) = default;
+ TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem &&other)
+ = default;
+
+ std::string as_string () const override;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+
+ std::vector &get_for_lifetimes () { return for_lifetimes; }
+
+ std::unique_ptr &get_bound_type () { return bound_type; }
+
+ std::vector> &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+
+ Analysis::NodeMapping get_mappings () const override final
+ {
+ return mappings;
+ };
+
+ ItemType get_item_type () const override final
+ {
+ return WhereClauseItem::ItemType::TYPE_BOUND;
+ }
+
+protected:
+ // Clone function implementation as (not pure) virtual method
+ TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override
+ {
+ return new TypeBoundWhereClauseItem (*this);
+ }
+};
+
+// A where clause
+struct WhereClause
+{
+private:
+ std::vector> where_clause_items;
+
+ // should this store location info?
+
+public:
+ WhereClause (std::vector> where_clause_items)
+ : where_clause_items (std::move (where_clause_items))
+ {}
+
+ // copy constructor with vector clone
+ WhereClause (WhereClause const &other)
+ {
+ where_clause_items.reserve (other.where_clause_items.size ());
+ for (const auto &e : other.where_clause_items)
+ where_clause_items.push_back (e->clone_where_clause_item ());
+ }
+
+ // overloaded assignment operator with vector clone
+ WhereClause &operator= (WhereClause const &other)
+ {
+ where_clause_items.reserve (other.where_clause_items.size ());
+ for (const auto &e : other.where_clause_items)
+ where_clause_items.push_back (e->clone_where_clause_item ());
+
+ return *this;
+ }
+
+ // move constructors
+ WhereClause (WhereClause &&other) = default;
+ WhereClause &operator= (WhereClause &&other) = default;
+
+ // Creates a WhereClause with no items.
+ static WhereClause create_empty ()
+ {
+ return WhereClause (std::vector> ());
+ }
+
+ // Returns whether the WhereClause has no items.
+ bool is_empty () const { return where_clause_items.empty (); }
+
+ std::string as_string () const;
+
+ std::vector> &get_items ()
+ {
+ return where_clause_items;
+ }
+ const std::vector> &get_items () const
+ {
+ return where_clause_items;
+ }
+};
+
+// A self parameter in a method
+struct SelfParam
+{
+public:
+ enum ImplicitSelfKind
+ {
+ IMM, // self
+ MUT, // mut self
+ IMM_REF, // &self
+ MUT_REF, // &mut self
+ NONE
+ };
+
+private:
+ ImplicitSelfKind self_kind;
+ Lifetime lifetime;
+ std::unique_ptr type;
+ Location locus;
+ Analysis::NodeMapping mappings;
+
+ SelfParam (Analysis::NodeMapping mappings, ImplicitSelfKind self_kind,
+ Lifetime lifetime, Type *type)
+ : self_kind (self_kind), lifetime (std::move (lifetime)), type (type),
+ mappings (mappings)
+ {}
+
+public:
+ // Type-based self parameter (not ref, no lifetime)
+ SelfParam (Analysis::NodeMapping mappings, std::unique_ptr type,
+ bool is_mut, Location locus)
+ : self_kind (is_mut ? ImplicitSelfKind::MUT : ImplicitSelfKind::IMM),
+ lifetime (
+ Lifetime (mappings, AST::Lifetime::LifetimeType::NAMED, "", locus)),
+ type (std::move (type)), locus (locus), mappings (mappings)
+ {}
+
+ // Lifetime-based self parameter (is ref, no type)
+ SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, bool is_mut,
+ Location locus)
+ : self_kind (is_mut ? ImplicitSelfKind::MUT_REF
+ : ImplicitSelfKind::IMM_REF),
+ lifetime (std::move (lifetime)), locus (locus), mappings (mappings)
+ {}
+
+ // Copy constructor requires clone
+ SelfParam (SelfParam const &other)
+ : self_kind (other.self_kind), lifetime (other.lifetime),
+ locus (other.locus), mappings (other.mappings)
+ {
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ }
+
+ // Overload assignment operator to use clone
+ SelfParam &operator= (SelfParam const &other)
+ {
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+
+ self_kind = other.self_kind;
+ lifetime = other.lifetime;
+ locus = other.locus;
+ mappings = other.mappings;
+
+ return *this;
+ }
+
+ // move constructors
+ SelfParam (SelfParam &&other) = default;
+ SelfParam &operator= (SelfParam &&other) = default;
+
+ static SelfParam error ()
+ {
+ return SelfParam (Analysis::NodeMapping::get_error (),
+ ImplicitSelfKind::NONE, Lifetime::error (), nullptr);
+ }
+
+ // Returns whether the self-param has a type field.
+ bool has_type () const { return type != nullptr; }
+
+ // Returns whether the self-param has a valid lifetime.
+ bool has_lifetime () const { return !lifetime.is_error (); }
+
+ // Returns whether the self-param is in an error state.
+ bool is_error () const { return self_kind == ImplicitSelfKind::NONE; }
+
+ std::string as_string () const;
+
+ Location get_locus () const { return locus; }
+
+ ImplicitSelfKind get_self_kind () const { return self_kind; }
+
+ std::unique_ptr &get_type ()
+ {
+ rust_assert (has_type ());
+ return type;
+ }
+
+ Analysis::NodeMapping get_mappings () { return mappings; }
+
+ Mutability get_mut () const
+ {
+ return (self_kind == ImplicitSelfKind::MUT
+ || self_kind == ImplicitSelfKind::MUT_REF)
+ ? Mutability::Mut
+ : Mutability::Imm;
+ }
+
+ bool is_mut () const
+ {
+ return self_kind == ImplicitSelfKind::MUT
+ || self_kind == ImplicitSelfKind::MUT_REF;
+ }
+
+ bool is_ref () const
+ {
+ return self_kind == ImplicitSelfKind::IMM_REF
+ || self_kind == ImplicitSelfKind::MUT_REF;
+ }
+};
+
+// Qualifiers for function, i.e. const, unsafe, extern etc.
+struct FunctionQualifiers
+{
+private:
+ AsyncConstStatus const_status;
+ Unsafety unsafety;
+ bool has_extern;
+ ABI abi;
+
+public:
+ FunctionQualifiers (AsyncConstStatus const_status, Unsafety unsafety,
+ bool has_extern, ABI abi)
+ : const_status (const_status), unsafety (unsafety), has_extern (has_extern),
+ abi (abi)
+ {}
+
+ std::string as_string () const;
+
+ AsyncConstStatus get_status () const { return const_status; }
+
+ bool is_const () const { return const_status == AsyncConstStatus::CONST_FN; }
+ bool is_unsafe () const { return unsafety == Unsafety::Unsafe; }
+
+ ABI get_abi () const { return abi; }
+};
+
+// A function parameter
+struct FunctionParam
+{
+ std::unique_ptr param_name;
+ std::unique_ptr