diff options
Diffstat (limited to 'gcc/rust/expand/rust-derive-cmp-common.cc')
-rw-r--r-- | gcc/rust/expand/rust-derive-cmp-common.cc | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc new file mode 100644 index 0000000..22ca16f --- /dev/null +++ b/gcc/rust/expand/rust-derive-cmp-common.cc @@ -0,0 +1,191 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#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> +SelfOther::indexes (Builder builder, const std::vector<TupleField> &fields) +{ + std::vector<SelfOther> 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> +SelfOther::fields (Builder builder, const std::vector<StructField> &fields) +{ + std::vector<SelfOther> 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<EnumItemTuple &> (variant_raw); + + auto self_patterns = std::vector<std::unique_ptr<Pattern>> (); + auto other_patterns = std::vector<std::unique_ptr<Pattern>> (); + + auto self_other_exprs = std::vector<SelfOther> (); + + for (size_t i = 0; i < variant.get_tuple_fields ().size (); i++) + { + // The patterns we're creating for each field are `self_<i>` and + // `other_<i>` 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<TupleStructItems> ( + new TupleStructItemsNoRange (std::move (self_patterns))); + auto other_pattern_items = std::unique_ptr<TupleStructItems> ( + new TupleStructItemsNoRange (std::move (other_patterns))); + + auto self_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern ( + self_variant_path, std::move (self_pattern_items))), + false, false, builder.loc)); + auto other_pattern = std::unique_ptr<Pattern> (new ReferencePattern ( + std::unique_ptr<Pattern> (new TupleStructPattern ( + other_variant_path, std::move (other_pattern_items))), + false, false, builder.loc)); + + auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern + = std::make_unique<TuplePattern> (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<EnumItemStruct &> (variant_raw); + + auto self_fields = std::vector<std::unique_ptr<StructPatternField>> (); + auto other_fields = std::vector<std::unique_ptr<StructPatternField>> (); + + auto self_other_exprs = std::vector<SelfOther> (); + + for (auto &field : variant.get_struct_fields ()) + { + // The patterns we're creating for each field are `self_<field>` and + // `other_<field>` 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<Pattern> (new ReferencePattern ( + std::unique_ptr<Pattern> (new StructPattern (self_variant_path, builder.loc, + std::move (self_elts))), + false, false, builder.loc)); + auto other_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> ( + new StructPattern (other_variant_path, builder.loc, + std::move (other_elts))), + false, false, builder.loc)); + + auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern + = std::make_unique<TuplePattern> (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 |