81namespace welder::inline v0::rods::sol2 {
89template <
class T,
class... A>
152 std::is_enum_v<std::remove_cvref_t<T>> ||
153 ::sol::lua_type_of<std::remove_cvref_t<T>>::value == ::sol::type::userdata;
166 std::function<void(
const char*, lua_Integer)>
187 template <
class T, auto Ctors,
bool HasDefault,
bool Aggregate>
189 std::vector<std::meta::info> sigs;
190 auto sig = [](std::vector<std::meta::info> targs) {
191 return std::meta::dealias(std::meta::substitute(^^
ctor_sig, targs));
194 sigs.push_back(sig({^^T}));
195 for (
auto c : Ctors) {
196 std::vector<std::meta::info> targs{^^T};
197 for (
auto p : std::meta::parameters_of(c))
198 targs.push_back(std::meta::type_of(p));
199 sigs.push_back(sig(targs));
204 if constexpr (Aggregate) {
212 if (HasDefault && start == 0)
214 for (std::size_t arity{start}; arity <= fields.size(); ++arity) {
215 std::vector<std::meta::info> targs{^^T};
216 for (std::size_t i{0}; i < arity; ++i)
217 targs.push_back(std::meta::type_of(fields[i]));
218 sigs.push_back(sig(targs));
225 template <
class T, auto Ctors,
bool HasDefault,
bool Aggregate>
227 constexpr std::size_t n{
229 std::array<std::meta::info, n> out{};
232 if constexpr (n != 0) {
234 for (std::size_t i{0}; i < n; ++i)
246 template <
class T,
auto Sigs, std::size_t... I>
248 std::index_sequence<I...>) {
250 ut[::sol::call_constructor] = ::sol::constructors<
typename [:Sigs[I]:]...>();
251 ut[
"new"] = ::sol::constructors<
typename [:Sigs[I]:]...>();
266 template <
class T,
auto Bases, std::size_t... I>
268 std::index_sequence<I...>) {
280 ::sol::automagic_enrollments enroll{};
281 enroll.default_constructor =
false;
282 enroll.to_string_operator =
false;
283 enroll.call_operator =
false;
284 enroll.less_than_operator =
false;
285 enroll.less_than_or_equal_to_operator =
false;
286 enroll.equal_to_operator =
false;
287 ::sol::usertype<T> ut{m.new_usertype<T>(name, enroll)};
288 if constexpr (
sizeof...(I) != 0)
289 ut[::sol::base_classes] =
290 ::sol::bases<
typename [:Bases[I]:]...>();
310 std::meta::info type,
lang L, std::vector<std::meta::info>& out) {
333 constexpr std::size_t n{[] {
334 std::vector<std::meta::info> v;
338 std::array<std::meta::info, n> out{};
340 if constexpr (n != 0) {
341 std::vector<std::meta::info> v;
343 for (std::size_t i{0}; i < n; ++i)
360 template <
auto Grp,
class Target, std::size_t... I>
362 std::index_sequence<I...>) {
369 if constexpr (
sizeof...(I) == 1)
370 t[name] = &[:Grp[0]:];
372 t[name] = ::sol::overload(&[:Grp[I]:]...);
381 template <
auto Grp,
class Target, std::size_t... I>
385 if constexpr (
sizeof...(I) == 1)
386 t[slot] = &[:Grp[0]:];
388 t[slot] = ::sol::overload(&[:Grp[I]:]...);
396 static ::sol::object
_prev_index(::sol::this_state ts, const ::sol::object& prev,
397 const ::sol::table& self, const ::sol::object& key) {
398 if (prev.get_type() == ::sol::type::function)
399 return ::sol::object{prev.as<::sol::function>()(self, key)};
400 if (prev.get_type() == ::sol::type::table)
401 return ::sol::object{prev.as<::sol::table>()[key]};
402 return ::sol::make_object(ts, ::sol::lua_nil);
409 const ::sol::object& key, const ::sol::object& value) {
410 if (prev.get_type() == ::sol::type::function) {
411 prev.as<::sol::function>()(self, key, value);
414 if (prev.get_type() == ::sol::type::table) {
415 prev.as<::sol::table>()[key] = value;
418 self.raw_set(key, value);
432 ::sol::table setters) {
433 lua_State* L{m.lua_state()};
434 ::sol::state_view
lua{L};
440 const bool had_mt{lua_getmetatable(L, -1) != 0};
441 ::sol::table mt{had_mt ? ::sol::stack::pop<::sol::table>(L)
442 :
lua.create_table()};
446 ::sol::object prev_index{mt[
"__index"]};
447 ::sol::object prev_newindex{mt[
"__newindex"]};
449 mt[
"__index"] = [getters, prev_index](::sol::this_state ts, ::sol::table self,
450 ::sol::object key) -> ::sol::object {
451 ::sol::object g{getters[key]};
452 if (g.get_type() == ::sol::type::function)
453 return ::sol::object{g.as<::sol::function>()()};
456 mt[
"__newindex"] = [setters, prev_newindex](::sol::table self, ::sol::object key,
457 ::sol::object value) {
458 ::sol::object s{setters[key]};
459 if (s.get_type() == ::sol::type::function) {
460 s.as<::sol::function>()(value);
465 m[::sol::metatable_key] = mt;
501 template <
class T,
auto Bases, std::size_t... I>
503 std::index_sequence<I...> ) {
506 m, name, std::make_index_sequence<bases.size()>{});
519 template <
class T,
auto Bases, std::size_t... I>
521 const char*
doc, std::index_sequence<I...> seq) {
525 m[name] = ::sol::lua_nil;
536 template <
class T,
auto Ctors,
bool HasDefault,
bool Aggregate,
bool Copyable,
540 if constexpr (sigs.size() != 0)
551 template <std::meta::info Mem,
class Style = ::welder::naming::none>
553 constexpr const char* name{
555 constexpr bool read_only{std::meta::is_const_type(std::meta::type_of(Mem)) ||
557 if constexpr (!std::meta::is_public(Mem)) {
563 if constexpr (read_only)
564 ut[name] = ::sol::readonly_property(&fa::get);
566 ut[name] = ::sol::property(&fa::get, &fa::set);
567 }
else if constexpr (read_only) {
568 ut[name] = ::sol::readonly(&[:Mem:]);
583 template <
class T, std::meta::info Getter, std::meta::info Setter>
586 if constexpr (Setter == std::meta::info{}) {
587 ut[name] = ::sol::readonly_property(&[:Getter:]);
588 }
else if constexpr (std::is_void_v<
589 typename [:std::meta::return_type_of(Setter):]>) {
590 ut[name] = ::sol::property(&[:Getter:], &[:Setter:]);
596 [:std::meta::type_of(std::meta::parameters_of(Setter)[0]):];
597 static constexpr auto sp{&[:Setter:]};
598 ut[name] = ::sol::property(
600 [](T& self, Arg v) { (self.*sp)(std::forward<Arg>(v)); });
607 template <auto Fns,
class Style = ::welder::naming::none>
612 std::make_index_sequence<Fns.size()>{});
617 template <auto Fns,
class Style = ::welder::naming::none>
623 std::make_index_sequence<Fns.size()>{});
634 template <
class T, auto Fns>
646 template <
class T, auto Fns, auto Covered>
648 constexpr auto seq{std::make_index_sequence<Fns.size()>{}};
649 if constexpr (!Covered[0])
651 if constexpr (!Covered[1])
658 template <
class T, std::meta::info Fn>
671 constexpr ::sol::meta_function slot{
673 ? ::sol::meta_function::less_than
674 : ::sol::meta_function::less_than_or_equal_to};
676 ut[slot] = ::sol::overload(
677 &synthesized_comparison<
683 &synthesized_comparison<
698 ::sol::table values{::sol::state_view{m.lua_state()}.create_table()};
701 values, [m](
const char* n, lua_Integer v)
mutable { m[n] = v; },
702 std::is_scoped_enum_v<E>};
713 ::sol::table values{::sol::state_view{m.lua_state()}.create_table()};
714 outer[name] = values;
719 [outer](
const char* n, lua_Integer v)
mutable {
720 outer[n] = ::sol::var(v);
722 std::is_scoped_enum_v<E>};
730 template <std::meta::info Enum,
class Style = ::welder::naming::none>
732 constexpr const char* name{
734 const lua_Integer value{
static_cast<lua_Integer
>(std::to_underlying([:Enum:]))};
735 e.values[name] = value;
737 e.mirror(name, value);
763 template <auto Fns,
class Style = ::welder::naming::none>
768 return m.get<sol::object>(fn_name);
783 template <std::meta::info Var,
class Style = ::welder::naming::none>
787 if constexpr (std::meta::is_const_type(std::meta::type_of(Var))) {
791 ::sol::state_view
lua{m.lua_state()};
796 s.
getters[key] = [] {
return [:Var:]; };
797 s.
setters[key] = [](
typename [:std::meta::type_of(Var):] v) {
805 ::sol::table sub{::sol::state_view{m.lua_state()}.create_table()};
818static_assert(::welder::rod<rod>,
819 "welder::rods::sol2::rod must satisfy welder::rod");
Backend-agnostic selection layer: the reflection predicates and selectors that decide what participat...
The contract a rod (a welder backend, welder::rods::…::rod) must satisfy to plug into the generic dri...
The stored forms of the annotation vocabulary.
consteval auto aggregate_fields()
The fields an aggregate is initialized from: its non-static data members in declaration order (all pu...
consteval std::size_t aggregate_required_arity()
How many leading fields the synthesized aggregate field constructor REQUIRES: everything up to and in...
std::string stringify(const T &self)
The stringifier wrapper every runtime rod binds for a swept ostream inserter (see is_stringifier_for)...
cmp_slot
The rewritten-expression comparison a rod binds for a type whose C++ comparisons come from operator<=...
consteval metamethod operator_mm(std::meta::info f)
Map a member operator to its sol2 metamethod ({…, nullptr} = not exposed).
T(A...) ctor_sig
The alias T(A...) — a constructor call signature, built by substitute (a namespace-scope alias so it ...
consteval bool welded_for(std::meta::info type, lang L)
Is type welded for language L — i.e.
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?
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.
@ lua
Lua (via the sol2 and LuaBridge3 backends).
@ static_method
a static member function → transform_static_method.
@ function
a free function → transform_function.
@ variable
a namespace variable → transform_variable.
@ method
a member function → transform_method.
consteval void validate_return_policy()
Reject a return_policy on Fn (for language L) that contradicts Fn's return type.
constexpr const char * name_of_or(const char *override_)
Resolve a bound name with a call-site override: override_ wins verbatim, nullptr falls back to name_o...
consteval const char * name_of()
The final bound name of Ent (a K-kind entity) for language L under name style Style.
consteval std::vector< std::meta::info > public_bases(std::meta::info type)
The types of the public base classes of type.
Splice-based accessors for data member Mem — the pointer-to-member-free route the rods bind a protect...
The identity style: bind every C++ identifier unchanged.
A welded enum's binding: the name→value table, how to mirror a name onto the enclosing scope,...
std::function< void(const char *, lua_Integer)> mirror
Write one name onto the enclosing scope.
bool scoped
true for enum class.
::sol::table values
The E = { Name = value, … } table.
Per-module session: the deferred state for live namespace variables.
::sol::table getters
name → fun(): value (live reads).
bool has_live
any mutable variable registered?
::sol::table setters
name → fun(value) (live writes).
static void add_field(auto &ut)
Bind data member Mem as a usertype property.
static module_type add_submodule(module_type &m, const char *name)
Create a submodule table named name under m.
static consteval void _collect_welded_bases(std::meta::info type, lang L, std::vector< std::meta::info > &out)
Collect all welded ancestors of type (transitively), deduplicated.
static void set_module_doc(module_type &, const char *)
No runtime module docstring in Lua (its home is a generated stub).
::sol::usertype< T > class_handle_type
The class / enum handles the per-class / per-enum hooks operate on — exactly what make_class / make_e...
static auto make_class(module_type &m, const char *name, const char *, std::index_sequence< I... >)
Create the sol::usertype<T> handle (constructors are installed by the driver's subsequent add_constru...
static void _prev_newindex(const ::sol::object &prev, ::sol::table self, const ::sol::object &key, const ::sol::object &value)
Route a missing-key write on the module to a captured previous __newindex (function or table form); w...
static void add_static_method(auto &ut)
Bind static-method overload group Fns as a class-table function (T.name(…)), grouped as in add_method...
static void close_module(module_type &m, session &s)
Close the session: install the live-variable metatable proxy, if any mutable variable was welded onto...
static consteval const char * special_method_name(std::meta::info op_fn)
Map a member operator to its Lua metamethod name (nullptr = not exposed).
static void add_enumerator(auto &e)
Add enumerator Enum (as its underlying integer).
static auto make_nested_enum(module_type &m, auto &outer, const char *name, const char *)
Create the Name = value table for a nested member enum, placed on the enclosing type's usertype (modu...
static auto make_enum(module_type &m, const char *name, const char *)
Create the enum's Name = value table on the module (doc ignored).
static auto make_nested_class(module_type &m, auto &outer, const char *name, const char *doc, std::index_sequence< I... > seq)
Create the sol::usertype<T> for a nested member type, placed on the enclosing type's usertype table (...
static void _register_operator(Target &t, std::index_sequence< I... >)
Register operator group Grp under its Lua metamethod slot (a single callable, or a sol::overload(…) f...
_enum_binding< E > enum_handle_type
static void _install_live_variables(module_type &m, ::sol::table getters, ::sol::table setters)
Install (or extend) the module table's metatable so absent keys in getters / setters read and write t...
static void add_comparisons(auto &ut)
Synthesize __lt/__le from operator<=> group Fns via rewritten expressions (a < b, …) — Lua derives >,...
static sol::object add_function(module_type &m, const char *name=nullptr)
Bind free-function overload group Fns as one module-level function (a single callable,...
static consteval auto _ctor_sigs_array()
_ctor_signatures<T, …>() as a fixed-size, splice-ready static array.
static consteval std::vector< std::meta::info > _ctor_signatures()
The set of sol::constructors<…> signatures to expose for T, as function- type reflections T(A....
static consteval auto _welded_bases_array()
_collect_welded_bases for T as a fixed-size, splice-ready static array.
static void add_property(auto &ut, const char *name)
Bind the resolved property (Getter + optional Setter) as a usertype property named name (driver-resol...
static void finish_enum(auto &)
No whole-enum finalizer needed (unscoped export is done per-enumerator).
static void add_variable(module_type &m, session &s, const char *name=nullptr)
Bind namespace variable Var onto the module.
static void add_stringifier(auto &ut)
Bind the swept free ostream inserter Fn as __tostring (via welder::detail::stringify — print(obj) / t...
static void add_operator(auto &ut)
Bind operator slot group Fns under its Lua metamethod — one (operator, arity) slot whole,...
static void add_constructors(::sol::usertype< T > &ut)
Install T's whole constructor set — exactly what sol2 wants (one sol::constructors<…> assignment cove...
static void _set_constructors(::sol::usertype< T > &ut, std::index_sequence< I... >)
Register T's constructor set on the usertype from the reflected signatures.
static auto _make_usertype(::sol::table &m, const char *name, std::index_sequence< I... >)
Create m.new_usertype<T, Bases…>(name) with sol2's base-class linkage.
static session open_module(module_type &)
Open a per-module session.
static constexpr lang language
welder::lang::lua.
static constexpr bool has_native_caster
caster_oracle: T converts without welder registering a usertype iff sol2 does not classify it as need...
::sol::object _prev_index(::sol::this_state ts, const ::sol::object &prev, const ::sol::table &self, const ::sol::object &key)
Route a missing-key read on the module to a captured previous __index (function or table form),...
::sol::table module_type
A Lua module is a table.
static void _register_named(Target &t, const char *name, std::index_sequence< I... >)
Register overload group Grp on target t under the (already name-styled) name — a single callable when...
static void _register_synth_cmp(Target &ut, std::index_sequence< I... >)
Assign one synthesized comparison slot: a sol::overload of the rewritten-expression wrappers,...
static constexpr bool _needs_registration
Whether sol2 can only convert T via runtime usertype registration.
static void add_method(auto &ut)
Bind method overload group Fns as one method (obj:name(…)) — a single callable when unique,...
welder's binding entry point: the welder::welder struct.