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_AST_LOWER_STMT
      20  #define RUST_AST_LOWER_STMT
      21  
      22  #include "rust-diagnostics.h"
      23  
      24  #include "rust-ast-lower-base.h"
      25  #include "rust-ast-lower-enumitem.h"
      26  #include "rust-ast-lower-type.h"
      27  #include "rust-ast-lower-block.h"
      28  #include "rust-ast-lower-expr.h"
      29  #include "rust-ast-lower-pattern.h"
      30  
      31  namespace Rust {
      32  namespace HIR {
      33  
      34  class ASTLoweringStmt : public ASTLoweringBase
      35  {
      36    using Rust::HIR::ASTLoweringBase::visit;
      37  
      38  public:
      39    static HIR::Stmt *translate (AST::Stmt *stmt, bool *terminated)
      40    {
      41      ASTLoweringStmt resolver;
      42      stmt->accept_vis (resolver);
      43  
      44      rust_assert (resolver.translated != nullptr);
      45      *terminated = resolver.terminated;
      46      resolver.mappings->insert_location (
      47        resolver.translated->get_mappings ().get_hirid (),
      48        resolver.translated->get_locus ());
      49      resolver.mappings->insert_hir_stmt (resolver.translated);
      50      if (resolver.translated->is_item ())
      51        {
      52  	HIR::Item *i = static_cast<HIR::Item *> (resolver.translated);
      53  
      54  	auto defid = resolver.translated->get_mappings ().get_defid ();
      55  
      56  	resolver.handle_outer_attributes (*i);
      57  	resolver.mappings->insert_hir_item (i);
      58  	resolver.mappings->insert_defid_mapping (defid, i);
      59        }
      60  
      61      return resolver.translated;
      62    }
      63  
      64    void visit (AST::ExprStmtWithBlock &stmt) override
      65    {
      66      HIR::ExprWithBlock *expr
      67        = ASTLoweringExprWithBlock::translate (stmt.get_expr ().get (),
      68  					     &terminated);
      69  
      70      auto crate_num = mappings->get_current_crate ();
      71      Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (),
      72  				   mappings->get_next_hir_id (crate_num),
      73  				   UNKNOWN_LOCAL_DEFID);
      74      translated
      75        = new HIR::ExprStmtWithBlock (mapping,
      76  				    std::unique_ptr<HIR::ExprWithBlock> (expr),
      77  				    stmt.get_locus (),
      78  				    !stmt.is_semicolon_followed ());
      79    }
      80  
      81    void visit (AST::ExprStmtWithoutBlock &stmt) override
      82    {
      83      HIR::Expr *expr
      84        = ASTLoweringExpr::translate (stmt.get_expr ().get (), &terminated);
      85  
      86      auto crate_num = mappings->get_current_crate ();
      87      Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (),
      88  				   mappings->get_next_hir_id (crate_num),
      89  				   UNKNOWN_LOCAL_DEFID);
      90      translated
      91        = new HIR::ExprStmtWithoutBlock (mapping,
      92  				       std::unique_ptr<HIR::Expr> (expr),
      93  				       stmt.get_locus ());
      94    }
      95  
      96    void visit (AST::ConstantItem &constant) override
      97    {
      98      HIR::Visibility vis = translate_visibility (constant.get_visibility ());
      99  
     100      HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ());
     101      HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ());
     102  
     103      auto crate_num = mappings->get_current_crate ();
     104      Analysis::NodeMapping mapping (crate_num, constant.get_node_id (),
     105  				   mappings->get_next_hir_id (crate_num),
     106  				   mappings->get_next_localdef_id (crate_num));
     107  
     108      translated = new HIR::ConstantItem (mapping, constant.get_identifier (),
     109  					vis, std::unique_ptr<HIR::Type> (type),
     110  					std::unique_ptr<HIR::Expr> (expr),
     111  					constant.get_outer_attrs (),
     112  					constant.get_locus ());
     113    }
     114  
     115    void visit (AST::LetStmt &stmt) override
     116    {
     117      HIR::Pattern *variables
     118        = ASTLoweringPattern::translate (stmt.get_pattern ().get ());
     119      HIR::Type *type = stmt.has_type ()
     120  			? ASTLoweringType::translate (stmt.get_type ().get ())
     121  			: nullptr;
     122      HIR::Expr *init_expression
     123        = stmt.has_init_expr ()
     124  	  ? ASTLoweringExpr::translate (stmt.get_init_expr ().get ())
     125  	  : nullptr;
     126  
     127      auto crate_num = mappings->get_current_crate ();
     128      Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (),
     129  				   mappings->get_next_hir_id (crate_num),
     130  				   UNKNOWN_LOCAL_DEFID);
     131      translated
     132        = new HIR::LetStmt (mapping, std::unique_ptr<HIR::Pattern> (variables),
     133  			  std::unique_ptr<HIR::Expr> (init_expression),
     134  			  std::unique_ptr<HIR::Type> (type),
     135  			  stmt.get_outer_attrs (), stmt.get_locus ());
     136    }
     137  
     138    void visit (AST::TupleStruct &struct_decl) override
     139    {
     140      std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
     141      if (struct_decl.has_generics ())
     142        {
     143  	generic_params
     144  	  = lower_generic_params (struct_decl.get_generic_params ());
     145        }
     146  
     147      std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
     148      HIR::WhereClause where_clause (std::move (where_clause_items));
     149      HIR::Visibility vis = translate_visibility (struct_decl.get_visibility ());
     150  
     151      std::vector<HIR::TupleField> fields;
     152      for (AST::TupleField &field : struct_decl.get_fields ())
     153        {
     154  	HIR::Visibility vis = translate_visibility (field.get_visibility ());
     155  	HIR::Type *type
     156  	  = ASTLoweringType::translate (field.get_field_type ().get ());
     157  
     158  	auto crate_num = mappings->get_current_crate ();
     159  	Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
     160  				       mappings->get_next_hir_id (crate_num),
     161  				       mappings->get_next_localdef_id (
     162  					 crate_num));
     163  
     164  	HIR::TupleField translated_field (mapping,
     165  					  std::unique_ptr<HIR::Type> (type),
     166  					  vis, field.get_locus (),
     167  					  field.get_outer_attrs ());
     168  	fields.push_back (std::move (translated_field));
     169        }
     170  
     171      auto crate_num = mappings->get_current_crate ();
     172      Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (),
     173  				   mappings->get_next_hir_id (crate_num),
     174  				   mappings->get_next_localdef_id (crate_num));
     175  
     176      translated = new HIR::TupleStruct (mapping, std::move (fields),
     177  				       struct_decl.get_identifier (),
     178  				       std::move (generic_params),
     179  				       std::move (where_clause), vis,
     180  				       struct_decl.get_outer_attrs (),
     181  				       struct_decl.get_locus ());
     182    }
     183  
     184    void visit (AST::StructStruct &struct_decl) override
     185    {
     186      std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
     187      if (struct_decl.has_generics ())
     188        {
     189  	generic_params
     190  	  = lower_generic_params (struct_decl.get_generic_params ());
     191        }
     192  
     193      std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
     194      HIR::WhereClause where_clause (std::move (where_clause_items));
     195      HIR::Visibility vis = translate_visibility (struct_decl.get_visibility ());
     196  
     197      bool is_unit = struct_decl.is_unit_struct ();
     198      std::vector<HIR::StructField> fields;
     199      for (AST::StructField &field : struct_decl.get_fields ())
     200        {
     201  	HIR::Visibility vis = translate_visibility (field.get_visibility ());
     202  	HIR::Type *type
     203  	  = ASTLoweringType::translate (field.get_field_type ().get ());
     204  
     205  	auto crate_num = mappings->get_current_crate ();
     206  	Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
     207  				       mappings->get_next_hir_id (crate_num),
     208  				       mappings->get_next_localdef_id (
     209  					 crate_num));
     210  
     211  	HIR::StructField translated_field (mapping, field.get_field_name (),
     212  					   std::unique_ptr<HIR::Type> (type),
     213  					   vis, field.get_locus (),
     214  					   field.get_outer_attrs ());
     215  
     216  	if (struct_field_name_exists (fields, translated_field))
     217  	  break;
     218  
     219  	fields.push_back (std::move (translated_field));
     220        }
     221  
     222      auto crate_num = mappings->get_current_crate ();
     223      Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (),
     224  				   mappings->get_next_hir_id (crate_num),
     225  				   mappings->get_next_localdef_id (crate_num));
     226  
     227      translated = new HIR::StructStruct (mapping, std::move (fields),
     228  					struct_decl.get_identifier (),
     229  					std::move (generic_params),
     230  					std::move (where_clause), is_unit, vis,
     231  					struct_decl.get_outer_attrs (),
     232  					struct_decl.get_locus ());
     233    }
     234  
     235    void visit (AST::Union &union_decl) override
     236    {
     237      std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
     238      if (union_decl.has_generics ())
     239        {
     240  	generic_params
     241  	  = lower_generic_params (union_decl.get_generic_params ());
     242        }
     243  
     244      std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
     245      HIR::WhereClause where_clause (std::move (where_clause_items));
     246      HIR::Visibility vis = translate_visibility (union_decl.get_visibility ());
     247  
     248      std::vector<HIR::StructField> variants;
     249      for (AST::StructField &variant : union_decl.get_variants ())
     250        {
     251  	HIR::Visibility vis = translate_visibility (variant.get_visibility ());
     252  	HIR::Type *type
     253  	  = ASTLoweringType::translate (variant.get_field_type ().get ());
     254  
     255  	auto crate_num = mappings->get_current_crate ();
     256  	Analysis::NodeMapping mapping (crate_num, variant.get_node_id (),
     257  				       mappings->get_next_hir_id (crate_num),
     258  				       mappings->get_next_localdef_id (
     259  					 crate_num));
     260  
     261  	HIR::StructField translated_variant (mapping, variant.get_field_name (),
     262  					     std::unique_ptr<HIR::Type> (type),
     263  					     vis, variant.get_locus (),
     264  					     variant.get_outer_attrs ());
     265  
     266  	if (struct_field_name_exists (variants, translated_variant))
     267  	  break;
     268  
     269  	variants.push_back (std::move (translated_variant));
     270        }
     271  
     272      auto crate_num = mappings->get_current_crate ();
     273      Analysis::NodeMapping mapping (crate_num, union_decl.get_node_id (),
     274  				   mappings->get_next_hir_id (crate_num),
     275  				   mappings->get_next_localdef_id (crate_num));
     276  
     277      translated
     278        = new HIR::Union (mapping, union_decl.get_identifier (), vis,
     279  			std::move (generic_params), std::move (where_clause),
     280  			std::move (variants), union_decl.get_outer_attrs (),
     281  			union_decl.get_locus ());
     282    }
     283  
     284    void visit (AST::Enum &enum_decl) override
     285    {
     286      std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
     287      if (enum_decl.has_generics ())
     288        {
     289  	generic_params = lower_generic_params (enum_decl.get_generic_params ());
     290        }
     291  
     292      std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
     293      HIR::WhereClause where_clause (std::move (where_clause_items));
     294      HIR::Visibility vis = translate_visibility (enum_decl.get_visibility ());
     295  
     296      // bool is_unit = enum_decl.is_zero_variant ();
     297      std::vector<std::unique_ptr<HIR::EnumItem>> items;
     298      for (auto &variant : enum_decl.get_variants ())
     299        {
     300  	HIR::EnumItem *hir_item
     301  	  = ASTLoweringEnumItem::translate (variant.get ());
     302  	items.push_back (std::unique_ptr<HIR::EnumItem> (hir_item));
     303        }
     304  
     305      auto crate_num = mappings->get_current_crate ();
     306      Analysis::NodeMapping mapping (crate_num, enum_decl.get_node_id (),
     307  				   mappings->get_next_hir_id (crate_num),
     308  				   mappings->get_next_localdef_id (crate_num));
     309  
     310      translated = new HIR::Enum (mapping, enum_decl.get_identifier (), vis,
     311  				std::move (generic_params),
     312  				std::move (where_clause), /* is_unit, */
     313  				std::move (items), enum_decl.get_outer_attrs (),
     314  				enum_decl.get_locus ());
     315    }
     316  
     317    void visit (AST::EmptyStmt &empty) override
     318    {
     319      auto crate_num = mappings->get_current_crate ();
     320      Analysis::NodeMapping mapping (crate_num, empty.get_node_id (),
     321  				   mappings->get_next_hir_id (crate_num),
     322  				   mappings->get_next_localdef_id (crate_num));
     323  
     324      translated = new HIR::EmptyStmt (mapping, empty.get_locus ());
     325    }
     326  
     327    void visit (AST::Function &function) override
     328    {
     329      // ignore for now and leave empty
     330      std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
     331      HIR::WhereClause where_clause (std::move (where_clause_items));
     332      HIR::FunctionQualifiers qualifiers
     333        = lower_qualifiers (function.get_qualifiers ());
     334      HIR::Visibility vis = translate_visibility (function.get_visibility ());
     335  
     336      // need
     337      std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
     338      if (function.has_generics ())
     339        {
     340  	generic_params = lower_generic_params (function.get_generic_params ());
     341        }
     342  
     343      Identifier function_name = function.get_function_name ();
     344      Location locus = function.get_locus ();
     345  
     346      std::unique_ptr<HIR::Type> return_type
     347        = function.has_return_type () ? std::unique_ptr<HIR::Type> (
     348  	  ASTLoweringType::translate (function.get_return_type ().get ()))
     349  				    : nullptr;
     350  
     351      std::vector<HIR::FunctionParam> function_params;
     352      for (auto ¶m : function.get_function_params ())
     353        {
     354  	auto translated_pattern = std::unique_ptr<HIR::Pattern> (
     355  	  ASTLoweringPattern::translate (param.get_pattern ().get ()));
     356  	auto translated_type = std::unique_ptr<HIR::Type> (
     357  	  ASTLoweringType::translate (param.get_type ().get ()));
     358  
     359  	auto crate_num = mappings->get_current_crate ();
     360  	Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
     361  				       mappings->get_next_hir_id (crate_num),
     362  				       UNKNOWN_LOCAL_DEFID);
     363  
     364  	auto hir_param
     365  	  = HIR::FunctionParam (mapping, std::move (translated_pattern),
     366  				std::move (translated_type),
     367  				param.get_locus ());
     368  	function_params.push_back (hir_param);
     369        }
     370  
     371      bool terminated = false;
     372      std::unique_ptr<HIR::BlockExpr> function_body
     373        = std::unique_ptr<HIR::BlockExpr> (
     374  	ASTLoweringBlock::translate (function.get_definition ().get (),
     375  				     &terminated));
     376  
     377      auto crate_num = mappings->get_current_crate ();
     378      Analysis::NodeMapping mapping (crate_num, function.get_node_id (),
     379  				   mappings->get_next_hir_id (crate_num),
     380  				   mappings->get_next_localdef_id (crate_num));
     381  
     382      mappings->insert_location (function_body->get_mappings ().get_hirid (),
     383  			       function.get_locus ());
     384  
     385      auto fn
     386        = new HIR::Function (mapping, std::move (function_name),
     387  			   std::move (qualifiers), std::move (generic_params),
     388  			   std::move (function_params), std::move (return_type),
     389  			   std::move (where_clause), std::move (function_body),
     390  			   std::move (vis), function.get_outer_attrs (),
     391  			   HIR::SelfParam::error (), locus);
     392  
     393      // add the mappings for the function params at the end
     394      for (auto ¶m : fn->get_function_params ())
     395        {
     396  	mappings->insert_hir_param (¶m);
     397  	mappings->insert_location (mapping.get_hirid (), param.get_locus ());
     398        }
     399  
     400      translated = fn;
     401    }
     402  
     403    void visit (AST::ExternBlock &extern_block) override
     404    {
     405      translated = lower_extern_block (extern_block);
     406    }
     407  
     408  private:
     409    ASTLoweringStmt () : translated (nullptr), terminated (false) {}
     410  
     411    HIR::Stmt *translated;
     412    bool terminated;
     413  };
     414  
     415  } // namespace HIR
     416  } // namespace Rust
     417  
     418  #endif // RUST_AST_LOWER_PATTERN