welder 0.1.0
Bindings for annotated C++ types, from C++26 reflection
Loading...
Searching...
No Matches
rod.hpp
Go to the documentation of this file.
1#pragma once
25
26#include <array>
27#include <cstddef>
28#include <meta>
29#include <ostream>
30#include <string>
31#include <type_traits>
32#include <utility>
33
34#include <welder/welder.hpp>
36#include <welder/rods/python/opaque_containers/marks.hpp> // marked_by_value
37
38namespace welder::inline v0::rods::opaque_containers {
39
43struct rod {
44 static constexpr lang language{lang::py};
45
52 std::string prefix{};
53 };
55
58 struct class_handle {
60 };
61
63 struct enum_handle {};
64
65 template <class> using class_handle_type = class_handle;
66 template <class> using enum_handle_type = enum_handle;
67
68 struct session {};
69
74 template <class T>
75 static constexpr bool has_native_caster = true;
76
79 static consteval const char* special_method_name(std::meta::info) {
80 return nullptr;
81 }
82
83 // --- class binding: pass the document down to the per-member hooks -------
84
85 template <class T, auto Bases, std::size_t... I>
86 static class_handle make_class(module_type& m, const char* /*name*/,
87 const char* /*doc*/, std::index_sequence<I...>) {
88 return {m.doc};
89 }
90
92 template <class T, std::meta::info Decl, auto Bases, std::size_t... I>
93 static class_handle make_class(module_type& m, const char* /*name*/,
94 const char* /*doc*/, std::index_sequence<I...>) {
95 return {m.doc};
96 }
97 template <class T, auto Bases, std::size_t... I>
99 const char* /*name*/, const char* /*doc*/,
100 std::index_sequence<I...>) {
101 return {m.doc};
102 }
103
107 template <class T, auto Ctors, bool HasDefault, bool Aggregate, bool Copyable>
108 static void add_constructors(class_handle& cls) {
109 template for (constexpr auto ctor : std::define_static_array(Ctors))
110 cls.doc->template collect_callable<ctor, ::welder::naming::none>(false);
111 }
112
116 template <std::meta::info Mem, class Style = ::welder::naming::none>
117 static void add_field(class_handle& cls) {
118 cls.doc->template collect<std::meta::type_of(Mem), Style,
119 std::meta::parent_of(Mem), Mem>(
121 }
122
126 template <class T, std::meta::info Getter, std::meta::info Setter>
127 static void add_property(class_handle& cls, const char*) {
128 cls.doc->template collect_callable<Getter, ::welder::naming::none>(false);
129 if constexpr (Setter != std::meta::info{})
130 cls.doc->template collect_callable<Setter, ::welder::naming::none>(false);
131 }
132
133 template <auto Fns, class Style = ::welder::naming::none>
134 static void add_method(class_handle& cls) {
135 template for (constexpr auto fn : std::define_static_array(Fns))
136 cls.doc->template collect_callable<fn, Style>(true);
137 }
138 template <auto Fns, class Style = ::welder::naming::none>
139 static void add_static_method(class_handle& cls) {
140 template for (constexpr auto fn : std::define_static_array(Fns))
141 cls.doc->template collect_callable<fn, Style>(true);
142 }
143 template <class T, auto Fns>
144 static void add_operator(class_handle& cls) {
145 template for (constexpr auto fn : std::define_static_array(Fns))
146 cls.doc->template collect_callable<fn, ::welder::naming::none>(false);
147 }
148 template <class T, auto Fns, auto Covered>
149 static void add_comparisons(class_handle&) {} // spaceship operands are the anchor type
150 template <class T, std::meta::info Fn>
151 static void add_stringifier(class_handle&) {} // ostream inserter: no container surface
152
153 // --- enum binding: nothing to collect -----------------------------------
154
155 template <class E>
156 static enum_handle make_enum(module_type&, const char*,
157 const ::welder::detail::enum_doc&) {
158 return {};
159 }
160 template <class E>
162 const ::welder::detail::enum_doc&) {
163 return {};
164 }
165 template <std::meta::info, class = ::welder::naming::none>
167 template <class E> static void finish_enum(enum_handle&) {}
168
169 // --- namespace / module binding -----------------------------------------
170
171 static session open_module(module_type&) { return {}; }
172 static void set_module_doc(module_type&, const char*) {}
173
176 template <auto Fns, class Style = ::welder::naming::none>
177 static void add_function(module_type& m, const char* = nullptr) {
178 template for (constexpr auto fn : std::define_static_array(Fns))
179 m.doc->template collect_callable<fn, Style>(true);
180 }
181
184 template <std::meta::info Var, class Style = ::welder::naming::none>
185 static void add_variable(module_type& m, session&, const char* = nullptr) {
186 m.doc->template collect<std::meta::type_of(Var), Style,
187 std::meta::parent_of(Var), Var>(false, true);
188 }
189
191 static module_type add_submodule(module_type& m, const char* name) {
192 return module_type{m.doc, m.prefix.empty() ? std::string{name}
193 : m.prefix + "." + name};
194 }
196
197 // --- whole-header generation (this backend's extra entry point) ----------
198
206 template <std::meta::info Ns, class Style = ::welder::naming::none>
207 static void generate(std::ostream& os) {
208 static_assert(std::meta::is_namespace(Ns),
209 "welder: opaque_containers::generate<Ns>: Ns must reflect a "
210 "namespace");
211 document doc{};
212 module_type m{&doc, {}};
213 ::welder::welder<rod, Style>::template weld_namespace<Ns>(m);
214 // namespace_name is consteval (heap std::string), so materialize its result
215 // to a static C-string before it crosses into this runtime call.
216 os << doc.render(std::define_static_string(namespace_name(Ns)));
217 }
218};
219
220static_assert(::welder::rod<rod>,
221 "welder::rods::opaque_containers::rod must satisfy welder::rod");
222
223} // namespace welder::inline v0::rods::opaque_containers
The contract a rod (a welder backend, welder::rods::…::rod) must satisfy to plug into the generic dri...
Definition concepts.hpp:263
The one opt-out mark of the opaque-container generator (welder::rods::opaque_containers::rod): welder...
consteval std::string namespace_name(std::meta::info ns)
The fully-qualified spelling of namespace ns for a namespace X { … } header block (no leading :: — ge...
Definition document.hpp:210
consteval bool marked_by_value(std::meta::info entity)
Does entity carry a by_value mark?
Definition marks.hpp:37
consteval detail::doc_spec< N > doc(const char(&s)[N])
Attach a docstring to a namespace, class, function, or function parameter.
lang
The target languages welder ships rods for — but not the whole value space.
Definition lang.hpp:42
@ py
Python (via the pybind11 and nanobind backends).
Definition lang.hpp:43
The text-emitting core of welder's opaque-container generator rod: the collector that gathers the ref...
The accumulator threaded through the rod's emission hooks: the deduped set of reference containers th...
Definition document.hpp:309
The per-class handle: it carries the document so the per-member hooks (add_field / add_method / …) ca...
Definition rod.hpp:58
The enum handle — enums use no containers, so it carries nothing.
Definition rod.hpp:63
A copyable handle onto the growing document threaded through every emission primitive (the rod's modu...
Definition rod.hpp:50
static void set_module_doc(module_type &, const char *)
Definition rod.hpp:172
static enum_handle make_enum(module_type &, const char *, const ::welder::detail::enum_doc &)
Definition rod.hpp:156
static session open_module(module_type &)
Definition rod.hpp:171
static class_handle make_class(module_type &m, const char *, const char *, std::index_sequence< I... >)
The declaring-entity-aware form the carriage prefers (see bind_type); the generator keys off member t...
Definition rod.hpp:93
static void add_stringifier(class_handle &)
Definition rod.hpp:151
static void add_field(class_handle &cls)
Collect the container(s) in data member Mem's type — excluded when Mem carries [[=welder::rods::pytho...
Definition rod.hpp:117
static void add_static_method(class_handle &cls)
Definition rod.hpp:139
static void generate(std::ostream &os)
Emit the opaque-container header for the welded types in namespace Ns to os.
Definition rod.hpp:207
static void finish_enum(enum_handle &)
Definition rod.hpp:167
static module_type add_submodule(module_type &m, const char *name)
Recurse into a nested namespace, carrying the document through.
Definition rod.hpp:191
static consteval const char * special_method_name(std::meta::info)
No operators expose special names here (containers are collected from operator signatures directly).
Definition rod.hpp:79
static void add_enumerator(enum_handle &)
Definition rod.hpp:166
static void add_method(class_handle &cls)
Definition rod.hpp:134
static constexpr bool has_native_caster
Permissive: the generator only reads the welded surface to find containers, so it does not need a bac...
Definition rod.hpp:75
static class_handle make_class(module_type &m, const char *, const char *, std::index_sequence< I... >)
Definition rod.hpp:86
static constexpr lang language
Opaque containers are Python-only.
Definition rod.hpp:44
static void add_property(class_handle &cls, const char *)
Collect from the property accessor signatures (getter return, setter param).
Definition rod.hpp:127
static class_handle make_nested_class(module_type &m, class_handle &, const char *, const char *, std::index_sequence< I... >)
Definition rod.hpp:98
static void add_operator(class_handle &cls)
Definition rod.hpp:144
static void close_module(module_type &, session &)
Definition rod.hpp:195
static enum_handle make_nested_enum(module_type &, class_handle &, const char *, const ::welder::detail::enum_doc &)
Definition rod.hpp:161
static void add_variable(module_type &m, session &, const char *=nullptr)
Collect the container(s) in a namespace variable's type (a Style-aware site).
Definition rod.hpp:185
static void add_constructors(class_handle &cls)
Collect from each participating constructor's parameter types.
Definition rod.hpp:108
static void add_comparisons(class_handle &)
Definition rod.hpp:149
static void add_function(module_type &m, const char *=nullptr)
Collect from a free function's overload group signatures (a Style-aware site).
Definition rod.hpp:177
welder's binding entry point, parameterized on a rod.
Definition welder.hpp:85
welder's binding entry point: the welder::welder struct.