Line data Source code
1 : // Copyright (C) 2025-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : #ifndef RUST_DERIVE_ORD_H
20 : #define RUST_DERIVE_ORD_H
21 :
22 : #include "rust-ast.h"
23 : #include "rust-derive-cmp-common.h"
24 : #include "rust-derive.h"
25 :
26 : namespace Rust {
27 : namespace AST {
28 :
29 : /**
30 : * DeriveOrd is a bit special as the expansion of both `PartialOrd` and `Ord`
31 : * is extremely similar. The only difference is that `PartialOrd` concerns
32 : * partial-ordering, and thus its main method returns an `Option<Ordering>`,
33 : * while `Ord` concerns total-ordering, and its main method returns an
34 : * `Ordering`. Otherwise, the expansion logic is the same, so we factor both
35 : * derives into one.
36 : */
37 75 : class DeriveOrd : public DeriveVisitor
38 : {
39 : public:
40 : enum class Ordering
41 : {
42 : Total,
43 : Partial
44 : };
45 :
46 266 : std::string fn (Ordering ordering)
47 : {
48 266 : if (ordering == Ordering::Total)
49 112 : return "cmp";
50 : else
51 154 : return "partial_cmp";
52 : }
53 :
54 191 : std::string trait (Ordering ordering)
55 : {
56 191 : if (ordering == Ordering::Total)
57 75 : return "Ord";
58 : else
59 116 : return "PartialOrd";
60 : }
61 :
62 : DeriveOrd (Ordering ordering, location_t loc);
63 :
64 : std::unique_ptr<Item> go (Item &item);
65 :
66 : private:
67 : std::unique_ptr<Item> expanded;
68 :
69 : Ordering ordering;
70 :
71 : /* Identifier patterns for the non-equal match arms */
72 : constexpr static const char *not_equal = "#non_eq";
73 : constexpr static const char *self_discr = "#self_discr";
74 : constexpr static const char *other_discr = "#other_discr";
75 :
76 : /**
77 : * Create the recursive matching structure used when implementing the
78 : * comparison function on multiple sub items (fields, tuple indexes...)
79 : */
80 : std::unique_ptr<Expr> recursive_match (std::vector<SelfOther> &&members);
81 :
82 : /**
83 : * Create a pattern for the `Ordering::Equal` case. In the case of partial
84 : * ordering, `Option::Some(Ordering::Equal)`.
85 : */
86 : std::unique_ptr<Pattern> make_equal ();
87 :
88 : /**
89 : * Make the match arms for one inner match in a comparison function block.
90 : * This returns the "equal" match arm and the "rest" match arm, so something
91 : * like `Ordering::Equal` and `non_eq` in the following match expression:
92 : *
93 : * match cmp(...) {
94 : * Ordering::Equal => match cmp(...) { ... }
95 : * non_eq => non_eq,
96 : * }
97 : */
98 : std::pair<MatchArm, MatchArm> make_cmp_arms ();
99 :
100 : /**
101 : * Generate a call to the proper trait function, based on the ordering, in
102 : * order to compare two given expressions
103 : */
104 : std::unique_ptr<Expr> cmp_call (std::unique_ptr<Expr> &&self_expr,
105 : std::unique_ptr<Expr> &&other_expr);
106 :
107 : std::unique_ptr<Item>
108 : cmp_impl (std::unique_ptr<BlockExpr> &&fn_block, Identifier type_name,
109 : const std::vector<std::unique_ptr<GenericParam>> &type_generics);
110 : std::unique_ptr<AssociatedItem> cmp_fn (std::unique_ptr<BlockExpr> &&block,
111 : Identifier type_name);
112 :
113 : virtual void visit_struct (StructStruct &item) override;
114 : virtual void visit_tuple (TupleStruct &item) override;
115 : virtual void visit_enum (Enum &item) override;
116 : virtual void visit_union (Union &item) override;
117 : };
118 :
119 : } // namespace AST
120 : } // namespace Rust
121 :
122 : #endif // ! RUST_DERIVE_ORD_H
|