welder 0.1.0
Bindings for annotated C++ types, from C++26 reflection
Loading...
Searching...
No Matches
operators.hpp
Go to the documentation of this file.
1#pragma once
2#include <meta>
3
4#include <welder/bind_traits.hpp> // is_unary_operator
5
21
22namespace welder::inline v0::rods::python {
23
41consteval const char* operator_dunder(std::meta::info f) {
42 using std::meta::operators;
43 const bool unary{::welder::detail::is_unary_operator(f)};
44 switch (std::meta::operator_of(f)) {
45 case operators::op_plus: return unary ? "__pos__" : "__add__";
46 case operators::op_minus: return unary ? "__neg__" : "__sub__";
47 case operators::op_star: return unary ? nullptr : "__mul__"; // unary * = deref
48 case operators::op_slash: return "__truediv__";
49 case operators::op_percent: return "__mod__";
50 case operators::op_tilde: return "__invert__";
51 case operators::op_caret: return "__xor__";
52 case operators::op_ampersand: return unary ? nullptr : "__and__"; // unary & = address-of
53 case operators::op_pipe: return "__or__";
54 case operators::op_less_less: return "__lshift__";
55 case operators::op_greater_greater: return "__rshift__";
56 case operators::op_equals_equals: return "__eq__";
57 case operators::op_exclamation_equals: return "__ne__";
58 case operators::op_less: return "__lt__";
59 case operators::op_greater: return "__gt__";
60 case operators::op_less_equals: return "__le__";
61 case operators::op_greater_equals: return "__ge__";
62 case operators::op_parentheses: return "__call__";
63 case operators::op_square_brackets: return "__getitem__";
64 default: return nullptr;
65 }
66}
67
79consteval const char* reflected_dunder(std::meta::info f) {
80 using std::meta::operators;
82 return nullptr; // a unary operator has no second operand to reflect
83 switch (std::meta::operator_of(f)) {
84 case operators::op_plus: return "__radd__";
85 case operators::op_minus: return "__rsub__";
86 case operators::op_star: return "__rmul__";
87 case operators::op_slash: return "__rtruediv__";
88 case operators::op_percent: return "__rmod__";
89 case operators::op_caret: return "__rxor__";
90 case operators::op_ampersand: return "__rand__";
91 case operators::op_pipe: return "__ror__";
92 case operators::op_less_less: return "__rlshift__";
93 case operators::op_greater_greater: return "__rrshift__";
94 // Comparisons mirror rather than prefix with r.
95 case operators::op_equals_equals: return "__eq__";
96 case operators::op_exclamation_equals: return "__ne__";
97 case operators::op_less: return "__gt__";
98 case operators::op_greater: return "__lt__";
99 case operators::op_less_equals: return "__ge__";
100 case operators::op_greater_equals: return "__le__";
101 default: return nullptr;
102 }
103}
104
116consteval bool dunder_uses_not_implemented(std::meta::info f) {
117 using std::meta::operators;
119 return false;
120 switch (std::meta::operator_of(f)) {
121 case operators::op_parentheses:
122 case operators::op_square_brackets: return false;
123 default: return operator_dunder(f) != nullptr;
124 }
125}
126
132 switch (s) {
133 case ::welder::detail::cmp_slot::lt: return "__lt__";
134 case ::welder::detail::cmp_slot::le: return "__le__";
135 case ::welder::detail::cmp_slot::gt: return "__gt__";
136 case ::welder::detail::cmp_slot::ge: return "__ge__";
137 }
138 return nullptr;
139}
140
152template <class T, auto Fns, auto Covered, class Def>
156 template for (constexpr auto fn : std::define_static_array(Fns)) {
157 using P = std::remove_cvref_t<
158 typename [: ::welder::detail::comparison_operand(fn, ^^T) :]>;
159 if constexpr (!Covered[0])
160 def(cmp_slot_dunder(cmp_slot::lt),
161 &synthesized_comparison<T, P, cmp_slot::lt>::call);
162 if constexpr (!Covered[1])
163 def(cmp_slot_dunder(cmp_slot::le),
164 &synthesized_comparison<T, P, cmp_slot::le>::call);
165 if constexpr (!Covered[2])
166 def(cmp_slot_dunder(cmp_slot::gt),
167 &synthesized_comparison<T, P, cmp_slot::gt>::call);
168 if constexpr (!Covered[3])
169 def(cmp_slot_dunder(cmp_slot::ge),
170 &synthesized_comparison<T, P, cmp_slot::ge>::call);
171 }
172}
173
174} // namespace welder::rods::python
Backend-agnostic selection layer: the reflection predicates and selectors that decide what participat...
consteval bool is_unary_operator(std::meta::info f)
Whether an operator function is unary vs binary.
consteval std::meta::info comparison_operand(std::meta::info f, std::meta::info type)
The operand a comparison synthesized from spaceship overload f takes: the parameter type that is not ...
cmp_slot
The rewritten-expression comparison a rod binds for a type whose C++ comparisons come from operator<=...
consteval const char * operator_dunder(std::meta::info f)
The Python special-method ("dunder") name for an operator (member or anchored free),...
Definition operators.hpp:41
consteval const char * reflected_dunder(std::meta::info f)
The reflected ("swapped-operand") dunder for a free operator whose anchor type is the right operand —...
Definition operators.hpp:79
consteval bool dunder_uses_not_implemented(std::meta::info f)
Whether f's slot participates in Python's NotImplemented protocol — every binary arithmetic / bitwise...
void synthesize_comparisons(Def def)
The comparison-synthesis walk shared by both Python backends: for each operator<=> overload in Fns,...
consteval const char * cmp_slot_dunder(::welder::detail::cmp_slot s)
The dunder each synthesized comparison slot binds under (see the rods' add_comparisons and welder::de...