// Copyright (C) 2020-2024 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-pattern.h" #include "rust-ast-lower-expr.h" namespace Rust { namespace HIR { ASTLoweringPattern::ASTLoweringPattern () : translated (nullptr) {} HIR::Pattern * ASTLoweringPattern::translate (AST::Pattern &pattern, bool is_let_top_level) { ASTLoweringPattern resolver; resolver.is_let_top_level = is_let_top_level; pattern.accept_vis (resolver); rust_assert (resolver.translated != nullptr); resolver.mappings.insert_hir_pattern (resolver.translated); resolver.mappings.insert_location ( resolver.translated->get_mappings ().get_hirid (), pattern.get_locus ()); return resolver.translated; } void ASTLoweringPattern::visit (AST::IdentifierPattern &pattern) { auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); std::unique_ptr to_bind; translated = new HIR::IdentifierPattern (mapping, pattern.get_ident (), pattern.get_locus (), pattern.get_is_ref (), pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm, std::move (to_bind)); } void ASTLoweringPattern::visit (AST::PathInExpression &pattern) { translated = ASTLowerPathInExpression::translate (pattern); } void ASTLoweringPattern::visit (AST::TupleStructPattern &pattern) { HIR::PathInExpression *path = ASTLowerPathInExpression::translate (pattern.get_path ()); TupleStructItems *lowered = nullptr; auto &items = pattern.get_items (); switch (items.get_item_type ()) { case AST::TupleStructItems::RANGE: { // TODO rust_unreachable (); } break; case AST::TupleStructItems::NO_RANGE: { AST::TupleStructItemsNoRange &items_no_range = static_cast (items); std::vector> patterns; for (auto &inner_pattern : items_no_range.get_patterns ()) { HIR::Pattern *p = ASTLoweringPattern::translate (*inner_pattern); patterns.push_back (std::unique_ptr (p)); } lowered = new HIR::TupleStructItemsNoRange (std::move (patterns)); } break; } auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::TupleStructPattern ( mapping, *path, std::unique_ptr (lowered)); } void ASTLoweringPattern::visit (AST::StructPattern &pattern) { HIR::PathInExpression *path = ASTLowerPathInExpression::translate (pattern.get_path ()); auto &raw_elems = pattern.get_struct_pattern_elems (); rust_assert (!raw_elems.has_etc ()); std::vector> fields; for (auto &field : raw_elems.get_struct_pattern_fields ()) { HIR::StructPatternField *f = nullptr; switch (field->get_item_type ()) { case AST::StructPatternField::ItemType::TUPLE_PAT: { auto &tuple = static_cast (*field); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, tuple.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); std::unique_ptr pat ( ASTLoweringPattern::translate (tuple.get_index_pattern ())); f = new HIR::StructPatternFieldTuplePat (mapping, tuple.get_index (), std::move (pat), tuple.get_outer_attrs (), tuple.get_locus ()); } break; case AST::StructPatternField::ItemType::IDENT_PAT: { AST::StructPatternFieldIdentPat &ident = static_cast (*field); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, ident.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); std::unique_ptr pat ( ASTLoweringPattern::translate (ident.get_ident_pattern ())); f = new HIR::StructPatternFieldIdentPat (mapping, ident.get_identifier (), std::move (pat), ident.get_outer_attrs (), ident.get_locus ()); } break; case AST::StructPatternField::ItemType::IDENT: { AST::StructPatternFieldIdent &ident = static_cast (*field.get ()); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, ident.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); f = new HIR::StructPatternFieldIdent ( mapping, ident.get_identifier (), ident.is_ref (), ident.is_mut () ? Mutability::Mut : Mutability::Imm, ident.get_outer_attrs (), ident.get_locus ()); } break; } // insert the reverse mappings and locations auto field_id = f->get_mappings ().get_hirid (); auto field_node_id = f->get_mappings ().get_nodeid (); mappings.insert_location (field_id, f->get_locus ()); mappings.insert_node_to_hir (field_node_id, field_id); // add it to the lowered fields list fields.push_back (std::unique_ptr (f)); } auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); HIR::StructPatternElements elems (std::move (fields)); translated = new HIR::StructPattern (mapping, *path, std::move (elems)); } void ASTLoweringPattern::visit (AST::WildcardPattern &pattern) { auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::WildcardPattern (mapping, pattern.get_locus ()); } void ASTLoweringPattern::visit (AST::TuplePattern &pattern) { std::unique_ptr items; switch (pattern.get_items ().get_pattern_type ()) { case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: { AST::TuplePatternItemsMultiple &ref = static_cast ( pattern.get_items ()); items = lower_tuple_pattern_multiple (ref); } break; case AST::TuplePatternItems::TuplePatternItemType::RANGED: { AST::TuplePatternItemsRanged &ref = static_cast (pattern.get_items ()); items = lower_tuple_pattern_ranged (ref); } break; } auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::TuplePattern (mapping, std::move (items), pattern.get_locus ()); } void ASTLoweringPattern::visit (AST::LiteralPattern &pattern) { auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); HIR::Literal l = lower_literal (pattern.get_literal ()); translated = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus ()); } void ASTLoweringPattern::visit (AST::RangePattern &pattern) { auto upper_bound = lower_range_pattern_bound (pattern.get_upper_bound ()); auto lower_bound = lower_range_pattern_bound (pattern.get_lower_bound ()); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::RangePattern (mapping, std::move (lower_bound), std::move (upper_bound), pattern.get_locus ()); } void ASTLoweringPattern::visit (AST::GroupedPattern &pattern) { is_let_top_level = false; pattern.get_pattern_in_parens ().accept_vis (*this); } void ASTLoweringPattern::visit (AST::ReferencePattern &pattern) { auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); HIR::Pattern *inner = ASTLoweringPattern::translate (pattern.get_referenced_pattern ()); translated = new HIR::ReferencePattern (mapping, std::unique_ptr (inner), pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm, pattern.get_locus ()); if (pattern.is_double_reference ()) { Analysis::NodeMapping mapping2 (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::ReferencePattern (mapping2, std::unique_ptr (translated), Mutability::Imm, pattern.get_locus ()); } } void ASTLoweringPattern::visit (AST::SlicePattern &pattern) { std::vector> items; for (auto &p : pattern.get_items ()) { HIR::Pattern *item = ASTLoweringPattern::translate (*p); items.push_back (std::unique_ptr (item)); } auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::SlicePattern (mapping, std::move (items), pattern.get_locus ()); } void ASTLoweringPattern::visit (AST::AltPattern &pattern) { auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); std::vector> alts; for (auto &alt : pattern.get_alts ()) { alts.push_back ( std::unique_ptr (ASTLoweringPattern::translate (*alt))); } translated = new HIR::AltPattern (mapping, std::move (alts), pattern.get_locus ()); if (is_let_top_level) { rich_location richloc (line_table, pattern.get_locus ()); richloc.add_fixit_replace ("use an outer grouped pattern"); rust_error_at ( richloc, "top level or-patterns are not allowed for % bindings"); } } } // namespace HIR } // namespace Rust