// Copyright (C) 2020-2023 Free Software Foundation, Inc. // This file is part of GCC. // GCC is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3, or (at your option) any later // version. // GCC is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // . #include "rust-ast-lower.h" #include "rust-ast-lower-item.h" #include "rust-ast-lower-implitem.h" #include "rust-ast-lower-expr.h" #include "rust-ast-lower-block.h" #include "rust-ast-lower-type.h" #include "rust-ast-lower-pattern.h" #include "rust-ast-lower-struct-field-expr.h" namespace Rust { namespace HIR { using HIR::ClosureParam; Visibility translate_visibility (const AST::Visibility &vis) { // FIXME: How do we create a private visibility here? Is it always private if // the AST vis is an error? // FIXME: We need to add a `create_private()` static function to the // AST::Visibility class and use it when the vis is empty in the parser... if (vis.is_error ()) return Visibility::create_error (); switch (vis.get_vis_type ()) { case AST::Visibility::PUB: return Visibility (Visibility::VisType::PUBLIC); case AST::Visibility::PRIV: case AST::Visibility::PUB_SELF: return Visibility (Visibility::VisType::PRIVATE); case AST::Visibility::PUB_CRATE: case AST::Visibility::PUB_SUPER: case AST::Visibility::PUB_IN_PATH: return Visibility (Visibility::VisType::RESTRICTED, ASTLoweringSimplePath::translate (vis.get_path ()), vis.get_locus ()); break; } return Visibility::create_error (); } ASTLowering::ASTLowering (AST::Crate &astCrate) : astCrate (astCrate) {} ASTLowering::~ASTLowering () {} std::unique_ptr ASTLowering::Resolve (AST::Crate &astCrate) { ASTLowering resolver (astCrate); return resolver.go (); } std::unique_ptr ASTLowering::go () { std::vector > items; for (auto it = astCrate.items.begin (); it != astCrate.items.end (); it++) { auto translated = ASTLoweringItem::translate (it->get ()); if (translated != nullptr) items.push_back (std::unique_ptr (translated)); } auto mappings = Analysis::Mappings::get (); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, astCrate.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); return std::unique_ptr ( new HIR::Crate (std::move (items), astCrate.get_inner_attrs (), mapping)); } // rust-ast-lower-block.h void ASTLoweringBlock::visit (AST::BlockExpr &expr) { std::vector > block_stmts; bool block_did_terminate = false; for (auto &s : expr.get_statements ()) { if (s->get_ast_kind () == AST::Kind::MACRO_RULES_DEFINITION) continue; if (s->get_ast_kind () == AST::Kind::MACRO_INVOCATION) rust_fatal_error ( s->get_locus (), "macro invocations should not get lowered to HIR - At " "this point in " "the pipeline, they should all have been expanded"); if (block_did_terminate) rust_warning_at (s->get_locus (), 0, "unreachable statement"); bool terminated = false; auto translated_stmt = ASTLoweringStmt::translate (s.get (), &terminated); block_stmts.push_back (std::unique_ptr (translated_stmt)); block_did_terminate |= terminated; } if (expr.has_tail_expr () && block_did_terminate) { // warning unreachable tail expressions rust_warning_at (expr.get_tail_expr ()->get_locus (), 0, "unreachable expression"); } HIR::ExprWithoutBlock *tail_expr = nullptr; if (expr.has_tail_expr ()) { bool terminated = false; tail_expr = (HIR::ExprWithoutBlock *) ASTLoweringExpr::translate (expr.get_tail_expr ().get (), &terminated); block_did_terminate |= terminated; } bool tail_reachable = !block_did_terminate; auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::BlockExpr (mapping, std::move (block_stmts), std::unique_ptr (tail_expr), tail_reachable, expr.get_inner_attrs (), expr.get_outer_attrs (), expr.get_start_locus (), expr.get_end_locus ()); terminated = block_did_terminate; } void ASTLoweringIfBlock::visit (AST::IfExpr &expr) { bool ignored_terminated = false; HIR::Expr *condition = ASTLoweringExpr::translate (expr.get_condition_expr ().get (), &ignored_terminated); HIR::BlockExpr *block = ASTLoweringBlock::translate (expr.get_if_block ().get (), &ignored_terminated); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::IfExpr (mapping, std::unique_ptr (condition), std::unique_ptr (block), expr.get_locus ()); } void ASTLoweringIfBlock::visit (AST::IfExprConseqElse &expr) { HIR::Expr *condition = ASTLoweringExpr::translate (expr.get_condition_expr ().get ()); bool if_block_terminated = false; bool else_block_termianted = false; HIR::BlockExpr *if_block = ASTLoweringBlock::translate (expr.get_if_block ().get (), &if_block_terminated); HIR::BlockExpr *else_block = ASTLoweringBlock::translate (expr.get_else_block ().get (), &else_block_termianted); terminated = if_block_terminated && else_block_termianted; auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::IfExprConseqElse (mapping, std::unique_ptr (condition), std::unique_ptr (if_block), std::unique_ptr (else_block), expr.get_locus ()); } void ASTLoweringIfBlock::visit (AST::IfExprConseqIf &expr) { HIR::Expr *condition = ASTLoweringExpr::translate (expr.get_condition_expr ().get ()); bool ignored_terminated = false; HIR::BlockExpr *block = ASTLoweringBlock::translate (expr.get_if_block ().get (), &ignored_terminated); HIR::IfExpr *conseq_if_expr = ASTLoweringIfBlock::translate (expr.get_conseq_if_expr ().get (), &ignored_terminated); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::IfExprConseqIf (mapping, std::unique_ptr (condition), std::unique_ptr (block), std::unique_ptr (conseq_if_expr), expr.get_locus ()); } void ASTLoweringIfLetBlock::visit (AST::IfLetExpr &expr) { std::vector > patterns; for (auto &pattern : expr.get_patterns ()) { HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ()); patterns.push_back (std::unique_ptr (ptrn)); } HIR::Expr *value_ptr = ASTLoweringExpr::translate (expr.get_value_expr ().get ()); bool ignored_terminated = false; HIR::BlockExpr *block = ASTLoweringBlock::translate (expr.get_if_block ().get (), &ignored_terminated); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::IfLetExpr (mapping, std::move (patterns), std::unique_ptr (value_ptr), std::unique_ptr (block), expr.get_locus ()); } // rust-ast-lower-struct-field-expr.h void ASTLowerStructExprField::visit (AST::StructExprFieldIdentifierValue &field) { HIR::Expr *value = ASTLoweringExpr::translate (field.get_value ().get ()); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, field.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::StructExprFieldIdentifierValue ( mapping, field.get_field_name (), std::unique_ptr (value), field.get_locus ()); } void ASTLowerStructExprField::visit (AST::StructExprFieldIndexValue &field) { HIR::Expr *value = ASTLoweringExpr::translate (field.get_value ().get ()); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, field.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::StructExprFieldIndexValue (mapping, field.get_index (), std::unique_ptr (value), field.get_locus ()); } void ASTLowerStructExprField::visit (AST::StructExprFieldIdentifier &field) { auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, field.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::StructExprFieldIdentifier (mapping, field.get_field_name (), field.get_locus ()); } // rust-ast-lower-block.h void ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr) { HIR::BlockExpr *loop_block = ASTLoweringBlock::translate (expr.get_loop_block ().get (), &terminated); HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ()); HIR::Expr *loop_condition = ASTLoweringExpr::translate (expr.get_predicate_expr ().get (), &terminated); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::WhileLoopExpr (mapping, std::unique_ptr (loop_condition), std::unique_ptr (loop_block), expr.get_locus (), std::move (loop_label), expr.get_outer_attrs ()); } void ASTLoweringExprWithBlock::visit (AST::ForLoopExpr &expr) { HIR::BlockExpr *loop_block = ASTLoweringBlock::translate (expr.get_loop_block ().get (), &terminated); HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ()); HIR::Expr *iterator_expr = ASTLoweringExpr::translate (expr.get_iterator_expr ().get (), &terminated); HIR::Pattern *loop_pattern = ASTLoweringPattern::translate (expr.get_pattern ().get ()); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::ForLoopExpr (mapping, std::unique_ptr (loop_pattern), std::unique_ptr (iterator_expr), std::unique_ptr (loop_block), expr.get_locus (), std::move (loop_label), expr.get_outer_attrs ()); } void ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr) { HIR::Expr *branch_value = ASTLoweringExpr::translate (expr.get_scrutinee_expr ().get ()); std::vector match_arms; for (auto &match_case : expr.get_match_cases ()) { HIR::Expr *kase_expr = ASTLoweringExpr::translate (match_case.get_expr ().get ()); HIR::Expr *kase_guard_expr = nullptr; if (match_case.get_arm ().has_match_arm_guard ()) { kase_guard_expr = ASTLoweringExpr::translate ( match_case.get_arm ().get_guard_expr ().get ()); } std::vector > match_arm_patterns; for (auto &pattern : match_case.get_arm ().get_patterns ()) { HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ()); match_arm_patterns.push_back (std::unique_ptr (ptrn)); } HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), std::unique_ptr (kase_guard_expr), match_case.get_arm ().get_outer_attrs ()); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); HIR::MatchCase kase (std::move (mapping), std::move (arm), std::unique_ptr (kase_expr)); match_arms.push_back (std::move (kase)); } auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::MatchExpr (mapping, std::unique_ptr (branch_value), std::move (match_arms), expr.get_inner_attrs (), expr.get_outer_attrs (), expr.get_locus ()); } // rust-ast-lower-expr.h void ASTLowerPathInExpression::visit (AST::PathInExpression &expr) { std::vector path_segments; auto &segments = expr.get_segments (); for (auto &s : segments) { path_segments.push_back (lower_path_expr_seg ((s))); // insert the mappings for the segment HIR::PathExprSegment *lowered_seg = &path_segments.back (); mappings->insert_hir_path_expr_seg (lowered_seg); } auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::PathInExpression (mapping, std::move (path_segments), expr.get_locus (), expr.opening_scope_resolution ()); } HIR::QualifiedPathType ASTLoweringBase::lower_qual_path_type (AST::QualifiedPathType &qualified_type) { HIR::Type *type = ASTLoweringType::translate (qualified_type.get_type ().get ()); HIR::TypePath *trait = qualified_type.has_as_clause () ? ASTLowerTypePath::translate (qualified_type.get_as_type_path ()) : nullptr; auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, qualified_type.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); return HIR::QualifiedPathType (mapping, std::unique_ptr (type), std::unique_ptr (trait), qualified_type.get_locus ()); } void ASTLowerQualPathInExpression::visit (AST::QualifiedPathInExpression &expr) { HIR::QualifiedPathType qual_path_type = lower_qual_path_type (expr.get_qualified_path_type ()); std::vector path_segments; auto &segments = expr.get_segments (); for (auto &s : segments) { path_segments.push_back (lower_path_expr_seg ((s))); // insert the mappings for the segment HIR::PathExprSegment *lowered_seg = &path_segments.back (); mappings->insert_hir_path_expr_seg (lowered_seg); } auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::QualifiedPathInExpression (mapping, qual_path_type, std::move (path_segments), expr.get_locus (), expr.get_outer_attrs ()); } ClosureParam ASTLoweringBase::lower_closure_param (AST::ClosureParam ¶m) { HIR::Pattern *param_pattern = ASTLoweringPattern::translate (param.get_pattern ().get ()); HIR::Type *param_type = param.has_type_given () ? ASTLoweringType::translate (param.get_type ().get ()) : nullptr; return HIR::ClosureParam (std::unique_ptr (param_pattern), param.get_locus (), param.has_type_given () ? std::unique_ptr (param_type) : nullptr, param.get_outer_attrs ()); } } // namespace HIR } // namespace Rust