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
4#include <welder/diag.hpp>
5
16
17namespace welder::inline v0 {
18
26consteval bool welded_for(std::meta::info type, lang L) {
27 auto anns{std::meta::annotations_of_with_type(type, ^^detail::weld_spec)};
28 return !anns.empty() &&
29 (std::meta::extract<detail::weld_spec>(anns[0]).mask & lang_bit(L)) != 0;
30}
31
43consteval bool names_template_specialization(std::meta::info mem) {
44 return std::meta::is_type_alias(mem) &&
45 std::meta::is_class_type(std::meta::dealias(mem)) &&
46 std::meta::has_template_arguments(std::meta::dealias(mem));
47}
48
60consteval bool alias_welded_for(std::meta::info mem, lang L) {
61 auto own{std::meta::annotations_of_with_type(mem, ^^detail::weld_spec)};
62 if (!own.empty())
63 return (std::meta::extract<detail::weld_spec>(own[0]).mask & lang_bit(L)) !=
64 0;
65 return welded_for(std::meta::dealias(mem), L);
66}
67
78consteval bool alias_marks_admissible(std::meta::info mem) {
79 for (auto a : std::meta::annotations_of(mem)) {
80 auto t{std::meta::type_of(a)};
85 return false;
86 if (std::meta::has_template_arguments(t)) {
87 auto tmpl{std::meta::template_of(t)};
88 if (tmpl == ^^detail::doc_spec || tmpl == ^^detail::return_doc_spec ||
89 tmpl == ^^detail::tparam_spec)
90 return false;
91 }
92 }
93 return true;
94}
95
109consteval bool member_alias_marks_admissible(std::meta::info mem) {
110 for (auto a : std::meta::annotations_of(mem)) {
111 auto t{std::meta::type_of(a)};
112 if (t == ^^detail::weld_spec || t == ^^detail::policy_spec ||
116 return false;
117 if (std::meta::has_template_arguments(t)) {
118 auto tmpl{std::meta::template_of(t)};
119 if (tmpl == ^^detail::doc_spec || tmpl == ^^detail::return_doc_spec ||
120 tmpl == ^^detail::tparam_spec)
121 return false;
122 }
123 }
124 return true;
125}
126
132consteval policy_kind policy_of(std::meta::info type) {
133 auto anns{std::meta::annotations_of_with_type(type, ^^detail::policy_spec)};
134 return anns.empty() ? policy_kind::automatic
135 : std::meta::extract<detail::policy_spec>(anns[0]).kind;
136}
137
155consteval bool protected_welded(std::meta::info type, lang L) {
156 for (auto a : std::meta::annotations_of_with_type(
158 auto s{std::meta::extract<detail::weld_protected_spec>(a)};
159 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
160 return true;
161 }
162 return false;
163}
164
172consteval bool excluded_for(std::meta::info member, lang L) {
173 for (auto a : std::meta::annotations_of_with_type(member, ^^detail::exclude_spec)) {
174 auto s{std::meta::extract<detail::exclude_spec>(a)};
175 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
176 return true;
177 }
178 return false;
179}
180
188consteval bool included_for(std::meta::info member, lang L) {
189 for (auto a : std::meta::annotations_of_with_type(member, ^^detail::include_spec)) {
190 auto s{std::meta::extract<detail::include_spec>(a)};
191 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
192 return true;
193 }
194 return false;
195}
196
208consteval bool trusted_for(std::meta::info member, lang L) {
209 for (auto a : std::meta::annotations_of_with_type(member, ^^detail::trust_bindable_spec)) {
210 auto s{std::meta::extract<detail::trust_bindable_spec>(a)};
211 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
212 return true;
213 }
214 return false;
215}
216
229consteval rv_kind return_policy_of(std::meta::info fn, lang L) {
230 for (auto a : std::meta::annotations_of_with_type(fn, ^^detail::return_policy_spec)) {
231 auto s{std::meta::extract<detail::return_policy_spec>(a)};
232 if (s.mask == 0 || (s.mask & lang_bit(L)) != 0)
233 return s.kind;
234 }
235 return rv_kind::automatic;
236}
237
252template <std::meta::info Fn, lang L>
253consteval void validate_return_policy() {
254 constexpr rv_kind k{return_policy_of(Fn, L)};
255 if constexpr (k == rv_kind::reference || k == rv_kind::reference_internal) {
256 constexpr std::meta::info rt{std::meta::return_type_of(Fn)};
257 if constexpr (!(std::meta::is_pointer_type(rt) ||
258 std::meta::is_lvalue_reference_type(rt) ||
259 std::meta::is_rvalue_reference_type(rt)))
261 }
262}
263
276consteval bool member_bound(std::meta::info member, lang L, policy_kind pol) {
277 if (excluded_for(member, L))
278 return false;
279 auto onlys{std::meta::annotations_of_with_type(member, ^^detail::only_spec)};
280 if (!onlys.empty()) {
281 unsigned mask{0};
282 for (auto a : onlys) {
283 auto s{std::meta::extract<detail::only_spec>(a)};
284 if (s.mask == 0)
285 throw diag::bare_mark_only{};
286 mask |= s.mask;
287 }
288 return (mask & lang_bit(L)) != 0;
289 }
290 if (pol == policy_kind::automatic)
291 return true;
292 return included_for(member, L);
293}
294
307consteval std::vector<std::meta::info> public_bases(std::meta::info type) {
308 std::vector<std::meta::info> out;
309 constexpr auto ctx{std::meta::access_context::unchecked()};
310 for (auto b : std::meta::bases_of(type, ctx))
311 if (std::meta::is_public(b))
312 out.push_back(std::meta::type_of(b));
313 return out;
314}
315
316} // 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:26
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:109
consteval bool trusted_for(std::meta::info member, lang L)
Does member carry a trust_bindable mark covering language L?
Definition reflect.hpp:208
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:60
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 excluded_for(std::meta::info member, lang L)
Does member carry an exclude mark covering language L?
Definition reflect.hpp:172
consteval bool protected_welded(std::meta::info type, lang L)
Does type admit its protected members for language L — i.e.
Definition reflect.hpp:155
consteval void validate_return_policy()
Reject a return_policy on Fn (for language L) that contradicts Fn's return type.
Definition reflect.hpp:253
consteval unsigned lang_bit(lang l)
The single-language bit for l within a language mask.
consteval policy_kind policy_of(std::meta::info type)
The reflection policy declared on type, defaulting to automatic.
Definition reflect.hpp:132
consteval bool alias_marks_admissible(std::meta::info mem)
May the annotations on alias-declaration mem appear there?
Definition reflect.hpp:78
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:276
consteval bool included_for(std::meta::info member, lang L)
Does member carry an include mark covering language L?
Definition reflect.hpp:188
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:43
consteval std::vector< std::meta::info > public_bases(std::meta::info type)
The types of the public base classes of type.
Definition reflect.hpp:307
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:229
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 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 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