LCOV - code coverage report
Current view: top level - gcc/rust/hir/tree - rust-hir-expr.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 49.4 % 543 268
Test Date: 2026-02-28 14:20:25 Functions: 39.3 % 183 72
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #ifndef RUST_HIR_EXPR_H
      20              : #define RUST_HIR_EXPR_H
      21              : 
      22              : #include "rust-ast.h"
      23              : #include "rust-hir-expr-abstract.h"
      24              : #include "rust-hir-literal.h"
      25              : #include "rust-common.h"
      26              : #include "rust-hir-bound.h"
      27              : #include "rust-hir-attrs.h"
      28              : #include "rust-expr.h"
      29              : #include "rust-hir-map.h"
      30              : #include "rust-mapping-common.h"
      31              : 
      32              : namespace Rust {
      33              : namespace HIR {
      34              : 
      35              : // Loop label expression HIR node used with break and continue expressions
      36              : // TODO: inline?
      37          288 : class LoopLabel /*: public Node*/
      38              : {
      39              :   Lifetime label; // of type LIFETIME_OR_LABEL
      40              : 
      41              :   location_t locus;
      42              : 
      43              :   Analysis::NodeMapping mappings;
      44              : 
      45              : public:
      46              :   std::string to_string () const;
      47              : 
      48              :   LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label,
      49              :              location_t locus);
      50              : 
      51           36 :   location_t get_locus () const { return locus; }
      52              : 
      53              :   Analysis::NodeMapping &get_mappings () { return mappings; }
      54              : 
      55           43 :   Lifetime &get_lifetime () { return label; }
      56              : };
      57              : 
      58              : // HIR node for an expression with an accompanying block - abstract
      59            0 : class ExprWithBlock : public Expr
      60              : {
      61              :   // TODO: should this mean that a BlockExpr should be a member variable?
      62              : protected:
      63              :   ExprWithBlock (Analysis::NodeMapping mappings,
      64              :                  AST::AttrVec outer_attrs = AST::AttrVec ());
      65              : 
      66              :   // pure virtual clone implementation
      67              :   virtual ExprWithBlock *clone_expr_with_block_impl () const = 0;
      68              : 
      69              :   // prevent having to define multiple clone expressions
      70            7 :   ExprWithBlock *clone_expr_impl () const override
      71              :   {
      72            7 :     return clone_expr_with_block_impl ();
      73              :   }
      74              : 
      75              : public:
      76              :   // Unique pointer custom clone function
      77            0 :   std::unique_ptr<ExprWithBlock> clone_expr_with_block () const
      78              :   {
      79            0 :     return std::unique_ptr<ExprWithBlock> (clone_expr_with_block_impl ());
      80              :   }
      81              : 
      82            0 :   BlockType get_block_expr_type () const final override
      83              :   {
      84            0 :     return BlockType::WITH_BLOCK;
      85              :   };
      86              : };
      87              : 
      88              : // Literals? Or literal base?
      89              : class LiteralExpr : public ExprWithoutBlock
      90              : {
      91              :   Literal literal;
      92              :   location_t locus;
      93              :   bool negative_number = false;
      94              : 
      95              : public:
      96        17371 :   std::string to_string () const override { return literal.as_string (); }
      97              : 
      98        44366 :   Literal::LitType get_lit_type () const { return literal.get_lit_type (); }
      99              : 
     100              :   LiteralExpr (Analysis::NodeMapping mappings, std::string value_as_string,
     101              :                Literal::LitType type, PrimitiveCoreType type_hint,
     102              :                location_t locus, AST::AttrVec outer_attrs);
     103              : 
     104              :   LiteralExpr (Analysis::NodeMapping mappings, Literal literal,
     105              :                location_t locus, AST::AttrVec outer_attrs);
     106              : 
     107              :   // Unique pointer custom clone function
     108              :   std::unique_ptr<LiteralExpr> clone_literal_expr () const
     109              :   {
     110              :     return std::unique_ptr<LiteralExpr> (clone_literal_expr_impl ());
     111              :   }
     112              : 
     113        70754 :   location_t get_locus () const override final { return locus; }
     114              : 
     115              :   void accept_vis (HIRFullVisitor &vis) override;
     116              :   void accept_vis (HIRExpressionVisitor &vis) override;
     117              : 
     118        18494 :   Literal &get_literal () { return literal; }
     119        21905 :   const Literal &get_literal () const { return literal; }
     120              : 
     121         1306 :   ExprType get_expression_type () const override final { return ExprType::Lit; }
     122              : 
     123        18090 :   bool is_negative () const { return negative_number; }
     124          552 :   void set_negative ()
     125              :   {
     126          552 :     rust_assert (get_lit_type () == Literal::LitType::INT
     127              :                  || get_lit_type () == Literal::LitType::FLOAT);
     128          552 :     negative_number = true;
     129          552 :   }
     130              : 
     131              : protected:
     132              :   /* Use covariance to implement clone function as returning this object rather
     133              :    * than base */
     134        90387 :   LiteralExpr *clone_expr_impl () const override
     135              :   {
     136        90387 :     return new LiteralExpr (*this);
     137              :   }
     138              : 
     139              :   /* Use covariance to implement clone function as returning this object rather
     140              :    * than base */
     141            0 :   LiteralExpr *clone_expr_without_block_impl () const override
     142              :   {
     143            0 :     return new LiteralExpr (*this);
     144              :   }
     145              : 
     146              :   /* not virtual as currently no subclasses of LiteralExpr, but could be in
     147              :    * future */
     148              :   /*virtual*/ LiteralExpr *clone_literal_expr_impl () const
     149              :   {
     150              :     return new LiteralExpr (*this);
     151              :   }
     152              : };
     153              : 
     154              : /* Represents an expression using unary or binary operators as HIR node. Can be
     155              :  * overloaded. */
     156              : class OperatorExpr : public ExprWithoutBlock
     157              : {
     158              :   // TODO: create binary and unary operator subclasses?
     159              : private:
     160              :   location_t locus;
     161              : 
     162              : protected:
     163              :   /* Variable must be protected to allow derived classes to use it as a first
     164              :    * class citizen */
     165              :   std::unique_ptr<Expr> main_or_left_expr;
     166              : 
     167              :   // Constructor (only for initialisation of expr purposes)
     168              :   OperatorExpr (Analysis::NodeMapping mappings,
     169              :                 std::unique_ptr<Expr> main_or_left_expr,
     170              :                 AST::AttrVec outer_attribs, location_t locus);
     171              : 
     172              :   // Copy constructor (only for initialisation of expr purposes)
     173              :   OperatorExpr (OperatorExpr const &other);
     174              : 
     175              :   // Overload assignment operator to deep copy expr
     176              :   OperatorExpr &operator= (OperatorExpr const &other);
     177              : 
     178              :   // move constructors
     179              :   OperatorExpr (OperatorExpr &&other) = default;
     180              :   OperatorExpr &operator= (OperatorExpr &&other) = default;
     181              : 
     182              : public:
     183        93822 :   location_t get_locus () const override final { return locus; }
     184              : 
     185        77159 :   Expr &get_expr () { return *main_or_left_expr; }
     186              : 
     187          159 :   ExprType get_expression_type () const override final
     188              :   {
     189          159 :     return ExprType::Operator;
     190              :   }
     191              : };
     192              : 
     193              : /* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be
     194              :  * overloaded. */
     195              : class BorrowExpr : public OperatorExpr
     196              : {
     197              :   Mutability mut;
     198              :   bool raw;
     199              : 
     200              : public:
     201              :   std::string to_string () const override;
     202              : 
     203              :   BorrowExpr (Analysis::NodeMapping mappings,
     204              :               std::unique_ptr<Expr> borrow_lvalue, Mutability mut, bool raw,
     205              :               AST::AttrVec outer_attribs, location_t locus);
     206              : 
     207              :   void accept_vis (HIRFullVisitor &vis) override;
     208              :   void accept_vis (HIRExpressionVisitor &vis) override;
     209              : 
     210         1947 :   Mutability get_mut () const { return mut; }
     211            0 :   bool is_mut () const { return mut == Mutability::Mut; }
     212         1947 :   bool is_raw_borrow () const { return raw; }
     213              : 
     214              : protected:
     215              :   /* Use covariance to implement clone function as returning this object rather
     216              :    * than base */
     217            4 :   BorrowExpr *clone_expr_impl () const override
     218              :   {
     219            4 :     return new BorrowExpr (*this);
     220              :   }
     221              : 
     222              :   /* Use covariance to implement clone function as returning this object rather
     223              :    * than base */
     224            0 :   BorrowExpr *clone_expr_without_block_impl () const override
     225              :   {
     226            0 :     return new BorrowExpr (*this);
     227              :   }
     228              : };
     229              : 
     230              : // Unary prefix * deference operator
     231            0 : class DereferenceExpr : public OperatorExpr
     232              : {
     233              : public:
     234              :   std::string to_string () const override;
     235              : 
     236              :   // Constructor calls OperatorExpr's protected constructor
     237              :   DereferenceExpr (Analysis::NodeMapping mappings,
     238              :                    std::unique_ptr<Expr> deref_lvalue,
     239              :                    AST::AttrVec outer_attribs, location_t locus);
     240              : 
     241              :   void accept_vis (HIRFullVisitor &vis) override;
     242              :   void accept_vis (HIRExpressionVisitor &vis) override;
     243              : 
     244              : protected:
     245              :   /* Use covariance to implement clone function as returning this object rather
     246              :    * than base */
     247            0 :   DereferenceExpr *clone_expr_impl () const override
     248              :   {
     249            0 :     return new DereferenceExpr (*this);
     250              :   }
     251              : 
     252              :   /* Use covariance to implement clone function as returning this object rather
     253              :    * than base */
     254            0 :   DereferenceExpr *clone_expr_without_block_impl () const override
     255              :   {
     256            0 :     return new DereferenceExpr (*this);
     257              :   }
     258              : };
     259              : 
     260              : // Unary postfix ? error propogation operator. Cannot be overloaded.
     261            0 : class ErrorPropagationExpr : public OperatorExpr
     262              : {
     263              : public:
     264              :   std::string to_string () const override;
     265              : 
     266              :   // Constructor calls OperatorExpr's protected constructor
     267              :   ErrorPropagationExpr (Analysis::NodeMapping mappings,
     268              :                         std::unique_ptr<Expr> potential_error_value,
     269              :                         AST::AttrVec outer_attribs, location_t locus);
     270              : 
     271              :   void accept_vis (HIRFullVisitor &vis) override;
     272              :   void accept_vis (HIRExpressionVisitor &vis) override;
     273              : 
     274              : protected:
     275              :   /* Use covariance to implement clone function as returning this object rather
     276              :    * than base */
     277            0 :   ErrorPropagationExpr *clone_expr_impl () const override
     278              :   {
     279            0 :     return new ErrorPropagationExpr (*this);
     280              :   }
     281              : 
     282              :   /* Use covariance to implement clone function as returning this object rather
     283              :    * than base */
     284            0 :   ErrorPropagationExpr *clone_expr_without_block_impl () const override
     285              :   {
     286            0 :     return new ErrorPropagationExpr (*this);
     287              :   }
     288              : };
     289              : 
     290              : // Unary prefix - or ! negation or NOT operators.
     291              : class NegationExpr : public OperatorExpr
     292              : {
     293              : public:
     294              :   using ExprType = NegationOperator;
     295              : 
     296              : private:
     297              :   /* Note: overload negation via std::ops::Neg and not via std::ops::Not
     298              :    * Negation only works for signed integer and floating-point types, NOT only
     299              :    * works for boolean and integer types (via bitwise NOT) */
     300              :   ExprType expr_type;
     301              : 
     302              : public:
     303              :   std::string to_string () const override;
     304              : 
     305         1725 :   ExprType get_expr_type () const { return expr_type; }
     306              : 
     307              :   // Constructor calls OperatorExpr's protected constructor
     308              :   NegationExpr (Analysis::NodeMapping mappings,
     309              :                 std::unique_ptr<Expr> negated_value, ExprType expr_kind,
     310              :                 AST::AttrVec outer_attribs, location_t locus);
     311              : 
     312              :   void accept_vis (HIRFullVisitor &vis) override;
     313              :   void accept_vis (HIRExpressionVisitor &vis) override;
     314              : 
     315              : protected:
     316              :   /* Use covariance to implement clone function as returning this object rather
     317              :    * than base */
     318         9183 :   NegationExpr *clone_expr_impl () const override
     319              :   {
     320         9183 :     return new NegationExpr (*this);
     321              :   }
     322              : 
     323              :   /* Use covariance to implement clone function as returning this object rather
     324              :    * than base */
     325            0 :   NegationExpr *clone_expr_without_block_impl () const override
     326              :   {
     327            0 :     return new NegationExpr (*this);
     328              :   }
     329              : };
     330              : 
     331              : // Infix binary operators. +, -, *, /, %, &, |, ^, <<, >>
     332              : class ArithmeticOrLogicalExpr : public OperatorExpr
     333              : {
     334              : public:
     335              :   using ExprType = ArithmeticOrLogicalOperator;
     336              : 
     337              : private:
     338              :   // Note: overloading trait specified in comments
     339              :   ExprType expr_type;
     340              : 
     341              :   std::unique_ptr<Expr> right_expr;
     342              : 
     343              : public:
     344              :   std::string to_string () const override;
     345              : 
     346        13299 :   ExprType get_expr_type () const { return expr_type; }
     347              : 
     348              :   // Constructor calls OperatorExpr's protected constructor
     349              :   ArithmeticOrLogicalExpr (Analysis::NodeMapping mappings,
     350              :                            std::unique_ptr<Expr> left_value,
     351              :                            std::unique_ptr<Expr> right_value,
     352              :                            ExprType expr_kind, location_t locus);
     353              :   // outer attributes not allowed
     354              : 
     355              :   // Copy constructor - probably required due to unique pointer
     356              :   ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr const &other);
     357              : 
     358              :   // Overload assignment operator
     359              :   ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr const &other);
     360              : 
     361              :   // move constructors
     362              :   ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr &&other) = default;
     363              :   ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr &&other)
     364              :     = default;
     365              : 
     366              :   void accept_vis (HIRFullVisitor &vis) override;
     367              :   void accept_vis (HIRExpressionVisitor &vis) override;
     368              : 
     369         2922 :   void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); }
     370         2922 :   void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); }
     371              : 
     372        25093 :   Expr &get_lhs () { return *main_or_left_expr; }
     373        28617 :   Expr &get_rhs () { return *right_expr; }
     374              : 
     375              :   std::string get_operator_str () const;
     376              : 
     377              : protected:
     378              :   /* Use covariance to implement clone function as returning this object rather
     379              :    * than base */
     380           34 :   ArithmeticOrLogicalExpr *clone_expr_impl () const override
     381              :   {
     382           34 :     return new ArithmeticOrLogicalExpr (*this);
     383              :   }
     384              : 
     385              :   /* Use covariance to implement clone function as returning this object rather
     386              :    * than base */
     387            0 :   ArithmeticOrLogicalExpr *clone_expr_without_block_impl () const override
     388              :   {
     389            0 :     return new ArithmeticOrLogicalExpr (*this);
     390              :   }
     391              : };
     392              : 
     393              : // Infix binary comparison operators. ==, !=, <, <=, >, >=
     394              : class ComparisonExpr : public OperatorExpr
     395              : {
     396              : public:
     397              :   using ExprType = ComparisonOperator;
     398              : 
     399              : private:
     400              :   // Note: overloading trait specified in comments
     401              :   ExprType expr_type;
     402              : 
     403              :   std::unique_ptr<Expr> right_expr;
     404              : 
     405              : public:
     406              :   std::string to_string () const override;
     407              : 
     408         9648 :   ExprType get_expr_type () const { return expr_type; }
     409              : 
     410              :   // Constructor requires pointers for polymorphism
     411              :   ComparisonExpr (Analysis::NodeMapping mappings,
     412              :                   std::unique_ptr<Expr> left_value,
     413              :                   std::unique_ptr<Expr> right_value, ExprType comparison_kind,
     414              :                   location_t locus);
     415              :   // outer attributes not allowed
     416              : 
     417              :   // Copy constructor also calls OperatorExpr's protected constructor
     418              :   ComparisonExpr (ComparisonExpr const &other);
     419              : 
     420              :   // Overload assignment operator to deep copy
     421              :   ComparisonExpr &operator= (ComparisonExpr const &other);
     422              : 
     423              :   // move constructors
     424              :   ComparisonExpr (ComparisonExpr &&other) = default;
     425              :   ComparisonExpr &operator= (ComparisonExpr &&other) = default;
     426              : 
     427              :   void accept_vis (HIRFullVisitor &vis) override;
     428              :   void accept_vis (HIRExpressionVisitor &vis) override;
     429              : 
     430        20468 :   Expr &get_lhs () { return *main_or_left_expr; }
     431        24014 :   Expr &get_rhs () { return *right_expr; }
     432              : 
     433              :   ExprType get_kind () { return expr_type; }
     434              : 
     435              :   /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2)
     436              :    * maybe? */
     437              : protected:
     438              :   /* Use covariance to implement clone function as returning this object rather
     439              :    * than base */
     440            0 :   ComparisonExpr *clone_expr_impl () const override
     441              :   {
     442            0 :     return new ComparisonExpr (*this);
     443              :   }
     444              : 
     445              :   /* Use covariance to implement clone function as returning this object rather
     446              :    * than base */
     447            0 :   ComparisonExpr *clone_expr_without_block_impl () const override
     448              :   {
     449            0 :     return new ComparisonExpr (*this);
     450              :   }
     451              : };
     452              : 
     453              : // Infix binary lazy boolean logical operators && and ||.
     454              : class LazyBooleanExpr : public OperatorExpr
     455              : {
     456              : public:
     457              :   using ExprType = LazyBooleanOperator;
     458              : 
     459              : private:
     460              :   ExprType expr_type;
     461              : 
     462              :   std::unique_ptr<Expr> right_expr;
     463              : 
     464              : public:
     465              :   // Constructor calls OperatorExpr's protected constructor
     466              :   LazyBooleanExpr (Analysis::NodeMapping mappings,
     467              :                    std::unique_ptr<Expr> left_bool_expr,
     468              :                    std::unique_ptr<Expr> right_bool_expr, ExprType expr_kind,
     469              :                    location_t locus);
     470              :   // outer attributes not allowed
     471              : 
     472              :   // Copy constructor also calls OperatorExpr's protected constructor
     473              :   LazyBooleanExpr (LazyBooleanExpr const &other);
     474              : 
     475              :   // Overload assignment operator to deep copy
     476              :   LazyBooleanExpr &operator= (LazyBooleanExpr const &other);
     477              : 
     478              :   // move constructors
     479              :   LazyBooleanExpr (LazyBooleanExpr &&other) = default;
     480              :   LazyBooleanExpr &operator= (LazyBooleanExpr &&other) = default;
     481              : 
     482              :   std::string to_string () const override;
     483              : 
     484          377 :   ExprType get_expr_type () const { return expr_type; }
     485              : 
     486              :   void accept_vis (HIRFullVisitor &vis) override;
     487              :   void accept_vis (HIRExpressionVisitor &vis) override;
     488              : 
     489         4646 :   Expr &get_lhs () { return *main_or_left_expr; }
     490         4646 :   Expr &get_rhs () { return *right_expr; }
     491              : 
     492              : protected:
     493              :   /* Use covariance to implement clone function as returning this object rather
     494              :    * than base */
     495            0 :   LazyBooleanExpr *clone_expr_impl () const override
     496              :   {
     497            0 :     return new LazyBooleanExpr (*this);
     498              :   }
     499              : 
     500              :   /* Use covariance to implement clone function as returning this object rather
     501              :    * than base */
     502            0 :   LazyBooleanExpr *clone_expr_without_block_impl () const override
     503              :   {
     504            0 :     return new LazyBooleanExpr (*this);
     505              :   }
     506              : };
     507              : 
     508              : // Binary infix "as" chir expression.
     509              : class TypeCastExpr : public OperatorExpr
     510              : {
     511              :   std::unique_ptr<Type> type_to_convert_to;
     512              : 
     513              :   // Note: only certain type casts allowed, outlined in reference
     514              : public:
     515              :   std::string to_string () const override;
     516              : 
     517              :   // Constructor requires calling protected constructor of OperatorExpr
     518              :   TypeCastExpr (Analysis::NodeMapping mappings,
     519              :                 std::unique_ptr<Expr> expr_to_cast,
     520              :                 std::unique_ptr<Type> type_to_cast_to, location_t locus);
     521              :   // outer attributes not allowed
     522              : 
     523              :   // Copy constructor also requires calling protected constructor
     524              :   TypeCastExpr (TypeCastExpr const &other);
     525              : 
     526              :   // Overload assignment operator to deep copy
     527              :   TypeCastExpr &operator= (TypeCastExpr const &other);
     528              : 
     529              :   // move constructors as not supported in c++03
     530              :   TypeCastExpr (TypeCastExpr &&other) = default;
     531              :   TypeCastExpr &operator= (TypeCastExpr &&other) = default;
     532              : 
     533              :   void accept_vis (HIRFullVisitor &vis) override;
     534              :   void accept_vis (HIRExpressionVisitor &vis) override;
     535              : 
     536              :   // FIXME: isn't it the same as get_expr() from parent?
     537        19928 :   Expr &get_casted_expr () { return *main_or_left_expr; }
     538              : 
     539        12182 :   Type &get_type_to_convert_to () { return *type_to_convert_to; }
     540              : 
     541              : protected:
     542              :   /* Use covariance to implement clone function as returning this object rather
     543              :    * than base */
     544            0 :   TypeCastExpr *clone_expr_impl () const override
     545              :   {
     546            0 :     return new TypeCastExpr (*this);
     547              :   }
     548              : 
     549              :   /* Use covariance to implement clone function as returning this object rather
     550              :    * than base */
     551            0 :   TypeCastExpr *clone_expr_without_block_impl () const override
     552              :   {
     553            0 :     return new TypeCastExpr (*this);
     554              :   }
     555              : };
     556              : 
     557              : // Binary assignment expression.
     558              : class AssignmentExpr : public OperatorExpr
     559              : {
     560              :   std::unique_ptr<Expr> right_expr;
     561              : 
     562              : public:
     563              :   std::string to_string () const override;
     564              : 
     565              :   // Call OperatorExpr constructor to initialise left_expr
     566              :   AssignmentExpr (Analysis::NodeMapping mappings,
     567              :                   std::unique_ptr<Expr> value_to_assign_to,
     568              :                   std::unique_ptr<Expr> value_to_assign, location_t locus);
     569              :   // outer attributes not allowed
     570              : 
     571              :   // Call OperatorExpr constructor in copy constructor, as well as clone
     572              :   AssignmentExpr (AssignmentExpr const &other);
     573              : 
     574              :   // Overload assignment operator to clone unique_ptr right_expr
     575              :   AssignmentExpr &operator= (AssignmentExpr const &other);
     576              : 
     577              :   // move constructors
     578              :   AssignmentExpr (AssignmentExpr &&other) = default;
     579              :   AssignmentExpr &operator= (AssignmentExpr &&other) = default;
     580              : 
     581              :   void accept_vis (HIRFullVisitor &vis) override;
     582              :   void accept_vis (HIRExpressionVisitor &vis) override;
     583              : 
     584         2364 :   void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); }
     585         2364 :   void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); }
     586              : 
     587        24427 :   Expr &get_lhs () { return *main_or_left_expr; }
     588        19527 :   Expr &get_rhs () { return *right_expr; }
     589              : 
     590              : protected:
     591              :   /* Use covariance to implement clone function as returning this object rather
     592              :    * than base */
     593            0 :   AssignmentExpr *clone_expr_impl () const override
     594              :   {
     595            0 :     return new AssignmentExpr (*this);
     596              :   }
     597              : 
     598              :   /* Use covariance to implement clone function as returning this object rather
     599              :    * than base */
     600            0 :   AssignmentExpr *clone_expr_without_block_impl () const override
     601              :   {
     602            0 :     return new AssignmentExpr (*this);
     603              :   }
     604              : };
     605              : 
     606              : class CompoundAssignmentExpr : public OperatorExpr
     607              : {
     608              : public:
     609              :   using ExprType = ArithmeticOrLogicalOperator;
     610              : 
     611              : private:
     612              :   // Note: overloading trait specified in comments
     613              :   ExprType expr_type;
     614              :   std::unique_ptr<Expr> right_expr;
     615              : 
     616              : public:
     617              :   std::string to_string () const override;
     618              : 
     619         2098 :   ExprType get_expr_type () const { return expr_type; }
     620              : 
     621              :   // Use pointers in constructor to enable polymorphism
     622              :   CompoundAssignmentExpr (Analysis::NodeMapping mappings,
     623              :                           std::unique_ptr<Expr> value_to_assign_to,
     624              :                           std::unique_ptr<Expr> value_to_assign,
     625              :                           ExprType expr_kind, location_t locus);
     626              :   // outer attributes not allowed
     627              : 
     628              :   // Have clone in copy constructor
     629              :   CompoundAssignmentExpr (CompoundAssignmentExpr const &other);
     630              : 
     631              :   // Overload assignment operator to clone
     632              :   CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other);
     633              : 
     634              :   // move constructors
     635              :   CompoundAssignmentExpr (CompoundAssignmentExpr &&other) = default;
     636              :   CompoundAssignmentExpr &operator= (CompoundAssignmentExpr &&other) = default;
     637              : 
     638              :   void accept_vis (HIRFullVisitor &vis) override;
     639              :   void accept_vis (HIRExpressionVisitor &vis) override;
     640              : 
     641         5371 :   Expr &get_lhs () { return *main_or_left_expr; }
     642              : 
     643         5385 :   Expr &get_rhs () { return *right_expr; }
     644              : 
     645          529 :   void visit_lhs (HIRFullVisitor &vis) { main_or_left_expr->accept_vis (vis); }
     646          529 :   void visit_rhs (HIRFullVisitor &vis) { right_expr->accept_vis (vis); }
     647              : 
     648              :   std::string get_operator_str () const;
     649              : 
     650              : protected:
     651              :   /* Use covariance to implement clone function as returning this object rather
     652              :    * than base */
     653            0 :   CompoundAssignmentExpr *clone_expr_without_block_impl () const override
     654              :   {
     655            0 :     return new CompoundAssignmentExpr (*this);
     656              :   }
     657              : };
     658              : 
     659              : // Expression in parentheses (i.e. like literally just any 3 + (2 * 6))
     660              : class GroupedExpr : public ExprWithoutBlock, public WithInnerAttrs
     661              : {
     662              :   std::unique_ptr<Expr> expr_in_parens;
     663              : 
     664              :   location_t locus;
     665              : 
     666              : public:
     667              :   std::string to_string () const override;
     668              : 
     669              :   GroupedExpr (Analysis::NodeMapping mappings,
     670              :                std::unique_ptr<Expr> parenthesised_expr,
     671              :                AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
     672              :                location_t locus);
     673              : 
     674              :   // Copy constructor includes clone for expr_in_parens
     675              :   GroupedExpr (GroupedExpr const &other);
     676              : 
     677              :   // Overloaded assignment operator to clone expr_in_parens
     678              :   GroupedExpr &operator= (GroupedExpr const &other);
     679              : 
     680              :   // move constructors
     681              :   GroupedExpr (GroupedExpr &&other) = default;
     682              :   GroupedExpr &operator= (GroupedExpr &&other) = default;
     683              : 
     684          641 :   location_t get_locus () const override final { return locus; }
     685              : 
     686              :   void accept_vis (HIRFullVisitor &vis) override;
     687              :   void accept_vis (HIRExpressionVisitor &vis) override;
     688              : 
     689         2403 :   Expr &get_expr_in_parens () { return *expr_in_parens; }
     690              : 
     691            1 :   ExprType get_expression_type () const override final
     692              :   {
     693            1 :     return ExprType::Grouped;
     694              :   }
     695              : 
     696              : protected:
     697              :   /* Use covariance to implement clone function as returning this object rather
     698              :    * than base */
     699            0 :   GroupedExpr *clone_expr_impl () const override
     700              :   {
     701            0 :     return new GroupedExpr (*this);
     702              :   }
     703              : 
     704              :   /* Use covariance to implement clone function as returning this object rather
     705              :    * than base */
     706            0 :   GroupedExpr *clone_expr_without_block_impl () const override
     707              :   {
     708            0 :     return new GroupedExpr (*this);
     709              :   }
     710              : };
     711              : 
     712              : // Base array initialisation internal element representation thing (abstract)
     713              : // aka ArrayElements
     714            0 : class ArrayElems : public FullVisitable
     715              : {
     716              : public:
     717              :   enum ArrayExprType
     718              :   {
     719              :     VALUES,
     720              :     COPIED,
     721              :   };
     722              : 
     723          427 :   ArrayElems (Analysis::NodeMapping mappings) : mappings (mappings){};
     724              : 
     725              :   virtual ~ArrayElems () {}
     726              : 
     727              :   // Unique pointer custom clone ArrayElems function
     728            0 :   std::unique_ptr<ArrayElems> clone_array_elems () const
     729              :   {
     730            0 :     return std::unique_ptr<ArrayElems> (clone_array_elems_impl ());
     731              :   }
     732              : 
     733              :   virtual std::string to_string () const = 0;
     734              : 
     735              :   virtual void accept_vis (HIRFullVisitor &vis) = 0;
     736              : 
     737              :   virtual ArrayExprType get_array_expr_type () const = 0;
     738              : 
     739          113 :   Analysis::NodeMapping &get_mappings () { return mappings; }
     740              : 
     741              : protected:
     742              :   // pure virtual clone implementation
     743              :   virtual ArrayElems *clone_array_elems_impl () const = 0;
     744              : 
     745              :   Analysis::NodeMapping mappings;
     746              : };
     747              : 
     748              : // Value array elements
     749              : class ArrayElemsValues : public ArrayElems
     750              : {
     751              :   std::vector<std::unique_ptr<Expr>> values;
     752              : 
     753              :   // TODO: should this store location data?
     754              : 
     755              : public:
     756              :   ArrayElemsValues (Analysis::NodeMapping mappings,
     757              :                     std::vector<std::unique_ptr<Expr>> elems);
     758              : 
     759              :   // copy constructor with vector clone
     760              :   ArrayElemsValues (ArrayElemsValues const &other);
     761              : 
     762              :   // overloaded assignment operator with vector clone
     763              :   ArrayElemsValues &operator= (ArrayElemsValues const &other);
     764              : 
     765              :   // move constructors
     766              :   ArrayElemsValues (ArrayElemsValues &&other) = default;
     767              :   ArrayElemsValues &operator= (ArrayElemsValues &&other) = default;
     768              : 
     769              :   std::string to_string () const override;
     770              : 
     771              :   void accept_vis (HIRFullVisitor &vis) override;
     772              : 
     773          303 :   size_t get_num_elements () const { return values.size (); }
     774              : 
     775         2012 :   std::vector<std::unique_ptr<Expr>> &get_values () { return values; }
     776              : 
     777          862 :   ArrayElems::ArrayExprType get_array_expr_type () const override final
     778              :   {
     779          862 :     return ArrayElems::ArrayExprType::VALUES;
     780              :   }
     781              : 
     782              : protected:
     783            0 :   ArrayElemsValues *clone_array_elems_impl () const override
     784              :   {
     785            0 :     return new ArrayElemsValues (*this);
     786              :   }
     787              : };
     788              : 
     789              : // Copied array element and number of copies
     790              : class ArrayElemsCopied : public ArrayElems
     791              : {
     792              :   std::unique_ptr<Expr> elem_to_copy;
     793              :   std::unique_ptr<Expr> num_copies;
     794              : 
     795              : public:
     796              :   // Constructor requires pointers for polymorphism
     797              :   ArrayElemsCopied (Analysis::NodeMapping mappings,
     798              :                     std::unique_ptr<Expr> copied_elem,
     799              :                     std::unique_ptr<Expr> copy_amount);
     800              : 
     801              :   // Copy constructor required due to unique_ptr - uses custom clone
     802              :   ArrayElemsCopied (ArrayElemsCopied const &other);
     803              : 
     804              :   // Overloaded assignment operator for deep copying
     805              :   ArrayElemsCopied &operator= (ArrayElemsCopied const &other);
     806              : 
     807              :   // move constructors
     808              :   ArrayElemsCopied (ArrayElemsCopied &&other) = default;
     809              :   ArrayElemsCopied &operator= (ArrayElemsCopied &&other) = default;
     810              : 
     811              :   std::string to_string () const override;
     812              : 
     813              :   void accept_vis (HIRFullVisitor &vis) override;
     814              : 
     815          723 :   Expr &get_elem_to_copy () { return *elem_to_copy; }
     816              : 
     817          509 :   Expr &get_num_copies_expr () { return *num_copies; }
     818              : 
     819          347 :   ArrayElems::ArrayExprType get_array_expr_type () const override final
     820              :   {
     821          347 :     return ArrayElems::ArrayExprType::COPIED;
     822              :   }
     823              : 
     824              : protected:
     825            0 :   ArrayElemsCopied *clone_array_elems_impl () const override
     826              :   {
     827            0 :     return new ArrayElemsCopied (*this);
     828              :   }
     829              : };
     830              : 
     831              : // Array definition-ish expression
     832              : class ArrayExpr : public ExprWithoutBlock, public WithInnerAttrs
     833              : {
     834              :   std::unique_ptr<ArrayElems> internal_elements;
     835              : 
     836              :   location_t locus;
     837              : 
     838              : public:
     839              :   std::string to_string () const override;
     840              : 
     841              :   // Returns whether array expr has array elems or if it is just empty.
     842            0 :   bool has_array_elems () const { return internal_elements != nullptr; }
     843              : 
     844              :   // Constructor requires ArrayElems pointer
     845              :   ArrayExpr (Analysis::NodeMapping mappings,
     846              :              std::unique_ptr<ArrayElems> array_elems,
     847              :              AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
     848              :              location_t locus);
     849              : 
     850              :   // Copy constructor requires cloning ArrayElems for polymorphism to hold
     851              :   ArrayExpr (ArrayExpr const &other);
     852              : 
     853              :   // Overload assignment operator to clone internal_elements
     854              :   ArrayExpr &operator= (ArrayExpr const &other);
     855              : 
     856              :   // move constructors
     857              :   ArrayExpr (ArrayExpr &&other) = default;
     858              :   ArrayExpr &operator= (ArrayExpr &&other) = default;
     859              : 
     860         3881 :   location_t get_locus () const override final { return locus; }
     861              : 
     862              :   void accept_vis (HIRFullVisitor &vis) override;
     863              :   void accept_vis (HIRExpressionVisitor &vis) override;
     864              : 
     865         2823 :   ArrayElems &get_internal_elements () { return *internal_elements; };
     866              : 
     867           32 :   ExprType get_expression_type () const override final
     868              :   {
     869           32 :     return ExprType::Array;
     870              :   }
     871              : 
     872              : protected:
     873              :   /* Use covariance to implement clone function as returning this object rather
     874              :    * than base */
     875            0 :   ArrayExpr *clone_expr_impl () const override { return new ArrayExpr (*this); }
     876              : 
     877              :   /* Use covariance to implement clone function as returning this object rather
     878              :    * than base */
     879            0 :   ArrayExpr *clone_expr_without_block_impl () const override
     880              :   {
     881            0 :     return new ArrayExpr (*this);
     882              :   }
     883              : };
     884              : 
     885              : class ArrayIndexExpr : public ExprWithoutBlock
     886              : {
     887              :   std::unique_ptr<Expr> array_expr;
     888              :   std::unique_ptr<Expr> index_expr;
     889              : 
     890              :   location_t locus;
     891              : 
     892              : public:
     893              :   std::string to_string () const override;
     894              : 
     895              :   ArrayIndexExpr (Analysis::NodeMapping mappings,
     896              :                   std::unique_ptr<Expr> array_expr,
     897              :                   std::unique_ptr<Expr> array_index_expr,
     898              :                   AST::AttrVec outer_attribs, location_t locus);
     899              : 
     900              :   // Copy constructor requires special cloning due to unique_ptr
     901              :   ArrayIndexExpr (ArrayIndexExpr const &other);
     902              : 
     903              :   // Overload assignment operator to clone unique_ptrs
     904              :   ArrayIndexExpr &operator= (ArrayIndexExpr const &other);
     905              : 
     906              :   // move constructors
     907              :   ArrayIndexExpr (ArrayIndexExpr &&other) = default;
     908              :   ArrayIndexExpr &operator= (ArrayIndexExpr &&other) = default;
     909              : 
     910         1185 :   location_t get_locus () const override final { return locus; }
     911              : 
     912              :   void accept_vis (HIRFullVisitor &vis) override;
     913              :   void accept_vis (HIRExpressionVisitor &vis) override;
     914              : 
     915         2112 :   Expr &get_array_expr () { return *array_expr; }
     916         2279 :   Expr &get_index_expr () { return *index_expr; }
     917              : 
     918            9 :   ExprType get_expression_type () const override final
     919              :   {
     920            9 :     return ExprType::ArrayIndex;
     921              :   }
     922              : 
     923              : protected:
     924              :   /* Use covariance to implement clone function as returning this object rather
     925              :    * than base */
     926            0 :   ArrayIndexExpr *clone_expr_impl () const override
     927              :   {
     928            0 :     return new ArrayIndexExpr (*this);
     929              :   }
     930              : 
     931              :   /* Use covariance to implement clone function as returning this object rather
     932              :    * than base */
     933            0 :   ArrayIndexExpr *clone_expr_without_block_impl () const override
     934              :   {
     935            0 :     return new ArrayIndexExpr (*this);
     936              :   }
     937              : };
     938              : 
     939              : // HIR representation of a tuple
     940              : class TupleExpr : public ExprWithoutBlock, public WithInnerAttrs
     941              : {
     942              :   std::vector<std::unique_ptr<Expr>> tuple_elems;
     943              :   // replaces (inlined version of) TupleElements
     944              : 
     945              :   location_t locus;
     946              : 
     947              : public:
     948              :   std::string to_string () const override;
     949              : 
     950              :   TupleExpr (Analysis::NodeMapping mappings,
     951              :              std::vector<std::unique_ptr<Expr>> tuple_elements,
     952              :              AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
     953              :              location_t locus);
     954              : 
     955              :   // copy constructor with vector clone
     956              :   TupleExpr (TupleExpr const &other);
     957              : 
     958              :   // overloaded assignment operator to vector clone
     959              :   TupleExpr &operator= (TupleExpr const &other);
     960              : 
     961              :   // move constructors
     962              :   TupleExpr (TupleExpr &&other) = default;
     963              :   TupleExpr &operator= (TupleExpr &&other) = default;
     964              : 
     965              :   /* Note: syntactically, can disambiguate single-element tuple from parens with
     966              :    * comma, i.e. (0,) rather than (0) */
     967              : 
     968         2437 :   location_t get_locus () const override final { return locus; }
     969              : 
     970              :   void accept_vis (HIRFullVisitor &vis) override;
     971              :   void accept_vis (HIRExpressionVisitor &vis) override;
     972              : 
     973              :   const std::vector<std::unique_ptr<Expr>> &get_tuple_elems () const
     974              :   {
     975              :     return tuple_elems;
     976              :   }
     977         3424 :   std::vector<std::unique_ptr<Expr>> &get_tuple_elems () { return tuple_elems; }
     978              : 
     979         1131 :   bool is_unit () const { return tuple_elems.size () == 0; }
     980              : 
     981            0 :   ExprType get_expression_type () const override final
     982              :   {
     983            0 :     return ExprType::Tuple;
     984              :   }
     985              : 
     986              : protected:
     987              :   /* Use covariance to implement clone function as returning this object rather
     988              :    * than base */
     989            0 :   TupleExpr *clone_expr_impl () const override { return new TupleExpr (*this); }
     990              : 
     991              :   /* Use covariance to implement clone function as returning this object rather
     992              :    * than base */
     993            0 :   TupleExpr *clone_expr_without_block_impl () const override
     994              :   {
     995            0 :     return new TupleExpr (*this);
     996              :   }
     997              : };
     998              : 
     999              : class TupleIndexExpr : public ExprWithoutBlock
    1000              : {
    1001              :   std::unique_ptr<Expr> tuple_expr;
    1002              :   TupleIndex tuple_index;
    1003              :   location_t locus;
    1004              : 
    1005              : public:
    1006              :   std::string to_string () const override;
    1007              : 
    1008         1774 :   TupleIndex get_tuple_index () const { return tuple_index; }
    1009              : 
    1010              :   TupleIndexExpr (Analysis::NodeMapping mappings,
    1011              :                   std::unique_ptr<Expr> tuple_expr, TupleIndex index,
    1012              :                   AST::AttrVec outer_attribs, location_t locus);
    1013              : 
    1014              :   // Copy constructor requires a clone for tuple_expr
    1015              :   TupleIndexExpr (TupleIndexExpr const &other);
    1016              : 
    1017              :   // Overload assignment operator in order to clone
    1018              :   TupleIndexExpr &operator= (TupleIndexExpr const &other);
    1019              : 
    1020              :   // move constructors
    1021              :   TupleIndexExpr (TupleIndexExpr &&other) = default;
    1022              :   TupleIndexExpr &operator= (TupleIndexExpr &&other) = default;
    1023              : 
    1024         2856 :   location_t get_locus () const override final { return locus; }
    1025              : 
    1026              :   void accept_vis (HIRFullVisitor &vis) override;
    1027              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1028              : 
    1029         5898 :   Expr &get_tuple_expr () { return *tuple_expr; }
    1030              : 
    1031            2 :   ExprType get_expression_type () const override final
    1032              :   {
    1033            2 :     return ExprType::TupleIdx;
    1034              :   }
    1035              : 
    1036              : protected:
    1037              :   /* Use covariance to implement clone function as returning this object rather
    1038              :    * than base */
    1039            0 :   TupleIndexExpr *clone_expr_impl () const override
    1040              :   {
    1041            0 :     return new TupleIndexExpr (*this);
    1042              :   }
    1043              : 
    1044              :   /* Use covariance to implement clone function as returning this object rather
    1045              :    * than base */
    1046            0 :   TupleIndexExpr *clone_expr_without_block_impl () const override
    1047              :   {
    1048            0 :     return new TupleIndexExpr (*this);
    1049              :   }
    1050              : };
    1051              : 
    1052              : // Base struct/tuple/union value creator HIR node (abstract)
    1053              : class StructExpr : public ExprWithoutBlock
    1054              : {
    1055              : protected:
    1056              :   PathInExpression struct_name;
    1057              : 
    1058              :   // Protected constructor to allow initialising struct_name
    1059              :   StructExpr (Analysis::NodeMapping mappings, PathInExpression struct_path,
    1060              :               AST::AttrVec outer_attribs);
    1061              : 
    1062              : public:
    1063         1604 :   PathInExpression &get_struct_name () { return struct_name; }
    1064              : 
    1065              :   std::string to_string () const override;
    1066              : 
    1067            3 :   ExprType get_expression_type () const override final
    1068              :   {
    1069            3 :     return ExprType::Struct;
    1070              :   }
    1071              : };
    1072              : 
    1073              : // Actual HIR node of the struct creator (with no fields). Not abstract!
    1074              : class StructExprStruct : public StructExpr, public WithInnerAttrs
    1075              : {
    1076              :   location_t locus;
    1077              : 
    1078              : public:
    1079              :   std::string to_string () const override;
    1080              : 
    1081              :   // Constructor has to call protected constructor of base class
    1082              :   StructExprStruct (Analysis::NodeMapping mappings,
    1083              :                     PathInExpression struct_path, AST::AttrVec inner_attribs,
    1084              :                     AST::AttrVec outer_attribs, location_t locus);
    1085              : 
    1086         5001 :   location_t get_locus () const override final { return locus; }
    1087              : 
    1088              :   void accept_vis (HIRFullVisitor &vis) override;
    1089              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1090              : 
    1091              : protected:
    1092              :   /* Use covariance to implement clone function as returning this object rather
    1093              :    * than base */
    1094            0 :   StructExprStruct *clone_expr_impl () const override
    1095              :   {
    1096            0 :     return new StructExprStruct (*this);
    1097              :   }
    1098              : 
    1099              :   /* Use covariance to implement clone function as returning this object rather
    1100              :    * than base */
    1101            0 :   StructExprStruct *clone_expr_without_block_impl () const override
    1102              :   {
    1103            0 :     return new StructExprStruct (*this);
    1104              :   }
    1105              : };
    1106              : 
    1107              : /* HIR node representing expression used to fill a struct's fields from another
    1108              :  * struct */
    1109              : struct StructBase
    1110              : {
    1111              : private:
    1112              :   std::unique_ptr<Expr> base_struct;
    1113              : 
    1114              : public:
    1115              :   // TODO: should this store location data?
    1116              :   StructBase (std::unique_ptr<Expr> base_struct_ptr);
    1117              : 
    1118              :   // Copy constructor requires clone
    1119              :   StructBase (StructBase const &other);
    1120              : 
    1121              :   // Destructor
    1122            0 :   ~StructBase () = default;
    1123              : 
    1124              :   // Overload assignment operator to clone base_struct
    1125              :   StructBase &operator= (StructBase const &other);
    1126              : 
    1127              :   // move constructors
    1128            0 :   StructBase (StructBase &&other) = default;
    1129              :   StructBase &operator= (StructBase &&other) = default;
    1130              : 
    1131              :   // Returns a null expr-ed StructBase - error state
    1132              :   static StructBase error () { return StructBase (nullptr); }
    1133              : 
    1134              :   // Returns whether StructBase is in error state
    1135              :   bool is_invalid () const { return base_struct == nullptr; }
    1136              : 
    1137              :   std::string to_string () const;
    1138              : 
    1139         2716 :   Expr &get_base () { return *base_struct; }
    1140              : };
    1141              : 
    1142              : /* Base HIR node for a single struct expression field (in struct instance
    1143              :  * creation) - abstract */
    1144            0 : class StructExprField : public FullVisitable
    1145              : {
    1146              : public:
    1147              :   enum StructExprFieldKind
    1148              :   {
    1149              :     IDENTIFIER_VALUE,
    1150              :     IDENTIFIER,
    1151              :     INDEX_VALUE,
    1152              :   };
    1153              : 
    1154              :   virtual ~StructExprField () {}
    1155              : 
    1156              :   // Unique pointer custom clone function
    1157            0 :   std::unique_ptr<StructExprField> clone_struct_expr_field () const
    1158              :   {
    1159            0 :     return std::unique_ptr<StructExprField> (clone_struct_expr_field_impl ());
    1160              :   }
    1161              : 
    1162              :   virtual std::string to_string () const = 0;
    1163              : 
    1164              :   virtual void accept_vis (HIRFullVisitor &vis) = 0;
    1165              :   virtual void accept_vis (HIRExpressionVisitor &vis) = 0;
    1166              : 
    1167        14228 :   Analysis::NodeMapping &get_mappings () { return mappings; }
    1168              : 
    1169         5972 :   location_t get_locus () { return locus; }
    1170              : 
    1171              :   virtual StructExprFieldKind get_kind () const = 0;
    1172              : 
    1173              : protected:
    1174              :   // pure virtual clone implementation
    1175              :   virtual StructExprField *clone_struct_expr_field_impl () const = 0;
    1176              : 
    1177              :   StructExprField (Analysis::NodeMapping mapping, location_t locus);
    1178              : 
    1179              :   Analysis::NodeMapping mappings;
    1180              :   location_t locus;
    1181              : };
    1182              : 
    1183              : // Identifier-only variant of StructExprField HIR node
    1184            0 : class StructExprFieldIdentifier : public StructExprField
    1185              : {
    1186              : private:
    1187              :   Identifier field_name;
    1188              : 
    1189              :   // TODO: should this store location data?
    1190              : public:
    1191              :   StructExprFieldIdentifier (Analysis::NodeMapping mapping,
    1192              :                              Identifier field_identifier, location_t locus);
    1193              : 
    1194            0 :   std::string to_string () const override { return field_name.as_string (); }
    1195              : 
    1196              :   void accept_vis (HIRFullVisitor &vis) override;
    1197              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1198              : 
    1199          845 :   Identifier get_field_name () const { return field_name; }
    1200              : 
    1201          413 :   StructExprFieldKind get_kind () const override
    1202              :   {
    1203          413 :     return StructExprFieldKind::IDENTIFIER;
    1204              :   }
    1205              : 
    1206              : protected:
    1207              :   /* Use covariance to implement clone function as returning this object rather
    1208              :    * than base */
    1209            0 :   StructExprFieldIdentifier *clone_struct_expr_field_impl () const override
    1210              :   {
    1211            0 :     return new StructExprFieldIdentifier (*this);
    1212              :   }
    1213              : };
    1214              : 
    1215              : /* Base HIR node for a single struct expression field with an assigned value -
    1216              :  * abstract */
    1217              : class StructExprFieldWithVal : public StructExprField
    1218              : {
    1219              :   std::unique_ptr<Expr> value;
    1220              : 
    1221              : protected:
    1222              :   StructExprFieldWithVal (Analysis::NodeMapping mapping,
    1223              :                           std::unique_ptr<Expr> field_value, location_t locus);
    1224              : 
    1225              :   // Copy constructor requires clone
    1226              :   StructExprFieldWithVal (StructExprFieldWithVal const &other);
    1227              : 
    1228              :   // Overload assignment operator to clone unique_ptr
    1229              :   StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other);
    1230              : 
    1231              :   // move constructors
    1232              :   StructExprFieldWithVal (StructExprFieldWithVal &&other) = default;
    1233              :   StructExprFieldWithVal &operator= (StructExprFieldWithVal &&other) = default;
    1234              : 
    1235              : public:
    1236              :   std::string to_string () const override;
    1237              : 
    1238        18156 :   Expr &get_value () { return *value; }
    1239              : };
    1240              : 
    1241              : // Identifier and value variant of StructExprField HIR node
    1242              : class StructExprFieldIdentifierValue : public StructExprFieldWithVal
    1243              : {
    1244              : public:
    1245              :   Identifier field_name;
    1246              : 
    1247              :   // TODO: should this store location data?
    1248              : 
    1249              :   StructExprFieldIdentifierValue (Analysis::NodeMapping mapping,
    1250              :                                   Identifier field_identifier,
    1251              :                                   std::unique_ptr<Expr> field_value,
    1252              :                                   location_t locus);
    1253              : 
    1254              :   std::string to_string () const override;
    1255              : 
    1256              :   void accept_vis (HIRFullVisitor &vis) override;
    1257              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1258              : 
    1259            4 :   Identifier get_field_name () const { return field_name; }
    1260              : 
    1261         4643 :   StructExprFieldKind get_kind () const override
    1262              :   {
    1263         4643 :     return StructExprFieldKind::IDENTIFIER_VALUE;
    1264              :   }
    1265              : 
    1266              : protected:
    1267              :   /* Use covariance to implement clone function as returning this object rather
    1268              :    * than base */
    1269            0 :   StructExprFieldIdentifierValue *clone_struct_expr_field_impl () const override
    1270              :   {
    1271            0 :     return new StructExprFieldIdentifierValue (*this);
    1272              :   }
    1273              : };
    1274              : 
    1275              : // Tuple index and value variant of StructExprField HIR node
    1276            0 : class StructExprFieldIndexValue : public StructExprFieldWithVal
    1277              : {
    1278              : public:
    1279              :   TupleIndex index;
    1280              : 
    1281              :   // TODO: should this store location data?
    1282              : 
    1283              :   StructExprFieldIndexValue (Analysis::NodeMapping mapping,
    1284              :                              TupleIndex tuple_index,
    1285              :                              std::unique_ptr<Expr> field_value,
    1286              :                              location_t locus);
    1287              : 
    1288              :   std::string to_string () const override;
    1289              : 
    1290           44 :   TupleIndex get_tuple_index () const { return index; };
    1291              : 
    1292              :   void accept_vis (HIRFullVisitor &vis) override;
    1293              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1294              : 
    1295           86 :   StructExprFieldKind get_kind () const override
    1296              :   {
    1297           86 :     return StructExprFieldKind::INDEX_VALUE;
    1298              :   }
    1299              : 
    1300              : protected:
    1301              :   /* Use covariance to implement clone function as returning this object rather
    1302              :    * than base */
    1303            0 :   StructExprFieldIndexValue *clone_struct_expr_field_impl () const override
    1304              :   {
    1305            0 :     return new StructExprFieldIndexValue (*this);
    1306              :   }
    1307              : };
    1308              : 
    1309              : // HIR node of a struct creator with fields
    1310              : class StructExprStructFields : public StructExprStruct
    1311              : {
    1312              :   // std::vector<StructExprField> fields;
    1313              :   std::vector<std::unique_ptr<StructExprField>> fields;
    1314              :   tl::optional<std::unique_ptr<StructBase>> struct_base;
    1315              : 
    1316              : public:
    1317              :   // For unions there is just one field, the index
    1318              :   // is set when type checking
    1319              :   int union_index = -1;
    1320              : 
    1321              :   std::string to_string () const override;
    1322              : 
    1323         2966 :   bool has_struct_base () const { return struct_base.has_value (); }
    1324              : 
    1325              :   // Constructor for StructExprStructFields when no struct base is used
    1326              :   StructExprStructFields (
    1327              :     Analysis::NodeMapping mappings, PathInExpression struct_path,
    1328              :     std::vector<std::unique_ptr<StructExprField>> expr_fields, location_t locus,
    1329              :     tl::optional<std::unique_ptr<StructBase>> base_struct,
    1330              :     AST::AttrVec inner_attribs, AST::AttrVec outer_attribs);
    1331              : 
    1332              :   // copy constructor with vector clone
    1333              :   StructExprStructFields (StructExprStructFields const &other);
    1334              : 
    1335              :   // overloaded assignment operator with vector clone
    1336              :   StructExprStructFields &operator= (StructExprStructFields const &other);
    1337              : 
    1338              :   // move constructors
    1339              :   StructExprStructFields (StructExprStructFields &&other) = default;
    1340              :   StructExprStructFields &operator= (StructExprStructFields &&other) = default;
    1341              : 
    1342              :   void accept_vis (HIRFullVisitor &vis) override;
    1343              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1344              : 
    1345         3476 :   std::vector<std::unique_ptr<StructExprField>> &get_fields ()
    1346              :   {
    1347        12578 :     return fields;
    1348              :   };
    1349              : 
    1350              :   const std::vector<std::unique_ptr<StructExprField>> &get_fields () const
    1351              :   {
    1352              :     return fields;
    1353              :   };
    1354              : 
    1355         2653 :   StructBase &get_struct_base () { return *struct_base.value (); }
    1356              : 
    1357              :   void
    1358         1159 :   set_fields_as_owner (std::vector<std::unique_ptr<StructExprField>> new_fields)
    1359              :   {
    1360         1159 :     fields = std::move (new_fields);
    1361              :   }
    1362              : 
    1363              : protected:
    1364              :   /* Use covariance to implement clone function as returning this object rather
    1365              :    * than base */
    1366            0 :   StructExprStructFields *clone_expr_impl () const override
    1367              :   {
    1368            0 :     return new StructExprStructFields (*this);
    1369              :   }
    1370              : 
    1371              :   /* Use covariance to implement clone function as returning this object rather
    1372              :    * than base */
    1373            0 :   StructExprStructFields *clone_expr_without_block_impl () const override
    1374              :   {
    1375            0 :     return new StructExprStructFields (*this);
    1376              :   }
    1377              : };
    1378              : 
    1379              : // HIR node of the functional update struct creator
    1380              : class StructExprStructBase : public StructExprStruct
    1381              : {
    1382              :   StructBase struct_base;
    1383              : 
    1384              : public:
    1385              :   StructExprStructBase (Analysis::NodeMapping mappings,
    1386              :                         PathInExpression struct_path, StructBase base_struct,
    1387              :                         AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
    1388              :                         location_t locus);
    1389              : 
    1390              :   void accept_vis (HIRFullVisitor &vis) override;
    1391              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1392              : 
    1393            0 :   StructBase &get_struct_base () { return struct_base; }
    1394              : 
    1395              : protected:
    1396              :   /* Use covariance to implement clone function as returning this object rather
    1397              :    * than base */
    1398            0 :   StructExprStructBase *clone_expr_impl () const override
    1399              :   {
    1400            0 :     return new StructExprStructBase (*this);
    1401              :   }
    1402              : 
    1403              :   /* Use covariance to implement clone function as returning this object rather
    1404              :    * than base */
    1405            0 :   StructExprStructBase *clone_expr_without_block_impl () const override
    1406              :   {
    1407            0 :     return new StructExprStructBase (*this);
    1408              :   }
    1409              : };
    1410              : 
    1411              : // Function call expression HIR node
    1412              : class CallExpr : public ExprWithoutBlock
    1413              : {
    1414              :   std::unique_ptr<Expr> function;
    1415              :   std::vector<std::unique_ptr<Expr>> params;
    1416              :   location_t locus;
    1417              : 
    1418              : public:
    1419              :   std::string to_string () const override;
    1420              : 
    1421              :   CallExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> function_expr,
    1422              :             std::vector<std::unique_ptr<Expr>> function_params,
    1423              :             AST::AttrVec outer_attribs, location_t locus);
    1424              : 
    1425              :   // copy constructor requires clone
    1426              :   CallExpr (CallExpr const &other);
    1427              : 
    1428              :   // Overload assignment operator to clone
    1429              :   CallExpr &operator= (CallExpr const &other);
    1430              : 
    1431              :   // move constructors
    1432              :   CallExpr (CallExpr &&other) = default;
    1433              :   CallExpr &operator= (CallExpr &&other) = default;
    1434              : 
    1435              :   // Returns whether function call has parameters.
    1436        21175 :   bool has_params () const { return !params.empty (); }
    1437              : 
    1438        76252 :   location_t get_locus () const override final { return locus; }
    1439              : 
    1440              :   void accept_vis (HIRFullVisitor &vis) override;
    1441              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1442              : 
    1443        32115 :   bool has_fnexpr () const { return function != nullptr; }
    1444        94445 :   Expr &get_fnexpr () { return *function; }
    1445              : 
    1446        26629 :   size_t num_params () const { return params.size (); }
    1447              : 
    1448        55208 :   std::vector<std::unique_ptr<Expr>> &get_arguments () { return params; }
    1449              : 
    1450              :   const std::vector<std::unique_ptr<Expr>> &get_arguments () const
    1451              :   {
    1452              :     return params;
    1453              :   }
    1454              : 
    1455           36 :   ExprType get_expression_type () const override final
    1456              :   {
    1457           36 :     return ExprType::Call;
    1458              :   }
    1459              : 
    1460              : protected:
    1461              :   /* Use covariance to implement clone function as returning this object rather
    1462              :    * than base */
    1463            8 :   CallExpr *clone_expr_impl () const override { return new CallExpr (*this); }
    1464              : 
    1465              :   /* Use covariance to implement clone function as returning this object rather
    1466              :    * than base */
    1467            0 :   CallExpr *clone_expr_without_block_impl () const override
    1468              :   {
    1469            0 :     return new CallExpr (*this);
    1470              :   }
    1471              : };
    1472              : 
    1473              : // Method call expression HIR node
    1474              : class MethodCallExpr : public ExprWithoutBlock
    1475              : {
    1476              :   std::unique_ptr<Expr> receiver;
    1477              :   PathExprSegment method_name;
    1478              :   std::vector<std::unique_ptr<Expr>> params;
    1479              :   location_t locus;
    1480              : 
    1481              : public:
    1482              :   std::string to_string () const override;
    1483              : 
    1484              :   MethodCallExpr (Analysis::NodeMapping mappings,
    1485              :                   std::unique_ptr<Expr> call_receiver,
    1486              :                   PathExprSegment method_path,
    1487              :                   std::vector<std::unique_ptr<Expr>> method_params,
    1488              :                   AST::AttrVec outer_attribs, location_t locus);
    1489              : 
    1490              :   // copy constructor required due to cloning
    1491              :   MethodCallExpr (MethodCallExpr const &other);
    1492              : 
    1493              :   // Overload assignment operator to clone receiver object
    1494              :   MethodCallExpr &operator= (MethodCallExpr const &other);
    1495              : 
    1496              :   // move constructors
    1497              :   MethodCallExpr (MethodCallExpr &&other) = default;
    1498              :   MethodCallExpr &operator= (MethodCallExpr &&other) = default;
    1499              : 
    1500        25101 :   location_t get_locus () const override final { return locus; }
    1501              : 
    1502              :   void accept_vis (HIRFullVisitor &vis) override;
    1503              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1504              : 
    1505        32931 :   Expr &get_receiver () { return *receiver; }
    1506              : 
    1507         2857 :   PathExprSegment &get_method_name () { return method_name; };
    1508              :   const PathExprSegment &get_method_name () const { return method_name; };
    1509              : 
    1510              :   bool has_params () const { return !params.empty (); }
    1511              :   size_t num_params () const { return params.size (); }
    1512              : 
    1513        18625 :   std::vector<std::unique_ptr<Expr>> &get_arguments () { return params; }
    1514              : 
    1515              :   const std::vector<std::unique_ptr<Expr>> &get_arguments () const
    1516              :   {
    1517              :     return params;
    1518              :   }
    1519              : 
    1520            0 :   ExprType get_expression_type () const override final
    1521              :   {
    1522            0 :     return ExprType::MethodCall;
    1523              :   }
    1524              : 
    1525              : protected:
    1526              :   /* Use covariance to implement clone function as returning this object rather
    1527              :    * than base */
    1528            0 :   MethodCallExpr *clone_expr_impl () const override
    1529              :   {
    1530            0 :     return new MethodCallExpr (*this);
    1531              :   }
    1532              : 
    1533              :   /* Use covariance to implement clone function as returning this object rather
    1534              :    * than base */
    1535            0 :   MethodCallExpr *clone_expr_without_block_impl () const override
    1536              :   {
    1537            0 :     return new MethodCallExpr (*this);
    1538              :   }
    1539              : };
    1540              : 
    1541              : // aka FieldExpression
    1542              : // Struct or union field access expression HIR node
    1543              : class FieldAccessExpr : public ExprWithoutBlock
    1544              : {
    1545              :   std::unique_ptr<Expr> receiver;
    1546              :   Identifier field;
    1547              : 
    1548              :   location_t locus;
    1549              : 
    1550              : public:
    1551              :   std::string to_string () const override;
    1552              : 
    1553              :   FieldAccessExpr (Analysis::NodeMapping mappings,
    1554              :                    std::unique_ptr<Expr> field_access_receiver,
    1555              :                    Identifier field_name, AST::AttrVec outer_attribs,
    1556              :                    location_t locus);
    1557              : 
    1558              :   // Copy constructor required due to unique_ptr cloning
    1559              :   FieldAccessExpr (FieldAccessExpr const &other);
    1560              : 
    1561              :   // Overload assignment operator to clone unique_ptr
    1562              :   FieldAccessExpr &operator= (FieldAccessExpr const &other);
    1563              : 
    1564              :   // move constructors
    1565              :   FieldAccessExpr (FieldAccessExpr &&other) = default;
    1566              :   FieldAccessExpr &operator= (FieldAccessExpr &&other) = default;
    1567              : 
    1568        16889 :   location_t get_locus () const override final { return locus; }
    1569              : 
    1570              :   void accept_vis (HIRFullVisitor &vis) override;
    1571              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1572              : 
    1573        41613 :   Expr &get_receiver_expr () { return *receiver; }
    1574              : 
    1575        13907 :   Identifier get_field_name () const { return field; }
    1576              : 
    1577            0 :   ExprType get_expression_type () const override final
    1578              :   {
    1579            0 :     return ExprType::FieldAccess;
    1580              :   }
    1581              : 
    1582              : protected:
    1583              :   /* Use covariance to implement clone function as returning this object rather
    1584              :    * than base */
    1585            0 :   FieldAccessExpr *clone_expr_impl () const override
    1586              :   {
    1587            0 :     return new FieldAccessExpr (*this);
    1588              :   }
    1589              : 
    1590              :   /* Use covariance to implement clone function as returning this object rather
    1591              :    * than base */
    1592            0 :   FieldAccessExpr *clone_expr_without_block_impl () const override
    1593              :   {
    1594            0 :     return new FieldAccessExpr (*this);
    1595              :   }
    1596              : };
    1597              : 
    1598              : // Closure parameter data structure
    1599              : struct ClosureParam
    1600              : {
    1601              : private:
    1602              :   std::vector<AST::Attribute> outer_attrs;
    1603              :   std::unique_ptr<Pattern> pattern;
    1604              :   std::unique_ptr<Type> type;
    1605              :   location_t locus;
    1606              : 
    1607              : public:
    1608              :   // Returns whether the type of the parameter has been given.
    1609           60 :   bool has_type_given () const { return type != nullptr; }
    1610              : 
    1611              :   // Constructor for closure parameter
    1612              :   ClosureParam (std::unique_ptr<Pattern> param_pattern, location_t locus,
    1613              :                 std::unique_ptr<Type> param_type = nullptr,
    1614              :                 std::vector<AST::Attribute> outer_attrs = {});
    1615              : 
    1616              :   // Copy constructor required due to cloning as a result of unique_ptrs
    1617              :   ClosureParam (ClosureParam const &other);
    1618              : 
    1619           61 :   ~ClosureParam () = default;
    1620              : 
    1621              :   // Assignment operator must be overloaded to clone as well
    1622              :   ClosureParam &operator= (ClosureParam const &other);
    1623              : 
    1624              :   // move constructors
    1625           61 :   ClosureParam (ClosureParam &&other) = default;
    1626              :   ClosureParam &operator= (ClosureParam &&other) = default;
    1627              : 
    1628              :   std::string to_string () const;
    1629              : 
    1630              :   const std::vector<AST::Attribute> &get_outer_attrs () const
    1631              :   {
    1632              :     return outer_attrs;
    1633              :   }
    1634            0 :   std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; }
    1635              : 
    1636          121 :   Pattern &get_pattern () { return *pattern; }
    1637              : 
    1638           58 :   Type &get_type () { return *type; }
    1639              : 
    1640           59 :   location_t get_locus () const { return locus; }
    1641              : };
    1642              : 
    1643              : // Base closure definition expression HIR node - abstract
    1644              : class ClosureExpr : public ExprWithoutBlock
    1645              : {
    1646              : private:
    1647              :   bool has_move;
    1648              :   std::vector<ClosureParam> params;
    1649              :   location_t locus;
    1650              :   std::unique_ptr<Type> return_type;
    1651              :   std::unique_ptr<Expr> expr;
    1652              : 
    1653              : public:
    1654              :   ClosureExpr (Analysis::NodeMapping mappings,
    1655              :                std::vector<ClosureParam> closure_params,
    1656              :                std::unique_ptr<Type> closure_return_type,
    1657              :                std::unique_ptr<Expr> closure_expr, bool has_move,
    1658              :                AST::AttrVec outer_attribs, location_t locus);
    1659              : 
    1660              :   // Copy constructor requires cloning
    1661              :   ClosureExpr (ClosureExpr const &other);
    1662              : 
    1663              :   // Overload assignment operator to clone unique_ptrs
    1664              :   ClosureExpr &operator= (ClosureExpr const &other);
    1665              : 
    1666              :   // move constructors
    1667              :   ClosureExpr (ClosureExpr &&other) = default;
    1668              :   ClosureExpr &operator= (ClosureExpr &&other) = default;
    1669              : 
    1670              :   std::string to_string () const override;
    1671              : 
    1672         1121 :   location_t get_locus () const override final { return locus; }
    1673              : 
    1674            1 :   ExprType get_expression_type () const override final
    1675              :   {
    1676            1 :     return ExprType::Closure;
    1677              :   }
    1678              : 
    1679              :   bool get_has_move () const { return has_move; }
    1680              : 
    1681          137 :   bool has_return_type () const { return return_type != nullptr; }
    1682              : 
    1683            0 :   Type &get_return_type () { return *return_type; };
    1684          358 :   Expr &get_expr () { return *expr; }
    1685              : 
    1686            0 :   bool has_params () const { return !params.empty (); }
    1687          133 :   std::vector<ClosureParam> &get_params () { return params; }
    1688              : 
    1689              :   void accept_vis (HIRFullVisitor &vis) override;
    1690              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1691              : 
    1692              : protected:
    1693              :   /* Use covariance to implement clone function as returning this object rather
    1694              :    * than base */
    1695            0 :   ClosureExpr *clone_expr_impl () const override
    1696              :   {
    1697            0 :     return new ClosureExpr (*this);
    1698              :   }
    1699              : 
    1700              :   /* Use covariance to implement clone function as returning this object rather
    1701              :    * than base */
    1702            0 :   ClosureExpr *clone_expr_without_block_impl () const override
    1703              :   {
    1704            0 :     return new ClosureExpr (*this);
    1705              :   }
    1706              : };
    1707              : 
    1708              : // A block HIR node
    1709              : class BlockExpr : public ExprWithBlock, public WithInnerAttrs
    1710              : {
    1711              :   // FIXME this should be private + get/set
    1712              : public:
    1713              :   std::vector<std::unique_ptr<Stmt>> statements;
    1714              :   std::unique_ptr<Expr> expr;
    1715              :   bool tail_reachable;
    1716              :   tl::optional<LoopLabel> label;
    1717              :   location_t start_locus;
    1718              :   location_t end_locus;
    1719              : 
    1720              :   std::string to_string () const override;
    1721              : 
    1722        20436 :   AST::AttrVec get_inner_attrs () const { return inner_attrs; }
    1723              : 
    1724              :   // Returns whether the block contains statements.
    1725              :   bool has_statements () const { return !statements.empty (); }
    1726              : 
    1727              :   // Returns whether the block contains an expression
    1728       147513 :   bool has_expr () const { return expr != nullptr; }
    1729              : 
    1730         5928 :   bool is_tail_reachable () const { return tail_reachable; }
    1731              : 
    1732              :   BlockExpr (Analysis::NodeMapping mappings,
    1733              :              std::vector<std::unique_ptr<Stmt>> block_statements,
    1734              :              std::unique_ptr<Expr> block_expr, bool tail_reachable,
    1735              :              AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
    1736              :              tl::optional<LoopLabel> label, location_t start_locus,
    1737              :              location_t end_locus);
    1738              : 
    1739              :   // Copy constructor with clone
    1740              :   BlockExpr (BlockExpr const &other);
    1741              : 
    1742              :   // Overloaded assignment operator to clone pointer
    1743              :   BlockExpr &operator= (BlockExpr const &other);
    1744              : 
    1745              :   // move constructors
    1746              :   BlockExpr (BlockExpr &&other) = default;
    1747              :   BlockExpr &operator= (BlockExpr &&other) = default;
    1748              : 
    1749              :   // Unique pointer custom clone function
    1750            0 :   std::unique_ptr<BlockExpr> clone_block_expr () const
    1751              :   {
    1752            0 :     return std::unique_ptr<BlockExpr> (clone_block_expr_impl ());
    1753              :   }
    1754              : 
    1755        92497 :   location_t get_locus () const override final { return start_locus; }
    1756              : 
    1757            0 :   location_t get_start_locus () const { return start_locus; }
    1758              : 
    1759        20064 :   location_t get_end_locus () const { return end_locus; }
    1760              : 
    1761              :   void accept_vis (HIRFullVisitor &vis) override;
    1762              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1763              : 
    1764              :   bool is_final_stmt (Stmt *stmt) { return statements.back ().get () == stmt; }
    1765              : 
    1766        19248 :   bool has_final_expr () { return expr != nullptr; }
    1767       123324 :   Expr &get_final_expr () { return *expr; }
    1768              : 
    1769       188595 :   std::vector<std::unique_ptr<Stmt>> &get_statements () { return statements; }
    1770              : 
    1771           91 :   ExprType get_expression_type () const final override
    1772              :   {
    1773           91 :     return ExprType::Block;
    1774              :   }
    1775              : 
    1776        27070 :   bool has_label () const { return label.has_value (); }
    1777            0 :   LoopLabel &get_label () { return label.value (); }
    1778              : 
    1779              : protected:
    1780              :   /* Use covariance to implement clone function as returning this object rather
    1781              :    * than base */
    1782           37 :   BlockExpr *clone_expr_impl () const override
    1783              :   {
    1784           37 :     return clone_block_expr_impl ();
    1785              :   }
    1786              : 
    1787              :   /* Use covariance to implement clone function as returning this object rather
    1788              :    * than base */
    1789            0 :   BlockExpr *clone_expr_with_block_impl () const override
    1790              :   {
    1791            0 :     return clone_block_expr_impl ();
    1792              :   }
    1793              : 
    1794              :   /* This is the base method as not an abstract class - not virtual but could be
    1795              :    * in future if required. */
    1796           37 :   /*virtual*/ BlockExpr *clone_block_expr_impl () const
    1797              :   {
    1798           37 :     return new BlockExpr (*this);
    1799              :   }
    1800              : };
    1801              : 
    1802              : class AnonConst : public ExprWithBlock
    1803              : {
    1804              : public:
    1805              :   enum class Kind
    1806              :   {
    1807              :     Explicit,
    1808              :     DeferredInference
    1809              :   };
    1810              : 
    1811              :   AnonConst (Analysis::NodeMapping mappings, std::unique_ptr<Expr> &&expr,
    1812              :              location_t locus = UNKNOWN_LOCATION);
    1813              :   AnonConst (Analysis::NodeMapping mappings,
    1814              :              location_t locus = UNKNOWN_LOCATION);
    1815              :   AnonConst (const AnonConst &other);
    1816              :   AnonConst operator= (const AnonConst &other);
    1817              : 
    1818              :   std::string to_string () const override;
    1819              : 
    1820              :   void accept_vis (HIRFullVisitor &vis) override;
    1821              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1822              : 
    1823          641 :   ExprType get_expression_type () const final override
    1824              :   {
    1825          641 :     return ExprType::AnonConst;
    1826              :   }
    1827              : 
    1828         4518 :   location_t get_locus () const override { return locus; }
    1829              : 
    1830         2208 :   Expr &get_inner_expr ()
    1831              :   {
    1832         2208 :     rust_assert (kind == Kind::Explicit);
    1833         2208 :     return *expr.value ();
    1834              :   }
    1835              : 
    1836            0 :   const Expr &get_inner_expr () const
    1837              :   {
    1838            0 :     rust_assert (kind == Kind::Explicit);
    1839            0 :     return *expr.value ();
    1840              :   }
    1841              : 
    1842         1155 :   bool is_deferred () const { return kind == Kind::DeferredInference; }
    1843              : 
    1844              : private:
    1845              :   location_t locus;
    1846              :   Kind kind;
    1847              :   tl::optional<std::unique_ptr<Expr>> expr;
    1848              : 
    1849            7 :   AnonConst *clone_expr_with_block_impl () const override
    1850              :   {
    1851            7 :     return new AnonConst (*this);
    1852              :   }
    1853              : };
    1854              : 
    1855              : class ConstBlock : public ExprWithBlock
    1856              : {
    1857              : public:
    1858              :   ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr,
    1859              :               location_t locus = UNKNOWN_LOCATION,
    1860              :               AST::AttrVec outer_attrs = {});
    1861              :   ConstBlock (const ConstBlock &other);
    1862              :   ConstBlock operator= (const ConstBlock &other);
    1863              : 
    1864              :   void accept_vis (HIRFullVisitor &vis) override;
    1865              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1866              : 
    1867              :   std::string to_string () const override;
    1868              : 
    1869            8 :   ExprType get_expression_type () const final override
    1870              :   {
    1871            8 :     return ExprType::ConstBlock;
    1872              :   }
    1873              : 
    1874           76 :   location_t get_locus () const override { return locus; }
    1875           82 :   AnonConst &get_const_expr () { return expr; }
    1876            0 :   const AnonConst &get_const_expr () const { return expr; }
    1877              : 
    1878              : private:
    1879              :   AnonConst expr;
    1880              :   location_t locus;
    1881              : 
    1882            0 :   ConstBlock *clone_expr_with_block_impl () const override
    1883              :   {
    1884            0 :     return new ConstBlock (*this);
    1885              :   }
    1886              : };
    1887              : 
    1888              : // HIR node representing continue expression within loops
    1889              : class ContinueExpr : public ExprWithoutBlock
    1890              : {
    1891              :   tl::optional<Lifetime> label;
    1892              :   location_t locus;
    1893              : 
    1894              : public:
    1895              :   std::string to_string () const override;
    1896              : 
    1897              :   // Returns true if the continue expr has a label.
    1898           24 :   bool has_label () const { return label.has_value (); }
    1899              : 
    1900              :   // Constructor for a ContinueExpr with a label.
    1901              :   ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
    1902              :                 tl::optional<Lifetime> label,
    1903              :                 AST::AttrVec outer_attribs = AST::AttrVec ());
    1904              : 
    1905           33 :   location_t get_locus () const override final { return locus; }
    1906              : 
    1907              :   void accept_vis (HIRFullVisitor &vis) override;
    1908              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1909              : 
    1910            7 :   Lifetime &get_label () { return label.value (); }
    1911            0 :   const Lifetime &get_label () const { return label.value (); }
    1912              : 
    1913            0 :   ExprType get_expression_type () const final override
    1914              :   {
    1915            0 :     return ExprType::Continue;
    1916              :   }
    1917              : 
    1918              : protected:
    1919              :   /* Use covariance to implement clone function as returning this object rather
    1920              :    * than base */
    1921            0 :   ContinueExpr *clone_expr_impl () const override
    1922              :   {
    1923            0 :     return new ContinueExpr (*this);
    1924              :   }
    1925              : 
    1926              :   /* Use covariance to implement clone function as returning this object rather
    1927              :    * than base */
    1928            0 :   ContinueExpr *clone_expr_without_block_impl () const override
    1929              :   {
    1930            0 :     return new ContinueExpr (*this);
    1931              :   }
    1932              : };
    1933              : 
    1934              : // HIR node representing break expression within loops
    1935              : class BreakExpr : public ExprWithoutBlock
    1936              : {
    1937              :   // bool has_label;
    1938              :   tl::optional<Lifetime> label;
    1939              : 
    1940              :   // bool has_break_expr;
    1941              :   std::unique_ptr<Expr> break_expr;
    1942              : 
    1943              :   location_t locus;
    1944              : 
    1945              : public:
    1946              :   std::string to_string () const override;
    1947              : 
    1948              :   // Returns whether the break expression has a label or not.
    1949          135 :   bool has_label () const { return label.has_value (); }
    1950              : 
    1951              :   /* Returns whether the break expression has an expression used in the break or
    1952              :    * not. */
    1953          590 :   bool has_break_expr () const { return break_expr != nullptr; }
    1954              : 
    1955              :   // Constructor for a break expression
    1956              :   BreakExpr (Analysis::NodeMapping mappings, location_t locus,
    1957              :              tl::optional<Lifetime> break_label,
    1958              :              std::unique_ptr<Expr> expr_in_break = nullptr,
    1959              :              AST::AttrVec outer_attribs = AST::AttrVec ());
    1960              : 
    1961              :   // Copy constructor defined to use clone for unique pointer
    1962              :   BreakExpr (BreakExpr const &other);
    1963              : 
    1964              :   // Overload assignment operator to clone unique pointer
    1965              :   BreakExpr &operator= (BreakExpr const &other);
    1966              : 
    1967              :   // move constructors
    1968              :   BreakExpr (BreakExpr &&other) = default;
    1969              :   BreakExpr &operator= (BreakExpr &&other) = default;
    1970              : 
    1971          205 :   location_t get_locus () const override final { return locus; }
    1972              : 
    1973              :   void accept_vis (HIRFullVisitor &vis) override;
    1974              :   void accept_vis (HIRExpressionVisitor &vis) override;
    1975              : 
    1976           38 :   Lifetime &get_label () { return label.value (); }
    1977            0 :   const Lifetime &get_label () const { return label.value (); }
    1978              : 
    1979          140 :   Expr &get_expr () { return *break_expr; }
    1980              : 
    1981            0 :   ExprType get_expression_type () const override final
    1982              :   {
    1983            0 :     return ExprType::Break;
    1984              :   }
    1985              : 
    1986              : protected:
    1987              :   /* Use covariance to implement clone function as returning this object rather
    1988              :    * than base */
    1989            0 :   BreakExpr *clone_expr_impl () const override { return new BreakExpr (*this); }
    1990              : 
    1991              :   /* Use covariance to implement clone function as returning this object rather
    1992              :    * than base */
    1993            0 :   BreakExpr *clone_expr_without_block_impl () const override
    1994              :   {
    1995            0 :     return new BreakExpr (*this);
    1996              :   }
    1997              : };
    1998              : 
    1999              : // Base range expression HIR node object - abstract
    2000            0 : class RangeExpr : public ExprWithoutBlock
    2001              : {
    2002              :   location_t locus;
    2003              : 
    2004              : protected:
    2005              :   // outer attributes not allowed before range expressions
    2006              :   RangeExpr (Analysis::NodeMapping mappings, location_t locus);
    2007              : 
    2008              : public:
    2009          366 :   location_t get_locus () const override final { return locus; }
    2010              : 
    2011            0 :   ExprType get_expression_type () const override final
    2012              :   {
    2013            0 :     return ExprType::Range;
    2014              :   }
    2015              : };
    2016              : 
    2017              : // Range from (inclusive) and to (exclusive) expression HIR node object
    2018              : // aka RangeExpr; constructs a std::ops::Range object
    2019              : class RangeFromToExpr : public RangeExpr
    2020              : {
    2021              :   std::unique_ptr<Expr> from;
    2022              :   std::unique_ptr<Expr> to;
    2023              : 
    2024              : public:
    2025              :   std::string to_string () const override;
    2026              : 
    2027              :   RangeFromToExpr (Analysis::NodeMapping mappings,
    2028              :                    std::unique_ptr<Expr> range_from,
    2029              :                    std::unique_ptr<Expr> range_to, location_t locus);
    2030              : 
    2031              :   // Copy constructor with cloning
    2032              :   RangeFromToExpr (RangeFromToExpr const &other);
    2033              : 
    2034              :   // Overload assignment operator to clone unique pointers
    2035              :   RangeFromToExpr &operator= (RangeFromToExpr const &other);
    2036              : 
    2037              :   // move constructors
    2038              :   RangeFromToExpr (RangeFromToExpr &&other) = default;
    2039              :   RangeFromToExpr &operator= (RangeFromToExpr &&other) = default;
    2040              : 
    2041              :   void accept_vis (HIRFullVisitor &vis) override;
    2042              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2043              : 
    2044          462 :   Expr &get_from_expr () { return *from; }
    2045          396 :   Expr &get_to_expr () { return *to; }
    2046              : 
    2047              : protected:
    2048              :   /* Use covariance to implement clone function as returning this object rather
    2049              :    * than base */
    2050            0 :   RangeFromToExpr *clone_expr_impl () const override
    2051              :   {
    2052            0 :     return new RangeFromToExpr (*this);
    2053              :   }
    2054              : 
    2055              :   /* Use covariance to implement clone function as returning this object rather
    2056              :    * than base */
    2057            0 :   RangeFromToExpr *clone_expr_without_block_impl () const override
    2058              :   {
    2059            0 :     return new RangeFromToExpr (*this);
    2060              :   }
    2061              : };
    2062              : 
    2063              : // Range from (inclusive) expression HIR node object
    2064              : // constructs a std::ops::RangeFrom object
    2065              : class RangeFromExpr : public RangeExpr
    2066              : {
    2067              :   std::unique_ptr<Expr> from;
    2068              : 
    2069              : public:
    2070              :   std::string to_string () const override;
    2071              : 
    2072              :   RangeFromExpr (Analysis::NodeMapping mappings,
    2073              :                  std::unique_ptr<Expr> range_from, location_t locus);
    2074              : 
    2075              :   // Copy constructor with clone
    2076              :   RangeFromExpr (RangeFromExpr const &other);
    2077              : 
    2078              :   // Overload assignment operator to clone unique_ptr
    2079              :   RangeFromExpr &operator= (RangeFromExpr const &other);
    2080              : 
    2081              :   // move constructors
    2082              :   RangeFromExpr (RangeFromExpr &&other) = default;
    2083              :   RangeFromExpr &operator= (RangeFromExpr &&other) = default;
    2084              : 
    2085              :   void accept_vis (HIRFullVisitor &vis) override;
    2086              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2087              : 
    2088           42 :   Expr &get_from_expr () { return *from; }
    2089              : 
    2090              : protected:
    2091              :   /* Use covariance to implement clone function as returning this object rather
    2092              :    * than base */
    2093            0 :   RangeFromExpr *clone_expr_impl () const override
    2094              :   {
    2095            0 :     return new RangeFromExpr (*this);
    2096              :   }
    2097              : 
    2098              :   /* Use covariance to implement clone function as returning this object rather
    2099              :    * than base */
    2100            0 :   RangeFromExpr *clone_expr_without_block_impl () const override
    2101              :   {
    2102            0 :     return new RangeFromExpr (*this);
    2103              :   }
    2104              : };
    2105              : 
    2106              : // Range to (exclusive) expression HIR node object
    2107              : // constructs a std::ops::RangeTo object
    2108              : class RangeToExpr : public RangeExpr
    2109              : {
    2110              :   std::unique_ptr<Expr> to;
    2111              : 
    2112              : public:
    2113              :   std::string to_string () const override;
    2114              : 
    2115              :   // outer attributes not allowed
    2116              :   RangeToExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> range_to,
    2117              :                location_t locus);
    2118              : 
    2119              :   // Copy constructor with clone
    2120              :   RangeToExpr (RangeToExpr const &other);
    2121              : 
    2122              :   // Overload assignment operator to clone unique_ptr
    2123              :   RangeToExpr &operator= (RangeToExpr const &other);
    2124              : 
    2125              :   // move constructors
    2126              :   RangeToExpr (RangeToExpr &&other) = default;
    2127              :   RangeToExpr &operator= (RangeToExpr &&other) = default;
    2128              : 
    2129              :   void accept_vis (HIRFullVisitor &vis) override;
    2130              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2131              : 
    2132           42 :   Expr &get_to_expr () { return *to; }
    2133              : 
    2134              : protected:
    2135              :   /* Use covariance to implement clone function as returning this object rather
    2136              :    * than base */
    2137            0 :   RangeToExpr *clone_expr_impl () const override
    2138              :   {
    2139            0 :     return new RangeToExpr (*this);
    2140              :   }
    2141              : 
    2142              :   /* Use covariance to implement clone function as returning this object rather
    2143              :    * than base */
    2144            0 :   RangeToExpr *clone_expr_without_block_impl () const override
    2145              :   {
    2146            0 :     return new RangeToExpr (*this);
    2147              :   }
    2148              : };
    2149              : 
    2150              : // Full range expression HIR node object
    2151              : // constructs a std::ops::RangeFull object
    2152            0 : class RangeFullExpr : public RangeExpr
    2153              : {
    2154              : public:
    2155              :   std::string to_string () const override;
    2156              : 
    2157              :   RangeFullExpr (Analysis::NodeMapping mappings, location_t locus);
    2158              :   // outer attributes not allowed
    2159              : 
    2160              :   void accept_vis (HIRFullVisitor &vis) override;
    2161              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2162              : 
    2163              : protected:
    2164              :   /* Use covariance to implement clone function as returning this object rather
    2165              :    * than base */
    2166            0 :   RangeFullExpr *clone_expr_impl () const override
    2167              :   {
    2168            0 :     return new RangeFullExpr (*this);
    2169              :   }
    2170              : 
    2171              :   /* Use covariance to implement clone function as returning this object rather
    2172              :    * than base */
    2173            0 :   RangeFullExpr *clone_expr_without_block_impl () const override
    2174              :   {
    2175            0 :     return new RangeFullExpr (*this);
    2176              :   }
    2177              : };
    2178              : 
    2179              : // Range from (inclusive) and to (inclusive) expression HIR node object
    2180              : // aka RangeInclusiveExpr; constructs a std::ops::RangeInclusive object
    2181              : class RangeFromToInclExpr : public RangeExpr
    2182              : {
    2183              :   std::unique_ptr<Expr> from;
    2184              :   std::unique_ptr<Expr> to;
    2185              : 
    2186              : public:
    2187              :   std::string to_string () const override;
    2188              : 
    2189              :   RangeFromToInclExpr (Analysis::NodeMapping mappings,
    2190              :                        std::unique_ptr<Expr> range_from,
    2191              :                        std::unique_ptr<Expr> range_to, location_t locus);
    2192              :   // outer attributes not allowed
    2193              : 
    2194              :   // Copy constructor with clone
    2195              :   RangeFromToInclExpr (RangeFromToInclExpr const &other);
    2196              : 
    2197              :   // Overload assignment operator to use clone
    2198              :   RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other);
    2199              : 
    2200              :   // move constructors
    2201              :   RangeFromToInclExpr (RangeFromToInclExpr &&other) = default;
    2202              :   RangeFromToInclExpr &operator= (RangeFromToInclExpr &&other) = default;
    2203              : 
    2204              :   void accept_vis (HIRFullVisitor &vis) override;
    2205              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2206              : 
    2207           49 :   Expr &get_from_expr () { return *from; }
    2208           42 :   Expr &get_to_expr () { return *to; }
    2209              : 
    2210              : protected:
    2211              :   /* Use covariance to implement clone function as returning this object rather
    2212              :    * than base */
    2213            0 :   RangeFromToInclExpr *clone_expr_impl () const override
    2214              :   {
    2215            0 :     return new RangeFromToInclExpr (*this);
    2216              :   }
    2217              : 
    2218              :   /* Use covariance to implement clone function as returning this object rather
    2219              :    * than base */
    2220            0 :   RangeFromToInclExpr *clone_expr_without_block_impl () const override
    2221              :   {
    2222            0 :     return new RangeFromToInclExpr (*this);
    2223              :   }
    2224              : };
    2225              : 
    2226              : // Range to (inclusive) expression HIR node object
    2227              : // aka RangeToInclusiveExpr; constructs a std::ops::RangeToInclusive object
    2228              : class RangeToInclExpr : public RangeExpr
    2229              : {
    2230              :   std::unique_ptr<Expr> to;
    2231              : 
    2232              : public:
    2233              :   std::string to_string () const override;
    2234              : 
    2235              :   RangeToInclExpr (Analysis::NodeMapping mappings,
    2236              :                    std::unique_ptr<Expr> range_to, location_t locus);
    2237              :   // outer attributes not allowed
    2238              : 
    2239              :   // Copy constructor with clone
    2240              :   RangeToInclExpr (RangeToInclExpr const &other);
    2241              : 
    2242              :   // Overload assignment operator to clone pointer
    2243              :   RangeToInclExpr &operator= (RangeToInclExpr const &other);
    2244              : 
    2245              :   // move constructors
    2246              :   RangeToInclExpr (RangeToInclExpr &&other) = default;
    2247              :   RangeToInclExpr &operator= (RangeToInclExpr &&other) = default;
    2248              : 
    2249              :   void accept_vis (HIRFullVisitor &vis) override;
    2250              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2251              : 
    2252            0 :   Expr &get_to_expr () { return *to; };
    2253              : 
    2254              : protected:
    2255              :   /* Use covariance to implement clone function as returning this object rather
    2256              :    * than base */
    2257            0 :   RangeToInclExpr *clone_expr_impl () const override
    2258              :   {
    2259            0 :     return new RangeToInclExpr (*this);
    2260              :   }
    2261              : 
    2262              :   /* Use covariance to implement clone function as returning this object rather
    2263              :    * than base */
    2264            0 :   RangeToInclExpr *clone_expr_without_block_impl () const override
    2265              :   {
    2266            0 :     return new RangeToInclExpr (*this);
    2267              :   }
    2268              : };
    2269              : 
    2270              : // Return expression HIR node representation
    2271              : class ReturnExpr : public ExprWithoutBlock
    2272              : {
    2273              : public:
    2274              :   std::unique_ptr<Expr> return_expr;
    2275              : 
    2276              :   location_t locus;
    2277              : 
    2278              :   std::string to_string () const override;
    2279              : 
    2280              :   /* Returns whether the object has an expression returned (i.e. not void return
    2281              :    * type). */
    2282         5172 :   bool has_return_expr () const { return return_expr != nullptr; }
    2283              : 
    2284              :   // Constructor for ReturnExpr.
    2285              :   ReturnExpr (Analysis::NodeMapping mappings, location_t locus,
    2286              :               std::unique_ptr<Expr> returned_expr = nullptr,
    2287              :               AST::AttrVec outer_attribs = AST::AttrVec ());
    2288              : 
    2289              :   // Copy constructor with clone
    2290              :   ReturnExpr (ReturnExpr const &other);
    2291              : 
    2292              :   // Overloaded assignment operator to clone return_expr pointer
    2293              :   ReturnExpr &operator= (ReturnExpr const &other);
    2294              : 
    2295              :   // move constructors
    2296              :   ReturnExpr (ReturnExpr &&other) = default;
    2297              :   ReturnExpr &operator= (ReturnExpr &&other) = default;
    2298              : 
    2299         1666 :   location_t get_locus () const override final { return locus; }
    2300              : 
    2301              :   void accept_vis (HIRFullVisitor &vis) override;
    2302              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2303              : 
    2304          371 :   bool has_expr () { return return_expr != nullptr; }
    2305         4749 :   Expr &get_expr () { return *return_expr; }
    2306              : 
    2307            0 :   ExprType get_expression_type () const override final
    2308              :   {
    2309            0 :     return ExprType::Return;
    2310              :   }
    2311              : 
    2312              : protected:
    2313              :   /* Use covariance to implement clone function as returning this object rather
    2314              :    * than base */
    2315            0 :   ReturnExpr *clone_expr_impl () const override
    2316              :   {
    2317            0 :     return new ReturnExpr (*this);
    2318              :   }
    2319              : 
    2320              :   /* Use covariance to implement clone function as returning this object rather
    2321              :    * than base */
    2322            0 :   ReturnExpr *clone_expr_without_block_impl () const override
    2323              :   {
    2324            0 :     return new ReturnExpr (*this);
    2325              :   }
    2326              : };
    2327              : 
    2328              : // An unsafe block HIR node
    2329              : class UnsafeBlockExpr : public ExprWithBlock
    2330              : {
    2331              :   // Or just have it extend BlockExpr
    2332              :   std::unique_ptr<BlockExpr> expr;
    2333              :   location_t locus;
    2334              : 
    2335              : public:
    2336              :   std::string to_string () const override;
    2337              : 
    2338              :   UnsafeBlockExpr (Analysis::NodeMapping mappings,
    2339              :                    std::unique_ptr<BlockExpr> block_expr,
    2340              :                    AST::AttrVec outer_attribs, location_t locus);
    2341              : 
    2342              :   // Copy constructor with clone
    2343              :   UnsafeBlockExpr (UnsafeBlockExpr const &other);
    2344              : 
    2345              :   // Overloaded assignment operator to clone
    2346              :   UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other);
    2347              : 
    2348              :   // move constructors
    2349              :   UnsafeBlockExpr (UnsafeBlockExpr &&other) = default;
    2350              :   UnsafeBlockExpr &operator= (UnsafeBlockExpr &&other) = default;
    2351              : 
    2352         9819 :   location_t get_locus () const override final { return locus; }
    2353              : 
    2354              :   void accept_vis (HIRFullVisitor &vis) override;
    2355              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2356              : 
    2357        28455 :   BlockExpr &get_block_expr () { return *expr; }
    2358              : 
    2359            0 :   ExprType get_expression_type () const override final
    2360              :   {
    2361            0 :     return ExprType::UnsafeBlock;
    2362              :   }
    2363              : 
    2364              : protected:
    2365              :   /* Use covariance to implement clone function as returning this object rather
    2366              :    * than base */
    2367            0 :   UnsafeBlockExpr *clone_expr_impl () const override
    2368              :   {
    2369            0 :     return new UnsafeBlockExpr (*this);
    2370              :   }
    2371              : 
    2372              :   /* Use covariance to implement clone function as returning this object rather
    2373              :    * than base */
    2374            0 :   UnsafeBlockExpr *clone_expr_with_block_impl () const override
    2375              :   {
    2376            0 :     return new UnsafeBlockExpr (*this);
    2377              :   }
    2378              : };
    2379              : 
    2380              : // Base loop expression HIR node - aka LoopExpr
    2381              : class BaseLoopExpr : public ExprWithBlock
    2382              : {
    2383              : protected:
    2384              :   tl::optional<LoopLabel> loop_label;
    2385              :   std::unique_ptr<BlockExpr> loop_block;
    2386              : 
    2387              : private:
    2388              :   location_t locus;
    2389              : 
    2390              : protected:
    2391              :   // Constructor for BaseLoopExpr
    2392              :   BaseLoopExpr (Analysis::NodeMapping mappings,
    2393              :                 std::unique_ptr<BlockExpr> loop_block, location_t locus,
    2394              :                 tl::optional<LoopLabel> loop_label,
    2395              :                 AST::AttrVec outer_attribs = AST::AttrVec ());
    2396              : 
    2397              :   // Copy constructor for BaseLoopExpr with clone
    2398              :   BaseLoopExpr (BaseLoopExpr const &other);
    2399              : 
    2400              :   // Overloaded assignment operator to clone
    2401              :   BaseLoopExpr &operator= (BaseLoopExpr const &other);
    2402              : 
    2403              :   // move constructors
    2404              :   BaseLoopExpr (BaseLoopExpr &&other) = default;
    2405              :   BaseLoopExpr &operator= (BaseLoopExpr &&other) = default;
    2406              : 
    2407            3 :   ExprType get_expression_type () const final override
    2408              :   {
    2409            3 :     return ExprType::BaseLoop;
    2410              :   }
    2411              : 
    2412              : public:
    2413          365 :   bool has_loop_label () const { return loop_label.has_value (); }
    2414              : 
    2415         1384 :   location_t get_locus () const override final { return locus; }
    2416              : 
    2417         1674 :   HIR::BlockExpr &get_loop_block () { return *loop_block; };
    2418              : 
    2419           79 :   LoopLabel &get_loop_label () { return loop_label.value (); }
    2420            0 :   const LoopLabel &get_loop_label () const { return loop_label.value (); }
    2421              : };
    2422              : 
    2423              : // 'Loop' expression (i.e. the infinite loop) HIR node
    2424            0 : class LoopExpr : public BaseLoopExpr
    2425              : {
    2426              : public:
    2427              :   std::string to_string () const override;
    2428              : 
    2429              :   // Constructor for LoopExpr
    2430              :   LoopExpr (Analysis::NodeMapping mappings,
    2431              :             std::unique_ptr<BlockExpr> loop_block, location_t locus,
    2432              :             tl::optional<LoopLabel> loop_label,
    2433              :             AST::AttrVec outer_attribs = AST::AttrVec ());
    2434              : 
    2435              :   void accept_vis (HIRFullVisitor &vis) override;
    2436              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2437              : 
    2438              : protected:
    2439              :   /* Use covariance to implement clone function as returning this object rather
    2440              :    * than base */
    2441            0 :   LoopExpr *clone_expr_impl () const override { return new LoopExpr (*this); }
    2442              : 
    2443              :   /* Use covariance to implement clone function as returning this object rather
    2444              :    * than base */
    2445            0 :   LoopExpr *clone_expr_with_block_impl () const override
    2446              :   {
    2447            0 :     return new LoopExpr (*this);
    2448              :   }
    2449              : };
    2450              : 
    2451              : // While loop expression HIR node (predicate loop)
    2452              : class WhileLoopExpr : public BaseLoopExpr
    2453              : {
    2454              :   std::unique_ptr<Expr> condition;
    2455              : 
    2456              : public:
    2457              :   std::string to_string () const override;
    2458              : 
    2459              :   // Constructor for while loop with loop label
    2460              :   WhileLoopExpr (Analysis::NodeMapping mappings,
    2461              :                  std::unique_ptr<Expr> loop_condition,
    2462              :                  std::unique_ptr<BlockExpr> loop_block, location_t locus,
    2463              :                  tl::optional<LoopLabel> loop_label,
    2464              :                  AST::AttrVec outer_attribs = AST::AttrVec ());
    2465              : 
    2466              :   // Copy constructor with clone
    2467              :   WhileLoopExpr (WhileLoopExpr const &other);
    2468              : 
    2469              :   // Overloaded assignment operator to clone
    2470              :   WhileLoopExpr &operator= (WhileLoopExpr const &other);
    2471              : 
    2472              :   // move constructors
    2473              :   WhileLoopExpr (WhileLoopExpr &&other) = default;
    2474              :   WhileLoopExpr &operator= (WhileLoopExpr &&other) = default;
    2475              : 
    2476              :   void accept_vis (HIRFullVisitor &vis) override;
    2477              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2478              : 
    2479          646 :   Expr &get_predicate_expr () { return *condition; }
    2480              : 
    2481              : protected:
    2482              :   /* Use covariance to implement clone function as returning this object rather
    2483              :    * than base */
    2484            0 :   WhileLoopExpr *clone_expr_impl () const override
    2485              :   {
    2486            0 :     return new WhileLoopExpr (*this);
    2487              :   }
    2488              : 
    2489              :   /* Use covariance to implement clone function as returning this object rather
    2490              :    * than base */
    2491            0 :   WhileLoopExpr *clone_expr_with_block_impl () const override
    2492              :   {
    2493            0 :     return new WhileLoopExpr (*this);
    2494              :   }
    2495              : };
    2496              : 
    2497              : // While let loop expression HIR node (predicate pattern loop)
    2498              : class WhileLetLoopExpr : public BaseLoopExpr
    2499              : {
    2500              :   // MatchArmPatterns patterns;
    2501              :   std::unique_ptr<Pattern> match_arm_pattern; // inlined
    2502              :   std::unique_ptr<Expr> condition;
    2503              : 
    2504              : public:
    2505              :   std::string to_string () const override;
    2506              : 
    2507              :   // Constructor with a loop label
    2508              :   WhileLetLoopExpr (Analysis::NodeMapping mappings,
    2509              :                     std::unique_ptr<Pattern> match_arm_pattern,
    2510              :                     std::unique_ptr<Expr> condition,
    2511              :                     std::unique_ptr<BlockExpr> loop_block, location_t locus,
    2512              :                     tl::optional<LoopLabel> loop_label,
    2513              :                     AST::AttrVec outer_attribs = AST::AttrVec ());
    2514              : 
    2515              :   // Copy constructor with clone
    2516              :   WhileLetLoopExpr (WhileLetLoopExpr const &other);
    2517              : 
    2518              :   // Overloaded assignment operator to clone pointers
    2519              :   WhileLetLoopExpr &operator= (WhileLetLoopExpr const &other);
    2520              : 
    2521              :   // move constructors
    2522              :   WhileLetLoopExpr (WhileLetLoopExpr &&other) = default;
    2523              :   WhileLetLoopExpr &operator= (WhileLetLoopExpr &&other) = default;
    2524              : 
    2525              :   void accept_vis (HIRFullVisitor &vis) override;
    2526              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2527              : 
    2528            0 :   Expr &get_cond () { return *condition; }
    2529            0 :   std::unique_ptr<Pattern> &get_pattern () { return match_arm_pattern; }
    2530              : 
    2531              : protected:
    2532              :   /* Use covariance to implement clone function as returning this object rather
    2533              :    * than base */
    2534            0 :   WhileLetLoopExpr *clone_expr_impl () const override
    2535              :   {
    2536            0 :     return new WhileLetLoopExpr (*this);
    2537              :   }
    2538              : 
    2539              :   /* Use covariance to implement clone function as returning this object rather
    2540              :    * than base */
    2541            0 :   WhileLetLoopExpr *clone_expr_with_block_impl () const override
    2542              :   {
    2543            0 :     return new WhileLetLoopExpr (*this);
    2544              :   }
    2545              : };
    2546              : 
    2547              : // Base if expression with no "else" or "if let" HIR node
    2548              : class IfExpr : public ExprWithBlock
    2549              : {
    2550              :   std::unique_ptr<Expr> condition;
    2551              :   std::unique_ptr<BlockExpr> if_block;
    2552              : 
    2553              :   location_t locus;
    2554              : 
    2555              : public:
    2556              :   std::string to_string () const override;
    2557              : 
    2558              :   IfExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> condition,
    2559              :           std::unique_ptr<BlockExpr> if_block, location_t locus);
    2560              :   // outer attributes are never allowed on IfExprs
    2561              : 
    2562              :   // Copy constructor with clone
    2563              :   IfExpr (IfExpr const &other);
    2564              : 
    2565              :   // Overloaded assignment operator to clone expressions
    2566              :   IfExpr &operator= (IfExpr const &other);
    2567              : 
    2568              :   // move constructors
    2569              :   IfExpr (IfExpr &&other) = default;
    2570              :   IfExpr &operator= (IfExpr &&other) = default;
    2571              : 
    2572              :   // Unique pointer custom clone function
    2573              :   std::unique_ptr<IfExpr> clone_if_expr () const
    2574              :   {
    2575              :     return std::unique_ptr<IfExpr> (clone_if_expr_impl ());
    2576              :   }
    2577              : 
    2578              :   /* Note that multiple "else if"s are handled via nested HIRs rather than a
    2579              :    * vector of else ifs - i.e. not like a switch statement. TODO - is this a
    2580              :    * better approach? or does it not parse correctly and have downsides? */
    2581              : 
    2582         9764 :   location_t get_locus () const override final { return locus; }
    2583              : 
    2584              :   void accept_vis (HIRFullVisitor &vis) override;
    2585              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2586              : 
    2587              :   void vis_if_condition (HIRFullVisitor &vis) { condition->accept_vis (vis); }
    2588              :   void vis_if_block (HIRFullVisitor &vis) { if_block->accept_vis (vis); }
    2589              : 
    2590        12661 :   Expr &get_if_condition () { return *condition; }
    2591        14293 :   BlockExpr &get_if_block () { return *if_block; }
    2592              : 
    2593            0 :   ExprType get_expression_type () const final override { return ExprType::If; }
    2594              : 
    2595              : protected:
    2596              :   /* Use covariance to implement clone function as returning this object rather
    2597              :    * than base */
    2598            0 :   IfExpr *clone_expr_impl () const override { return new IfExpr (*this); }
    2599              : 
    2600              :   // Base clone function but still concrete as concrete base class
    2601            0 :   virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); }
    2602              : 
    2603              :   /* Use covariance to implement clone function as returning this object rather
    2604              :    * than base */
    2605            0 :   IfExpr *clone_expr_with_block_impl () const override
    2606              :   {
    2607            0 :     return new IfExpr (*this);
    2608              :   }
    2609              : };
    2610              : 
    2611              : // If expression with an ending "else" expression HIR node (trailing)
    2612              : class IfExprConseqElse : public IfExpr
    2613              : {
    2614              :   std::unique_ptr<ExprWithBlock> else_block;
    2615              : 
    2616              : public:
    2617              :   std::string to_string () const override;
    2618              : 
    2619              :   IfExprConseqElse (Analysis::NodeMapping mappings,
    2620              :                     std::unique_ptr<Expr> condition,
    2621              :                     std::unique_ptr<BlockExpr> if_block,
    2622              :                     std::unique_ptr<ExprWithBlock> else_block,
    2623              :                     location_t locus);
    2624              :   // again, outer attributes not allowed
    2625              : 
    2626              :   // Copy constructor with clone
    2627              :   IfExprConseqElse (IfExprConseqElse const &other);
    2628              : 
    2629              :   // Overloaded assignment operator with cloning
    2630              :   IfExprConseqElse &operator= (IfExprConseqElse const &other);
    2631              : 
    2632              :   // move constructors
    2633              :   IfExprConseqElse (IfExprConseqElse &&other) = default;
    2634              :   IfExprConseqElse &operator= (IfExprConseqElse &&other) = default;
    2635              : 
    2636              :   void accept_vis (HIRFullVisitor &vis) override;
    2637              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2638              : 
    2639              :   void vis_else_block (HIRFullVisitor &vis) { else_block->accept_vis (vis); }
    2640              : 
    2641        11093 :   ExprWithBlock &get_else_block () { return *else_block; }
    2642              : 
    2643              : protected:
    2644              :   /* Use covariance to implement clone function as returning this object rather
    2645              :    * than base */
    2646            0 :   IfExprConseqElse *clone_expr_impl () const override
    2647              :   {
    2648            0 :     return new IfExprConseqElse (*this);
    2649              :   }
    2650              : 
    2651              :   /* Use covariance to implement clone function as returning this object rather
    2652              :    * than base */
    2653            0 :   IfExprConseqElse *clone_expr_with_block_impl () const override
    2654              :   {
    2655            0 :     return new IfExprConseqElse (*this);
    2656              :   }
    2657              : 
    2658              :   /* Use covariance to implement clone function as returning this object rather
    2659              :    * than base */
    2660            0 :   IfExprConseqElse *clone_if_expr_impl () const override
    2661              :   {
    2662            0 :     return new IfExprConseqElse (*this);
    2663              :   }
    2664              : };
    2665              : 
    2666              : // Match arm expression
    2667              : struct MatchArm
    2668              : {
    2669              : private:
    2670              :   AST::AttrVec outer_attrs;
    2671              :   std::unique_ptr<Pattern> match_arm_pattern;
    2672              :   std::unique_ptr<Expr> guard_expr;
    2673              :   location_t locus;
    2674              : 
    2675              : public:
    2676              :   // Returns whether the MatchArm has a match arm guard expression
    2677         8139 :   bool has_match_arm_guard () const { return guard_expr != nullptr; }
    2678              : 
    2679              :   // Constructor for match arm with a guard expression
    2680              :   MatchArm (std::unique_ptr<Pattern> match_arm_pattern, location_t locus,
    2681              :             std::unique_ptr<Expr> guard_expr = nullptr,
    2682              :             AST::AttrVec outer_attrs = AST::AttrVec ());
    2683              : 
    2684              :   // Copy constructor with clone
    2685              :   MatchArm (MatchArm const &other);
    2686              : 
    2687         9973 :   ~MatchArm () = default;
    2688              : 
    2689              :   // Overload assignment operator to clone
    2690              :   MatchArm &operator= (MatchArm const &other);
    2691              : 
    2692              :   // move constructors
    2693         5070 :   MatchArm (MatchArm &&other) = default;
    2694              :   MatchArm &operator= (MatchArm &&other) = default;
    2695              : 
    2696              :   // Returns whether match arm is in an error state.
    2697              :   bool is_error () const { return match_arm_pattern == nullptr; }
    2698              : 
    2699              :   // Creates a match arm in an error state.
    2700              :   static MatchArm create_error ()
    2701              :   {
    2702              :     location_t locus = UNDEF_LOCATION;
    2703              :     return MatchArm (nullptr, locus);
    2704              :   }
    2705              : 
    2706              :   std::string to_string () const;
    2707              : 
    2708         9380 :   std::unique_ptr<Pattern> &get_pattern () { return match_arm_pattern; }
    2709              : 
    2710            1 :   Expr &get_guard_expr () { return *guard_expr; }
    2711              : 
    2712         2048 :   location_t get_locus () const { return locus; }
    2713              : 
    2714              :   AST::AttrVec &get_outer_attrs () { return outer_attrs; }
    2715              : };
    2716              : 
    2717              : /* A "match case" - a correlated match arm and resulting expression. Not
    2718              :  * abstract. */
    2719              : struct MatchCase
    2720              : {
    2721              : private:
    2722              :   Analysis::NodeMapping mappings;
    2723              :   MatchArm arm;
    2724              :   std::unique_ptr<Expr> expr;
    2725              : 
    2726              : public:
    2727              :   MatchCase (Analysis::NodeMapping mappings, MatchArm arm,
    2728              :              std::unique_ptr<Expr> expr);
    2729              : 
    2730              :   MatchCase (const MatchCase &other);
    2731              : 
    2732              :   MatchCase &operator= (const MatchCase &other);
    2733              : 
    2734         1563 :   MatchCase (MatchCase &&other) = default;
    2735              :   MatchCase &operator= (MatchCase &&other) = default;
    2736              : 
    2737         1563 :   ~MatchCase () = default;
    2738              : 
    2739              :   std::string to_string () const;
    2740              :   std::string to_debug_string () const;
    2741              : 
    2742              :   Analysis::NodeMapping get_mappings () const { return mappings; }
    2743              : 
    2744        12720 :   MatchArm &get_arm () { return arm; }
    2745        19654 :   Expr &get_expr () { return *expr; }
    2746              : };
    2747              : 
    2748              : // Match expression HIR node
    2749              : class MatchExpr : public ExprWithBlock, public WithInnerAttrs
    2750              : {
    2751              :   std::unique_ptr<Expr> branch_value;
    2752              :   std::vector<MatchCase> match_arms;
    2753              :   location_t locus;
    2754              : 
    2755              : public:
    2756              :   std::string to_string () const override;
    2757              : 
    2758         3029 :   bool has_match_arms () const { return !match_arms.empty (); }
    2759              : 
    2760              :   MatchExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> branch_value,
    2761              :              std::vector<MatchCase> match_arms, AST::AttrVec inner_attrs,
    2762              :              AST::AttrVec outer_attrs, location_t locus);
    2763              : 
    2764              :   // Copy constructor requires clone due to unique_ptr
    2765              :   MatchExpr (MatchExpr const &other);
    2766              : 
    2767              :   // Overloaded assignment operator to clone due to unique_ptr
    2768              :   MatchExpr &operator= (MatchExpr const &other);
    2769              : 
    2770              :   // move constructors
    2771              :   MatchExpr (MatchExpr &&other) = default;
    2772              :   MatchExpr &operator= (MatchExpr &&other) = default;
    2773              : 
    2774        13055 :   location_t get_locus () const override final { return locus; }
    2775              : 
    2776              :   void accept_vis (HIRFullVisitor &vis) override;
    2777              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2778              : 
    2779        14516 :   Expr &get_scrutinee_expr () { return *branch_value; }
    2780          990 :   AST::AttrVec get_inner_attrs () const { return inner_attrs; }
    2781              :   const std::vector<MatchCase> &get_match_cases () const { return match_arms; }
    2782         8494 :   std::vector<MatchCase> &get_match_cases () { return match_arms; }
    2783              : 
    2784            0 :   ExprType get_expression_type () const final override
    2785              :   {
    2786            0 :     return ExprType::Match;
    2787              :   }
    2788              : 
    2789              : protected:
    2790              :   /* Use covariance to implement clone function as returning this object rather
    2791              :    * than base */
    2792            0 :   MatchExpr *clone_expr_impl () const override { return new MatchExpr (*this); }
    2793              : 
    2794              :   /* Use covariance to implement clone function as returning this object rather
    2795              :    * than base */
    2796            0 :   MatchExpr *clone_expr_with_block_impl () const override
    2797              :   {
    2798            0 :     return new MatchExpr (*this);
    2799              :   }
    2800              : };
    2801              : 
    2802              : // Await expression HIR node (pseudo-member variable access)
    2803              : class AwaitExpr : public ExprWithoutBlock
    2804              : {
    2805              :   std::unique_ptr<Expr> awaited_expr;
    2806              :   location_t locus;
    2807              : 
    2808              : public:
    2809              :   // TODO: ensure outer attributes are actually allowed
    2810              :   AwaitExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> awaited_expr,
    2811              :              AST::AttrVec outer_attrs, location_t locus);
    2812              : 
    2813              :   // copy constructor with clone
    2814              :   AwaitExpr (AwaitExpr const &other);
    2815              : 
    2816              :   // overloaded assignment operator with clone
    2817              :   AwaitExpr &operator= (AwaitExpr const &other);
    2818              : 
    2819              :   // move constructors
    2820              :   AwaitExpr (AwaitExpr &&other) = default;
    2821              :   AwaitExpr &operator= (AwaitExpr &&other) = default;
    2822              : 
    2823              :   std::string to_string () const override;
    2824              : 
    2825            0 :   location_t get_locus () const override final { return locus; }
    2826              : 
    2827              :   void accept_vis (HIRFullVisitor &vis) override;
    2828              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2829              : 
    2830            0 :   Expr &get_awaited_expr () { return *awaited_expr; }
    2831              : 
    2832            0 :   ExprType get_expression_type () const final override
    2833              :   {
    2834            0 :     return ExprType::Await;
    2835              :   }
    2836              : 
    2837              : protected:
    2838              :   /* Use covariance to implement clone function as returning this object rather
    2839              :    * than base */
    2840            0 :   AwaitExpr *clone_expr_without_block_impl () const override
    2841              :   {
    2842            0 :     return new AwaitExpr (*this);
    2843              :   }
    2844              : };
    2845              : 
    2846              : // Async block expression HIR node (block expr that evaluates to a future)
    2847              : class AsyncBlockExpr : public ExprWithBlock
    2848              : {
    2849              :   bool has_move;
    2850              :   std::unique_ptr<BlockExpr> block_expr;
    2851              :   location_t locus;
    2852              : 
    2853              : public:
    2854              :   AsyncBlockExpr (Analysis::NodeMapping mappings,
    2855              :                   std::unique_ptr<BlockExpr> block_expr, bool has_move,
    2856              :                   AST::AttrVec outer_attrs, location_t locus);
    2857              : 
    2858              :   // copy constructor with clone
    2859              :   AsyncBlockExpr (AsyncBlockExpr const &other);
    2860              : 
    2861              :   // overloaded assignment operator to clone
    2862              :   AsyncBlockExpr &operator= (AsyncBlockExpr const &other);
    2863              : 
    2864              :   // move constructors
    2865              :   AsyncBlockExpr (AsyncBlockExpr &&other) = default;
    2866              :   AsyncBlockExpr &operator= (AsyncBlockExpr &&other) = default;
    2867              : 
    2868              :   std::string to_string () const override;
    2869              : 
    2870            0 :   location_t get_locus () const override final { return locus; }
    2871              : 
    2872            0 :   bool get_has_move () const { return has_move; }
    2873            0 :   BlockExpr &get_block_expr () { return *block_expr; }
    2874              : 
    2875              :   void accept_vis (HIRFullVisitor &vis) override;
    2876              :   void accept_vis (HIRExpressionVisitor &vis) override;
    2877              : 
    2878            0 :   ExprType get_expression_type () const final override
    2879              :   {
    2880            0 :     return ExprType::AsyncBlock;
    2881              :   }
    2882              : 
    2883              : protected:
    2884              :   /* Use covariance to implement clone function as returning this object rather
    2885              :    * than base */
    2886            0 :   AsyncBlockExpr *clone_expr_with_block_impl () const override
    2887              :   {
    2888            0 :     return new AsyncBlockExpr (*this);
    2889              :   }
    2890              : };
    2891              : 
    2892              : // this is a utility helper class for type-checking and code-generation
    2893              : class OperatorExprMeta
    2894              : {
    2895              : public:
    2896              :   OperatorExprMeta (HIR::CompoundAssignmentExpr &expr);
    2897              : 
    2898              :   OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr);
    2899              : 
    2900              :   OperatorExprMeta (HIR::NegationExpr &expr);
    2901              : 
    2902              :   OperatorExprMeta (HIR::DereferenceExpr &expr);
    2903              : 
    2904              :   OperatorExprMeta (HIR::ArrayIndexExpr &expr);
    2905              : 
    2906              :   OperatorExprMeta (HIR::ComparisonExpr &expr);
    2907              : 
    2908           56 :   OperatorExprMeta (const OperatorExprMeta &other)
    2909           56 :     : node_mappings (other.node_mappings),
    2910           56 :       lvalue_mappings (other.lvalue_mappings),
    2911           24 :       rvalue_mappings (other.rvalue_mappings), locus (other.locus)
    2912              :   {}
    2913              : 
    2914            0 :   OperatorExprMeta &operator= (const OperatorExprMeta &other)
    2915              :   {
    2916            0 :     node_mappings = other.node_mappings;
    2917            0 :     lvalue_mappings = other.lvalue_mappings;
    2918            0 :     rvalue_mappings = other.rvalue_mappings;
    2919            0 :     locus = other.locus;
    2920              : 
    2921            0 :     return *this;
    2922              :   }
    2923              : 
    2924         2418 :   const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
    2925              : 
    2926         2568 :   const Analysis::NodeMapping &get_lvalue_mappings () const
    2927              :   {
    2928         2568 :     return lvalue_mappings;
    2929              :   }
    2930              : 
    2931              :   const Analysis::NodeMapping &get_rvalue_mappings () const
    2932              :   {
    2933              :     return rvalue_mappings;
    2934              :   }
    2935              : 
    2936            8 :   bool has_rvalue_mappings () const
    2937              :   {
    2938            8 :     return rvalue_mappings.get_hirid () != UNKNOWN_HIRID;
    2939              :   }
    2940              : 
    2941         6442 :   location_t get_locus () const { return locus; }
    2942              : 
    2943              : private:
    2944              :   Analysis::NodeMapping node_mappings;
    2945              :   Analysis::NodeMapping lvalue_mappings;
    2946              :   Analysis::NodeMapping rvalue_mappings;
    2947              :   location_t locus;
    2948              : };
    2949              : 
    2950              : class InlineAsmReg
    2951              : {
    2952              :   enum Kind
    2953              :   {
    2954              :     X86,
    2955              :     Arm,
    2956              :     AArch64,
    2957              :     RiscV,
    2958              :     Nvptx,
    2959              :     PowerPC,
    2960              :     Hexagon,
    2961              :     Mips,
    2962              :     S390x,
    2963              :     SpirV,
    2964              :     Wasm,
    2965              :     Bpf,
    2966              :     Avr,
    2967              :     Msp430,
    2968              :     // Placeholder for invalid register constraints for the current target
    2969              :     Err,
    2970              :   };
    2971              : 
    2972              :   // this placeholder is to be removed when the definations
    2973              :   // of the above enums are made in a later PR/patch.
    2974              :   std::string placeholder;
    2975              : };
    2976              : 
    2977              : class InlineAsmRegClass
    2978              : {
    2979              :   enum Type
    2980              :   {
    2981              :     X86,
    2982              :     Arm,
    2983              :     AArch64,
    2984              :     RiscV,
    2985              :     Nvptx,
    2986              :     PowerPC,
    2987              :     Hexagon,
    2988              :     Mips,
    2989              :     S390x,
    2990              :     SpirV,
    2991              :     Wasm,
    2992              :     Bpf,
    2993              :     Avr,
    2994              :     Msp430,
    2995              :     // Placeholder for invalid register constraints for the current target
    2996              :     Err,
    2997              :   };
    2998              : 
    2999              :   // this placeholder is to be removed when the definations
    3000              :   // of the above enums are made in a later PR/patch.
    3001              :   std::string placeholder;
    3002              : };
    3003              : 
    3004              : class InlineAsmOperand
    3005              : {
    3006              : public:
    3007              :   struct In
    3008              :   {
    3009              :     tl::optional<struct AST::InlineAsmRegOrRegClass> reg;
    3010              :     std::unique_ptr<Expr> expr;
    3011              : 
    3012              :     In (const tl::optional<struct AST::InlineAsmRegOrRegClass> &reg,
    3013              :         std::unique_ptr<Expr> expr);
    3014              : 
    3015              :     In (const struct In &other);
    3016              : 
    3017              :     In operator= (const struct In &other);
    3018              :   };
    3019              : 
    3020              :   struct Out
    3021              :   {
    3022              :     tl::optional<struct AST::InlineAsmRegOrRegClass> reg;
    3023              :     bool late;
    3024              :     std::unique_ptr<Expr> expr; // can be null
    3025              : 
    3026              :     Out (tl::optional<struct AST::InlineAsmRegOrRegClass> &reg, bool late,
    3027              :          std::unique_ptr<Expr> expr);
    3028              : 
    3029              :     Out (const struct Out &other);
    3030              : 
    3031              :     Out operator= (const struct Out &other);
    3032              :   };
    3033              : 
    3034              :   struct InOut
    3035              :   {
    3036              :     tl::optional<struct AST::InlineAsmRegOrRegClass> reg;
    3037              :     bool late;
    3038              :     std::unique_ptr<Expr> expr; // this can't be null
    3039              : 
    3040              :     InOut (tl::optional<struct AST::InlineAsmRegOrRegClass> &reg, bool late,
    3041              :            std::unique_ptr<Expr> expr);
    3042              : 
    3043              :     InOut (const struct InOut &other);
    3044              : 
    3045              :     InOut operator= (const struct InOut &other);
    3046              :   };
    3047              : 
    3048              :   struct SplitInOut
    3049              :   {
    3050              :     tl::optional<struct AST::InlineAsmRegOrRegClass> reg;
    3051              :     bool late;
    3052              :     std::unique_ptr<Expr> in_expr;
    3053              :     std::unique_ptr<Expr> out_expr; // could be null
    3054              : 
    3055              :     SplitInOut (tl::optional<struct AST::InlineAsmRegOrRegClass> &reg,
    3056              :                 bool late, std::unique_ptr<Expr> in_expr,
    3057              :                 std::unique_ptr<Expr> out_expr);
    3058              : 
    3059              :     SplitInOut (const struct SplitInOut &other);
    3060              : 
    3061              :     SplitInOut operator= (const struct SplitInOut &other);
    3062              :   };
    3063              : 
    3064            0 :   struct Const
    3065              :   {
    3066              :     AnonConst anon_const;
    3067              :   };
    3068              : 
    3069            0 :   struct Sym
    3070              :   {
    3071              :     std::unique_ptr<Expr> expr;
    3072              : 
    3073              :     Sym (std::unique_ptr<Expr> expr);
    3074              : 
    3075              :     Sym (const struct Sym &other);
    3076              : 
    3077              :     Sym operator= (const struct Sym &other);
    3078              :   };
    3079              : 
    3080            0 :   struct Label
    3081              :   {
    3082              :     std::string label_name;
    3083              :     std::unique_ptr<Expr> expr;
    3084              : 
    3085              :     Label (tl::optional<std::string> label_name, std::unique_ptr<Expr> expr);
    3086              : 
    3087              :     Label (const struct Label &other);
    3088              : 
    3089              :     Label operator= (const struct Label &other);
    3090              :   };
    3091              : 
    3092              :   using RegisterType = AST::InlineAsmOperand::RegisterType;
    3093              : 
    3094              : private:
    3095              :   AST::InlineAsmOperand::RegisterType register_type;
    3096              : 
    3097              :   tl::optional<struct In> in;
    3098              :   tl::optional<struct Out> out;
    3099              :   tl::optional<struct InOut> in_out;
    3100              :   tl::optional<struct SplitInOut> split_in_out;
    3101              :   tl::optional<struct Const> cnst;
    3102              :   tl::optional<struct Sym> sym;
    3103              :   tl::optional<struct Label> label;
    3104              : 
    3105              : public:
    3106           67 :   InlineAsmOperand (const InlineAsmOperand &other)
    3107           67 :     : register_type (other.register_type), in (other.in), out (other.out),
    3108           67 :       in_out (other.in_out), split_in_out (other.split_in_out),
    3109           67 :       cnst (other.cnst), sym (other.sym)
    3110           67 :   {}
    3111              : 
    3112           10 :   InlineAsmOperand (const struct In &reg)
    3113           10 :     : register_type (RegisterType::In), in (reg)
    3114           10 :   {}
    3115              : 
    3116           17 :   InlineAsmOperand (const struct Out &reg)
    3117           17 :     : register_type (RegisterType::Out), out (reg)
    3118           17 :   {}
    3119            0 :   InlineAsmOperand (const struct InOut &reg)
    3120            0 :     : register_type (RegisterType::InOut), in_out (reg)
    3121            0 :   {}
    3122            2 :   InlineAsmOperand (const struct SplitInOut &reg)
    3123            2 :     : register_type (RegisterType::SplitInOut), split_in_out (reg)
    3124            2 :   {}
    3125            0 :   InlineAsmOperand (const struct Const &reg)
    3126            0 :     : register_type (RegisterType::Const), cnst (reg)
    3127            0 :   {}
    3128            0 :   InlineAsmOperand (const struct Sym &reg)
    3129            0 :     : register_type (RegisterType::Sym), sym (reg)
    3130            0 :   {}
    3131            0 :   InlineAsmOperand (const struct Label &reg)
    3132            0 :     : register_type (RegisterType::Label), label (reg)
    3133            0 :   {}
    3134              : 
    3135          116 :   RegisterType get_register_type () const { return register_type; }
    3136              : 
    3137              :   // Potentially unsafe without get_register_type() check
    3138           10 :   const struct In &get_in () const { return in.value (); }
    3139           17 :   const struct Out &get_out () const { return out.value (); }
    3140            0 :   const struct InOut &get_in_out () const { return in_out.value (); }
    3141            2 :   const struct SplitInOut &get_split_in_out () const
    3142              :   {
    3143            2 :     return split_in_out.value ();
    3144              :   }
    3145            0 :   const struct Const &get_const () const { return cnst.value (); }
    3146            0 :   const struct Sym &get_sym () const { return sym.value (); }
    3147            0 :   const struct Label &get_label () const { return label.value (); }
    3148              : 
    3149           20 :   struct In &get_in () { return in.value (); }
    3150           34 :   struct Out &get_out () { return out.value (); }
    3151            0 :   struct InOut &get_in_out () { return in_out.value (); }
    3152            8 :   struct SplitInOut &get_split_in_out () { return split_in_out.value (); }
    3153            0 :   struct Const &get_const () { return cnst.value (); }
    3154            0 :   struct Sym &get_sym () { return sym.value (); }
    3155            0 :   struct Label &get_label () { return label.value (); }
    3156              : };
    3157              : 
    3158              : // Inline Assembly Node
    3159              : class InlineAsm : public ExprWithoutBlock
    3160              : {
    3161              :   NodeId id;
    3162              :   location_t locus;
    3163              : 
    3164              : public:
    3165              :   bool is_global_asm;
    3166              : 
    3167              :   std::vector<AST::InlineAsmTemplatePiece> template_;
    3168              :   std::vector<AST::TupleTemplateStr> template_strs;
    3169              :   std::vector<HIR::InlineAsmOperand> operands;
    3170              :   std::vector<AST::TupleClobber> clobber_abi;
    3171              :   std::set<AST::InlineAsm::Option> options;
    3172              : 
    3173              :   std::vector<location_t> line_spans;
    3174              : 
    3175              :   void accept_vis (HIRExpressionVisitor &vis) override;
    3176              : 
    3177              :   void accept_vis (HIRFullVisitor &vis) override;
    3178              : 
    3179            0 :   std::string to_string () const override { return "InlineAsm HIR Node"; }
    3180              : 
    3181           58 :   location_t get_locus () const override { return locus; }
    3182              : 
    3183            0 :   InlineAsm *clone_expr_without_block_impl () const override
    3184              :   {
    3185            0 :     return new InlineAsm (*this);
    3186              :   }
    3187              : 
    3188            0 :   ExprType get_expression_type () const final override
    3189              :   {
    3190            0 :     return ExprType::InlineAsm;
    3191              :   }
    3192            0 :   std::vector<AST::InlineAsmTemplatePiece> get_template_ ()
    3193              :   {
    3194            0 :     return template_;
    3195              :   }
    3196              : 
    3197            0 :   std::vector<AST::TupleTemplateStr> get_template_strs ()
    3198              :   {
    3199            0 :     return template_strs;
    3200              :   }
    3201              : 
    3202          103 :   std::vector<HIR::InlineAsmOperand> &get_operands () { return operands; }
    3203              : 
    3204              :   std::vector<AST::TupleClobber> get_clobber_abi () { return clobber_abi; }
    3205              : 
    3206              :   std::set<AST::InlineAsm::Option> get_options () { return options; }
    3207              : 
    3208           26 :   bool is_simple_asm ()
    3209              :   {
    3210              :     // INFO: A simple asm is an asm that does not have any operands
    3211           26 :     return this->operands.size () == 0;
    3212              :   }
    3213              : 
    3214           26 :   bool is_inline_asm ()
    3215              :   {
    3216              :     // INFO: An inline asm is asm!, which is the opposite of a global_asm()
    3217           26 :     return !this->is_global_asm;
    3218              :   }
    3219              : 
    3220              :   InlineAsm (location_t locus, bool is_global_asm,
    3221              :              std::vector<AST::InlineAsmTemplatePiece> template_,
    3222              :              std::vector<AST::TupleTemplateStr> template_strs,
    3223              :              std::vector<HIR::InlineAsmOperand> operands,
    3224              :              std::vector<AST::TupleClobber> clobber_abi,
    3225              :              std::set<AST::InlineAsm::Option> options,
    3226              :              Analysis::NodeMapping mappings,
    3227              :              AST::AttrVec outer_attribs = AST::AttrVec ());
    3228              : };
    3229              : 
    3230              : class OffsetOf : public ExprWithoutBlock
    3231              : {
    3232              : public:
    3233           15 :   OffsetOf (std::unique_ptr<Type> &&type, Identifier field,
    3234              :             Analysis::NodeMapping mappings, location_t loc)
    3235           30 :     : ExprWithoutBlock (mappings), type (std::move (type)), field (field),
    3236           15 :       loc (loc)
    3237           15 :   {}
    3238              : 
    3239            0 :   OffsetOf (const OffsetOf &other)
    3240            0 :     : ExprWithoutBlock (other), type (other.type->clone_type ()),
    3241            0 :       field (other.field), loc (other.loc)
    3242            0 :   {}
    3243              : 
    3244              :   OffsetOf &operator= (const OffsetOf &other);
    3245              : 
    3246              :   ExprWithoutBlock *clone_expr_without_block_impl () const override;
    3247              :   std::string to_string () const override;
    3248              : 
    3249              :   void accept_vis (HIRExpressionVisitor &vis) override;
    3250              :   void accept_vis (HIRFullVisitor &vis) override;
    3251              : 
    3252            0 :   ExprType get_expression_type () const override { return ExprType::OffsetOf; }
    3253              : 
    3254           44 :   location_t get_locus () const override { return loc; }
    3255              : 
    3256           29 :   Type &get_type () { return *type; }
    3257              :   const Type &get_type () const { return *type; }
    3258              :   const Identifier &get_field () const { return field; }
    3259              : 
    3260              : private:
    3261              :   std::unique_ptr<Type> type;
    3262              :   Identifier field;
    3263              :   location_t loc;
    3264              : };
    3265              : 
    3266            4 : struct LlvmOperand
    3267              : {
    3268              :   std::string constraint;
    3269              :   std::unique_ptr<Expr> expr;
    3270              : 
    3271            2 :   LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr)
    3272            4 :     : constraint (constraint), expr (std::move (expr))
    3273              :   {}
    3274              : 
    3275            4 :   LlvmOperand (const LlvmOperand &other)
    3276            8 :     : constraint (other.constraint), expr (other.expr->clone_expr ())
    3277            4 :   {}
    3278              :   LlvmOperand &operator= (const LlvmOperand &other)
    3279              :   {
    3280              :     constraint = other.constraint;
    3281              :     expr = other.expr->clone_expr ();
    3282              : 
    3283              :     return *this;
    3284              :   }
    3285              : };
    3286              : 
    3287              : class LlvmInlineAsm : public ExprWithoutBlock
    3288              : {
    3289              : public:
    3290              :   struct Options
    3291              :   {
    3292              :     bool is_volatile;
    3293              :     bool align_stack;
    3294              :     AST::LlvmInlineAsm::Dialect dialect;
    3295              :   };
    3296              : 
    3297              :   location_t locus;
    3298              :   AST::AttrVec outer_attrs;
    3299              :   std::vector<LlvmOperand> inputs;
    3300              :   std::vector<LlvmOperand> outputs;
    3301              :   std::vector<AST::TupleTemplateStr> templates;
    3302              :   std::vector<AST::TupleClobber> clobbers;
    3303              :   Options options;
    3304              : 
    3305            2 :   LlvmInlineAsm (location_t locus, std::vector<LlvmOperand> inputs,
    3306              :                  std::vector<LlvmOperand> outputs,
    3307              :                  std::vector<AST::TupleTemplateStr> templates,
    3308              :                  std::vector<AST::TupleClobber> clobbers, Options options,
    3309              :                  AST::AttrVec outer_attrs, Analysis::NodeMapping mappings)
    3310            4 :     : ExprWithoutBlock (mappings, std::move (outer_attrs)), locus (locus),
    3311            2 :       inputs (std::move (inputs)), outputs (std::move (outputs)),
    3312            2 :       templates (std::move (templates)), clobbers (std::move (clobbers)),
    3313            2 :       options (options)
    3314            2 :   {}
    3315              : 
    3316              :   AST::LlvmInlineAsm::Dialect get_dialect () { return options.dialect; }
    3317              : 
    3318            4 :   location_t get_locus () const override { return locus; }
    3319              : 
    3320              :   std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; }
    3321              : 
    3322              :   void accept_vis (HIRFullVisitor &vis) override;
    3323              :   void accept_vis (HIRExpressionVisitor &vis) override;
    3324              : 
    3325            0 :   LlvmInlineAsm *clone_expr_without_block_impl () const override
    3326              :   {
    3327            0 :     return new LlvmInlineAsm (*this);
    3328              :   }
    3329              : 
    3330              :   std::vector<AST::TupleTemplateStr> &get_templates () { return templates; }
    3331              : 
    3332            0 :   Expr::ExprType get_expression_type () const override
    3333              :   {
    3334            0 :     return Expr::ExprType::LlvmInlineAsm;
    3335              :   }
    3336              : 
    3337            2 :   std::vector<AST::TupleClobber> get_clobbers () { return clobbers; }
    3338              : };
    3339              : 
    3340              : } // namespace HIR
    3341              : } // namespace Rust
    3342              : 
    3343              : #endif
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.