// 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
// .
#ifndef RUST_DERIVE_ORD_H
#define RUST_DERIVE_ORD_H
#include "rust-ast.h"
#include "rust-derive-cmp-common.h"
#include "rust-derive.h"
namespace Rust {
namespace AST {
/**
* DeriveOrd is a bit special as the expansion of both `PartialOrd` and `Ord`
* is extremely similar. The only difference is that `PartialOrd` concerns
* partial-ordering, and thus its main method returns an `Option`,
* while `Ord` concerns total-ordering, and its main method returns an
* `Ordering`. Otherwise, the expansion logic is the same, so we factor both
* derives into one.
*/
class DeriveOrd : public DeriveVisitor
{
public:
enum class Ordering
{
Total,
Partial
};
std::string fn (Ordering ordering)
{
if (ordering == Ordering::Total)
return "cmp";
else
return "partial_cmp";
}
std::string trait (Ordering ordering)
{
if (ordering == Ordering::Total)
return "Ord";
else
return "PartialOrd";
}
DeriveOrd (Ordering ordering, location_t loc);
std::unique_ptr- go (Item &item);
private:
std::unique_ptr
- expanded;
Ordering ordering;
/* Identifier patterns for the non-equal match arms */
constexpr static const char *not_equal = "#non_eq";
constexpr static const char *self_discr = "#self_discr";
constexpr static const char *other_discr = "#other_discr";
/**
* Create the recursive matching structure used when implementing the
* comparison function on multiple sub items (fields, tuple indexes...)
*/
std::unique_ptr recursive_match (std::vector &&members);
/**
* Create a pattern for the `Ordering::Equal` case. In the case of partial
* ordering, `Option::Some(Ordering::Equal)`.
*/
std::unique_ptr make_equal ();
/**
* Make the match arms for one inner match in a comparison function block.
* This returns the "equal" match arm and the "rest" match arm, so something
* like `Ordering::Equal` and `non_eq` in the following match expression:
*
* match cmp(...) {
* Ordering::Equal => match cmp(...) { ... }
* non_eq => non_eq,
* }
*/
std::pair make_cmp_arms ();
/**
* Generate a call to the proper trait function, based on the ordering, in
* order to compare two given expressions
*/
std::unique_ptr cmp_call (std::unique_ptr &&self_expr,
std::unique_ptr &&other_expr);
std::unique_ptr
-
cmp_impl (std::unique_ptr &&fn_block, Identifier type_name,
const std::vector> &type_generics);
std::unique_ptr cmp_fn (std::unique_ptr &&block,
Identifier type_name);
virtual void visit_struct (StructStruct &item) override;
virtual void visit_tuple (TupleStruct &item) override;
virtual void visit_enum (Enum &item) override;
virtual void visit_union (Union &item) override;
};
} // namespace AST
} // namespace Rust
#endif // ! RUST_DERIVE_ORD_H