1  // Copyright (C) 2020-2023 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_STATEMENT_H
      20  #define RUST_HIR_STATEMENT_H
      21  
      22  #include "rust-hir.h"
      23  #include "rust-hir-path.h"
      24  #include "rust-hir-expr.h"
      25  
      26  namespace Rust {
      27  namespace HIR {
      28  // Just a semi-colon, which apparently is a statement.
      29  class EmptyStmt : public Stmt
      30  {
      31    Location locus;
      32  
      33  public:
      34    std::string as_string () const override { return std::string (1, ';'); }
      35  
      36    EmptyStmt (Analysis::NodeMapping mappings, Location locus)
      37      : Stmt (std::move (mappings)), locus (locus)
      38    {}
      39  
      40    Location get_locus () const override final { return locus; }
      41  
      42    void accept_vis (HIRFullVisitor &vis) override;
      43    void accept_vis (HIRStmtVisitor &vis) override;
      44  
      45    bool is_item () const override final { return false; }
      46  
      47  protected:
      48    /* Use covariance to implement clone function as returning this object rather
      49     * than base */
      50    EmptyStmt *clone_stmt_impl () const override { return new EmptyStmt (*this); }
      51  };
      52  
      53  /* Variable assignment let statement - type of "declaration statement" as it
      54   * introduces new name into scope */
      55  class LetStmt : public Stmt
      56  {
      57    // bool has_outer_attrs;
      58    AST::AttrVec outer_attrs;
      59  
      60    std::unique_ptr<Pattern> variables_pattern;
      61  
      62    // bool has_type;
      63    std::unique_ptr<Type> type;
      64  
      65    // bool has_init_expr;
      66    std::unique_ptr<Expr> init_expr;
      67  
      68    Location locus;
      69  
      70  public:
      71    // Returns whether let statement has outer attributes.
      72    bool has_outer_attrs () const { return !outer_attrs.empty (); }
      73  
      74    // Returns whether let statement has a given return type.
      75    bool has_type () const { return type != nullptr; }
      76  
      77    // Returns whether let statement has an initialisation expression.
      78    bool has_init_expr () const { return init_expr != nullptr; }
      79  
      80    std::string as_string () const override;
      81  
      82    LetStmt (Analysis::NodeMapping mappings,
      83  	   std::unique_ptr<Pattern> variables_pattern,
      84  	   std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type,
      85  	   AST::AttrVec outer_attrs, Location locus)
      86      : Stmt (std::move (mappings)), outer_attrs (std::move (outer_attrs)),
      87        variables_pattern (std::move (variables_pattern)),
      88        type (std::move (type)), init_expr (std::move (init_expr)), locus (locus)
      89    {}
      90  
      91    // Copy constructor with clone
      92    LetStmt (LetStmt const &other)
      93      : Stmt (other.mappings), outer_attrs (other.outer_attrs),
      94        locus (other.locus)
      95    {
      96      // guard to prevent null dereference (only required if error state)
      97      if (other.variables_pattern != nullptr)
      98        variables_pattern = other.variables_pattern->clone_pattern ();
      99  
     100      // guard to prevent null dereference (always required)
     101      if (other.init_expr != nullptr)
     102        init_expr = other.init_expr->clone_expr ();
     103      if (other.type != nullptr)
     104        type = other.type->clone_type ();
     105    }
     106  
     107    // Overloaded assignment operator to clone
     108    LetStmt &operator= (LetStmt const &other)
     109    {
     110      outer_attrs = other.outer_attrs;
     111      locus = other.locus;
     112  
     113      // guard to prevent null dereference (only required if error state)
     114      if (other.variables_pattern != nullptr)
     115        variables_pattern = other.variables_pattern->clone_pattern ();
     116      else
     117        variables_pattern = nullptr;
     118  
     119      // guard to prevent null dereference (always required)
     120      if (other.init_expr != nullptr)
     121        init_expr = other.init_expr->clone_expr ();
     122      else
     123        init_expr = nullptr;
     124      if (other.type != nullptr)
     125        type = other.type->clone_type ();
     126      else
     127        type = nullptr;
     128  
     129      return *this;
     130    }
     131  
     132    // move constructors
     133    LetStmt (LetStmt &&other) = default;
     134    LetStmt &operator= (LetStmt &&other) = default;
     135  
     136    Location get_locus () const override final { return locus; }
     137  
     138    void accept_vis (HIRFullVisitor &vis) override;
     139    void accept_vis (HIRStmtVisitor &vis) override;
     140  
     141    HIR::Type *get_type () { return type.get (); }
     142  
     143    HIR::Expr *get_init_expr () { return init_expr.get (); }
     144  
     145    HIR::Pattern *get_pattern () { return variables_pattern.get (); }
     146  
     147    bool is_item () const override final { return false; }
     148  
     149  protected:
     150    /* Use covariance to implement clone function as returning this object rather
     151     * than base */
     152    LetStmt *clone_stmt_impl () const override { return new LetStmt (*this); }
     153  };
     154  
     155  /* Abstract base class for expression statements (statements containing an
     156   * expression) */
     157  class ExprStmt : public Stmt
     158  {
     159    // TODO: add any useful virtual functions
     160  
     161    Location locus;
     162  
     163  public:
     164    Location get_locus () const override final { return locus; }
     165  
     166    bool is_item () const override final { return false; }
     167  
     168  protected:
     169    ExprStmt (Analysis::NodeMapping mappings, Location locus)
     170      : Stmt (std::move (mappings)), locus (locus)
     171    {}
     172  };
     173  
     174  /* Statement containing an expression without a block (or, due to technical
     175   * difficulties, can only be guaranteed to hold an expression). */
     176  class ExprStmtWithoutBlock : public ExprStmt
     177  {
     178    std::unique_ptr<Expr> expr;
     179  
     180  public:
     181    std::string as_string () const override;
     182  
     183    ExprStmtWithoutBlock (Analysis::NodeMapping mappings,
     184  			std::unique_ptr<Expr> expr, Location locus)
     185      : ExprStmt (std::move (mappings), locus), expr (std::move (expr))
     186    {}
     187  
     188    // Copy constructor with clone
     189    ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other)
     190      : ExprStmt (other), expr (other.expr->clone_expr ())
     191    {}
     192  
     193    // Overloaded assignment operator to clone
     194    ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other)
     195    {
     196      ExprStmt::operator= (other);
     197      expr = other.expr->clone_expr ();
     198  
     199      return *this;
     200    }
     201  
     202    // move constructors
     203    ExprStmtWithoutBlock (ExprStmtWithoutBlock &&other) = default;
     204    ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock &&other) = default;
     205  
     206    void accept_vis (HIRFullVisitor &vis) override;
     207    void accept_vis (HIRStmtVisitor &vis) override;
     208  
     209    Expr *get_expr () { return expr.get (); }
     210  
     211  protected:
     212    /* Use covariance to implement clone function as returning this object rather
     213     * than base */
     214    ExprStmtWithoutBlock *clone_stmt_impl () const override
     215    {
     216      return new ExprStmtWithoutBlock (*this);
     217    }
     218  };
     219  
     220  // Statement containing an expression with a block
     221  class ExprStmtWithBlock : public ExprStmt
     222  {
     223    std::unique_ptr<ExprWithBlock> expr;
     224    bool must_be_unit;
     225  
     226  public:
     227    std::string as_string () const override;
     228  
     229    ExprStmtWithBlock (Analysis::NodeMapping mappings,
     230  		     std::unique_ptr<ExprWithBlock> expr, Location locus,
     231  		     bool must_be_unit)
     232      : ExprStmt (std::move (mappings), locus), expr (std::move (expr)),
     233        must_be_unit (must_be_unit)
     234    {}
     235  
     236    // Copy constructor with clone
     237    ExprStmtWithBlock (ExprStmtWithBlock const &other)
     238      : ExprStmt (other), expr (other.expr->clone_expr_with_block ())
     239    {}
     240  
     241    // Overloaded assignment operator to clone
     242    ExprStmtWithBlock &operator= (ExprStmtWithBlock const &other)
     243    {
     244      ExprStmt::operator= (other);
     245      expr = other.expr->clone_expr_with_block ();
     246  
     247      return *this;
     248    }
     249  
     250    // move constructors
     251    ExprStmtWithBlock (ExprStmtWithBlock &&other) = default;
     252    ExprStmtWithBlock &operator= (ExprStmtWithBlock &&other) = default;
     253  
     254    void accept_vis (HIRFullVisitor &vis) override;
     255    void accept_vis (HIRStmtVisitor &vis) override;
     256  
     257    ExprWithBlock *get_expr () { return expr.get (); }
     258  
     259    bool is_unit_check_needed () const override { return must_be_unit; }
     260  
     261  protected:
     262    /* Use covariance to implement clone function as returning this object rather
     263     * than base */
     264    ExprStmtWithBlock *clone_stmt_impl () const override
     265    {
     266      return new ExprStmtWithBlock (*this);
     267    }
     268  };
     269  
     270  } // namespace HIR
     271  } // namespace Rust
     272  
     273  #endif