// Copyright (C) 2025 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-derive-cmp-common.h" #include "rust-ast-builder.h" #include "rust-item.h" namespace Rust { namespace AST { SelfOther SelfOther::index (Builder builder, int idx) { return SelfOther{ builder.tuple_idx ("self", idx), builder.tuple_idx ("other", idx), }; } std::vector SelfOther::indexes (Builder builder, const std::vector &fields) { std::vector vec; for (size_t i = 0; i < fields.size (); i++) vec.emplace_back (SelfOther::index (builder, i)); return vec; } SelfOther SelfOther::field (Builder builder, const std::string &field_name) { return SelfOther{ builder.field_access (builder.identifier ("self"), field_name), builder.field_access (builder.identifier ("other"), field_name), }; } std::vector SelfOther::fields (Builder builder, const std::vector &fields) { std::vector vec; for (const auto &field : fields) vec.emplace_back ( SelfOther::field (builder, field.get_field_name ().as_string ())); return vec; } MatchCase EnumMatchBuilder::tuple (EnumItem &variant_raw) { auto &variant = static_cast (variant_raw); auto self_patterns = std::vector> (); auto other_patterns = std::vector> (); auto self_other_exprs = std::vector (); for (size_t i = 0; i < variant.get_tuple_fields ().size (); i++) { // The patterns we're creating for each field are `self_` and // `other_` where `i` is the index of the field. It doesn't actually // matter what we use, as long as it's ordered, unique, and that we can // reuse it in the match case's return expression to check that they are // equal. auto self_pattern_str = "__self_" + std::to_string (i); auto other_pattern_str = "__other_" + std::to_string (i); self_patterns.emplace_back ( builder.identifier_pattern (self_pattern_str)); other_patterns.emplace_back ( builder.identifier_pattern (other_pattern_str)); self_other_exprs.emplace_back (SelfOther{ builder.identifier (self_pattern_str), builder.identifier (other_pattern_str), }); } // TODO: Replace with `reconstruct()` instead of building these twice auto self_variant_path = builder.variant_path (enum_path, variant_path); auto other_variant_path = builder.variant_path (enum_path, variant_path); auto self_pattern_items = std::unique_ptr ( new TupleStructItemsNoRange (std::move (self_patterns))); auto other_pattern_items = std::unique_ptr ( new TupleStructItemsNoRange (std::move (other_patterns))); auto self_pattern = std::unique_ptr ( new ReferencePattern (std::unique_ptr (new TupleStructPattern ( self_variant_path, std::move (self_pattern_items))), false, false, builder.loc)); auto other_pattern = std::unique_ptr (new ReferencePattern ( std::unique_ptr (new TupleStructPattern ( other_variant_path, std::move (other_pattern_items))), false, false, builder.loc)); auto tuple_items = std::make_unique ( vec (std::move (self_pattern), std::move (other_pattern))); auto pattern = std::make_unique (std::move (tuple_items), builder.loc); auto expr = fn (std::move (self_other_exprs)); return builder.match_case (std::move (pattern), std::move (expr)); } MatchCase EnumMatchBuilder::strukt (EnumItem &variant_raw) { auto &variant = static_cast (variant_raw); auto self_fields = std::vector> (); auto other_fields = std::vector> (); auto self_other_exprs = std::vector (); for (auto &field : variant.get_struct_fields ()) { // The patterns we're creating for each field are `self_` and // `other_` where `field` is the name of the field. It doesn't // actually matter what we use, as long as it's ordered, unique, and that // we can reuse it in the match case's return expression to check that // they are equal. auto field_name = field.get_field_name ().as_string (); auto self_pattern_str = "__self_" + field_name; auto other_pattern_str = "__other_" + field_name; self_fields.emplace_back (builder.struct_pattern_ident_pattern ( field_name, builder.identifier_pattern (self_pattern_str))); other_fields.emplace_back (builder.struct_pattern_ident_pattern ( field_name, builder.identifier_pattern (other_pattern_str))); self_other_exprs.emplace_back (SelfOther{ builder.identifier (self_pattern_str), builder.identifier (other_pattern_str), }); } // TODO: Replace with `reconstruct()` instead of building these twice auto self_variant_path = builder.variant_path (enum_path, variant_path); auto other_variant_path = builder.variant_path (enum_path, variant_path); auto self_elts = StructPatternElements (std::move (self_fields)); auto other_elts = StructPatternElements (std::move (other_fields)); auto self_pattern = std::unique_ptr (new ReferencePattern ( std::unique_ptr (new StructPattern (self_variant_path, builder.loc, std::move (self_elts))), false, false, builder.loc)); auto other_pattern = std::unique_ptr ( new ReferencePattern (std::unique_ptr ( new StructPattern (other_variant_path, builder.loc, std::move (other_elts))), false, false, builder.loc)); auto tuple_items = std::make_unique ( vec (std::move (self_pattern), std::move (other_pattern))); auto pattern = std::make_unique (std::move (tuple_items), builder.loc); auto expr = fn (std::move (self_other_exprs)); return builder.match_case (std::move (pattern), std::move (expr)); } } // namespace AST } // namespace Rust