welder 0.1.0
Bindings for annotated C++ types, from C++26 reflection
Loading...
Searching...
No Matches
reflect.hpp
Go to the documentation of this file.
1#pragma once
2#include <meta>
3#include <string> // accessor_explicit_name
4
5#include <welder/diag.hpp>
6
17
18namespace welder::inline v0 {
19
28consteval bool weld_mask_admits(unsigned mask, lang L) {
29 return mask == 0 || (mask & lang_bit(L)) != 0;
30}
31
40consteval bool welded_for(std::meta::info type, lang L) {
41 auto anns{std::meta::annotations_of_with_type(type, ^^detail::weld_spec)};
42 return !anns.empty() &&
43 weld_mask_admits(std::meta::extract<detail::weld_spec>(anns[0]).mask, L);
44}
45
54consteval bool flags_enum(std::meta::info type) {
55 return !std::meta::annotations_of_with_type(type, ^^detail::flags_spec).empty();
56}
57
69consteval bool names_template_specialization(std::meta::info mem) {
70 return std::meta::is_type_alias(mem) &&
71 std::meta::is_class_type(std::meta::dealias(mem)) &&
72 std::meta::has_template_arguments(std::meta::dealias(mem));
73}
74
86consteval bool alias_welded_for(std::meta::info mem, lang L) {
87 auto own{std::meta::annotations_of_with_type(mem, ^^detail::weld_spec)};
88 if (!own.empty())
89 return weld_mask_admits(
90 std::meta::extract<detail::weld_spec>(own[0]).mask, L);
91 return welded_for(std::meta::dealias(mem), L);
92}
93
104consteval bool alias_marks_admissible(std::meta::info mem) {
105 for (auto a : std::meta::annotations_of(mem)) {
106 auto t{std::meta::type_of(a)};
112 return false;
113 if (std::meta::has_template_arguments(t)) {
114 auto tmpl{std::meta::template_of(t)};
115 if (tmpl == ^^detail::doc_spec || tmpl == ^^detail::return_doc_spec ||
116 tmpl == ^^detail::tparam_spec)
117 return false;
118 }
119 }
120 return true;
121}
122
136consteval bool member_alias_marks_admissible(std::meta::info mem) {
137 for (auto a : std::meta::annotations_of(mem)) {
138 auto t{std::meta::type_of(a)};
139 if (t == ^^detail::weld_spec || t == ^^detail::policy_spec ||
144 return false;
145 if (std::meta::has_template_arguments(t)) {
146 auto tmpl{std::meta::template_of(t)};
147 if (tmpl == ^^detail::doc_spec || tmpl == ^^detail::return_doc_spec ||
148 tmpl == ^^detail::tparam_spec)
149 return false;
150 }
151 }
152 return true;
153}
154
160consteval policy_kind policy_of(std::meta::info type) {
161 auto anns{std::meta::annotations_of_with_type(type, ^^detail::policy_spec)};
162 return anns.empty() ? policy_kind::automatic
163 : std::meta::extract<detail::policy_spec>(anns[0]).kind;
164}
165
183consteval bool protected_welded(std::meta::info type, lang L) {
184 for (auto a : std::meta::annotations_of_with_type(
186 auto s{std::meta::extract<detail::weld_protected_spec>(a)};
187 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
188 return true;
189 }
190 return false;
191}
192
200consteval bool excluded_for(std::meta::info member, lang L) {
201 for (auto a : std::meta::annotations_of_with_type(member, ^^detail::exclude_spec)) {
202 auto s{std::meta::extract<detail::exclude_spec>(a)};
203 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
204 return true;
205 }
206 return false;
207}
208
216consteval bool included_for(std::meta::info member, lang L) {
217 for (auto a : std::meta::annotations_of_with_type(member, ^^detail::include_spec)) {
218 auto s{std::meta::extract<detail::include_spec>(a)};
219 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
220 return true;
221 }
222 return false;
223}
224
236consteval bool trusted_for(std::meta::info member, lang L) {
237 for (auto a : std::meta::annotations_of_with_type(member, ^^detail::trust_bindable_spec)) {
238 auto s{std::meta::extract<detail::trust_bindable_spec>(a)};
239 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
240 return true;
241 }
242 return false;
243}
244
255consteval bool member_no_reassign(std::meta::info member, lang L) {
256 for (auto a : std::meta::annotations_of_with_type(member, ^^detail::no_reassign_spec)) {
257 auto s{std::meta::extract<detail::no_reassign_spec>(a)};
258 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
259 return true;
260 }
261 return false;
262}
263
272consteval bool has_no_reassign_mark(std::meta::info entity) {
273 return !std::meta::annotations_of_with_type(entity, ^^detail::no_reassign_spec)
274 .empty();
275}
276
288consteval bool accessor_marked(std::meta::info member, accessor_role role, lang L) {
289 for (auto a : std::meta::annotations_of_with_type(member, ^^detail::accessor_spec)) {
290 auto s{std::meta::extract<detail::accessor_spec>(a)};
291 if (s.role == role && (s.mask == 0 || (s.mask & lang_bit(L)) != 0))
292 return true;
293 }
294 return false;
295}
296
302consteval bool is_accessor_for(std::meta::info member, lang L) {
303 return accessor_marked(member, accessor_role::getter, L) ||
305}
306
312consteval bool has_accessor_mark(std::meta::info member) {
313 return !std::meta::annotations_of_with_type(member, ^^detail::accessor_spec)
314 .empty();
315}
316
326consteval std::string accessor_explicit_name(std::meta::info member,
327 accessor_role role, lang L) {
328 for (auto a : std::meta::annotations_of_with_type(member, ^^detail::accessor_spec)) {
329 auto s{std::meta::extract<detail::accessor_spec>(a)};
330 if (s.role == role && (s.mask == 0 || (s.mask & lang_bit(L)) != 0) &&
331 s.name[0] != '\0')
332 return std::string{s.name};
333 }
334 return {};
335}
336
349consteval rv_kind return_policy_of(std::meta::info fn, lang L) {
350 for (auto a : std::meta::annotations_of_with_type(fn, ^^detail::return_policy_spec)) {
351 auto s{std::meta::extract<detail::return_policy_spec>(a)};
352 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
353 return s.kind;
354 }
355 return rv_kind::automatic;
356}
357
372template <std::meta::info Fn, lang L>
373consteval void validate_return_policy() {
374 constexpr rv_kind k{return_policy_of(Fn, L)};
375 if constexpr (k == rv_kind::reference || k == rv_kind::reference_internal) {
376 constexpr std::meta::info rt{std::meta::return_type_of(Fn)};
377 if constexpr (!(std::meta::is_pointer_type(rt) ||
378 std::meta::is_lvalue_reference_type(rt) ||
379 std::meta::is_rvalue_reference_type(rt)))
381 }
382}
383
399consteval bool member_bound(std::meta::info member, lang L, policy_kind pol) {
400 if (excluded_for(member, L))
401 return false;
402 auto onlys{std::meta::annotations_of_with_type(member, ^^detail::only_spec)};
403 if (!onlys.empty()) {
404 unsigned mask{0};
405 for (auto a : onlys) {
406 auto s{std::meta::extract<detail::only_spec>(a)};
407 if (s.mask == 0)
408 throw diag::bare_mark_only{};
409 mask |= s.mask;
410 }
411 return (mask & lang_bit(L)) != 0;
412 }
413 if (pol == policy_kind::automatic)
414 return true;
415 return included_for(member, L) || is_accessor_for(member, L);
416}
417
430consteval std::vector<std::meta::info> public_bases(std::meta::info type) {
431 std::vector<std::meta::info> out;
432 constexpr auto ctx{std::meta::access_context::unchecked()};
433 for (auto b : std::meta::bases_of(type, ctx))
434 if (std::meta::is_public(b))
435 out.push_back(std::meta::type_of(b));
436 return out;
437}
438
439} // namespace welder
welder's consteval diagnostics, collected in one place: every hand-rolled compile-time error the libr...
consteval bool welded_for(std::meta::info type, lang L)
Is type welded for language L — i.e.
Definition reflect.hpp:40
consteval bool is_accessor_for(std::meta::info member, lang L)
Does member supply either property half for language L — i.e.
Definition reflect.hpp:302
consteval bool accessor_marked(std::meta::info member, accessor_role role, lang L)
Does member carry a getter/setter mark of role covering L?
Definition reflect.hpp:288
consteval bool member_no_reassign(std::meta::info member, lang L)
Is data member member bound read-only for L by a no_reassign mark?
Definition reflect.hpp:255
policy_kind
How greedily a type's members are reflected for binding.
@ automatic
Reflect every member unless explicitly excluded (default).
consteval bool member_alias_marks_admissible(std::meta::info mem)
May the annotations on member type-alias mem appear there?
Definition reflect.hpp:136
consteval bool trusted_for(std::meta::info member, lang L)
Does member carry a trust_bindable mark covering language L?
Definition reflect.hpp:236
consteval bool alias_welded_for(std::meta::info mem, lang L)
Is the specialization named by alias mem welded for language L — reading the alias's own weld first,...
Definition reflect.hpp:86
lang
The target languages welder ships rods for — but not the whole value space.
Definition lang.hpp:42
rv_kind
How a bound callable's returned object is owned/converted in the target language — welder's backend-n...
@ automatic
The rod default — emit no explicit policy.
@ reference_internal
A non-owning reference tied to the parent's lifetime (implies keep_alive).
@ reference
A non-owning reference; the caller keeps the C++ object alive.
consteval bool flags_enum(std::meta::info type)
Is type a bitmask enum — does it carry a flags annotation?
Definition reflect.hpp:54
consteval bool excluded_for(std::meta::info member, lang L)
Does member carry an exclude mark covering language L?
Definition reflect.hpp:200
consteval bool protected_welded(std::meta::info type, lang L)
Does type admit its protected members for language L — i.e.
Definition reflect.hpp:183
consteval void validate_return_policy()
Reject a return_policy on Fn (for language L) that contradicts Fn's return type.
Definition reflect.hpp:373
consteval unsigned lang_bit(lang l)
The single-language bit for l within a language mask.
accessor_role
Which half of a property a marked accessor function supplies.
@ getter
The function reads the property's value (const, no parameters).
@ setter
The function writes it (exactly one parameter).
consteval policy_kind policy_of(std::meta::info type)
The reflection policy declared on type, defaulting to automatic.
Definition reflect.hpp:160
consteval bool alias_marks_admissible(std::meta::info mem)
May the annotations on alias-declaration mem appear there?
Definition reflect.hpp:104
consteval bool member_bound(std::meta::info member, lang L, policy_kind pol)
The core decision a backend asks for each member: does member bind for language L under policy pol?
Definition reflect.hpp:399
consteval bool included_for(std::meta::info member, lang L)
Does member carry an include mark covering language L?
Definition reflect.hpp:216
consteval bool has_accessor_mark(std::meta::info member)
Does member carry any getter/setter mark at all (any role, any language)?
Definition reflect.hpp:312
consteval bool has_no_reassign_mark(std::meta::info entity)
Does entity carry any no_reassign mark at all (any language)?
Definition reflect.hpp:272
consteval bool names_template_specialization(std::meta::info mem)
Is mem a namespace-scope alias naming a class-template specialization — the one way an instantiation ...
Definition reflect.hpp:69
consteval std::string accessor_explicit_name(std::meta::info member, accessor_role role, lang L)
The explicit property name an accessor mark of role forces for L, or "" when the name derives from th...
Definition reflect.hpp:326
consteval bool weld_mask_admits(unsigned mask, lang L)
Does a weld mask admit language L?
Definition reflect.hpp:28
consteval std::vector< std::meta::info > public_bases(std::meta::info type)
The types of the public base classes of type.
Definition reflect.hpp:430
consteval rv_kind return_policy_of(std::meta::info fn, lang L)
The return-value policy declared on callable fn for language L.
Definition reflect.hpp:349
The stored form of a getter / setter mark: which property half the function supplies,...
The stored form of a doc annotation: a summary docstring.
The stored form of an exclude mark: the languages a member is hidden from.
The stored form of a flags annotation on an enum type.
The stored form of an include mark: the languages a member is opted into.
The stored form of a keep_alive annotation: a lifetime dependency between two of a call's entities,...
The stored form of a no_reassign mark: the languages a data member is bound read-only** for,...
The stored form of an only mark: the complete set of languages a member may bind for — implicitly,...
The stored form of a policy annotation.
The stored form of a returns annotation: a function's return-value doc.
The stored form of a return_policy annotation: a return-value policy, optionally scoped to some langu...
The stored form of a tparam annotation: one template parameter's doc.
The stored form of a trust_bindable member mark.
The stored form of a policy::weld_protected annotation: the languages a type's protected members are ...
The stored form of a weld annotation: the mask of target languages.
Thrown by member_bound (<welder/reflect.hpp>) when a member carries a bare [[=welder::mark::only]] — ...
Definition diag.hpp:53
Thrown by validate_return_policy (<welder/reflect.hpp>) — every rod runs it at its per-overload bind ...
Definition diag.hpp:41