// 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