91#include <LuaBridge/LuaBridge.h>
101struct Stack<E, std::enable_if_t<std::is_enum_v<E>>> : Enum<E> {};
124template <
class T,
class... A>
126 return T(std::move(args)...);
150 lua_State*
L{
nullptr};
151 std::vector<std::string>
path{};
212 std::is_enum_v<std::remove_cvref_t<T>> ||
213 lb::detail::IsUserdata<std::remove_cvref_t<T>>::value;
225 lb::Namespace ns{lb::getGlobalNamespace(m.
L)};
226 for (
const auto& seg : m.
path)
227 ns = ns.beginNamespace(seg.c_str());
250 lua_pushglobaltable(m.
L);
251 for (
const auto& seg : m.
path) {
252 lua_pushlstring(m.
L, seg.data(), seg.size());
263 template <
class T, auto Ctors,
bool HasDefault,
bool Aggregate>
265 std::vector<std::vector<std::meta::info>> lists;
268 for (
auto c : Ctors) {
269 std::vector<std::meta::info> args;
270 for (
auto p : std::meta::parameters_of(c))
271 args.push_back(std::meta::type_of(p));
272 lists.push_back(args);
277 if constexpr (Aggregate) {
285 if (HasDefault && start == 0)
287 for (std::size_t arity{start}; arity <= fields.size(); ++arity) {
288 std::vector<std::meta::info> args;
289 for (std::size_t i{0}; i < arity; ++i)
290 args.push_back(std::meta::type_of(fields[i]));
291 lists.push_back(args);
299 template <
class T, auto Ctors,
bool HasDefault,
bool Aggregate>
301 constexpr std::size_t n{
303 std::array<std::meta::info, n> out{};
304 if constexpr (n != 0) {
306 for (std::size_t i{0}; i < n; ++i)
307 out[i] = std::meta::dealias(std::meta::substitute(^^
ctor_sig, lists[i]));
314 template <
class T, auto Ctors,
bool HasDefault,
bool Aggregate>
316 constexpr std::size_t n{
318 std::array<std::meta::info, n> out{};
319 if constexpr (n != 0) {
321 for (std::size_t i{0}; i < n; ++i) {
322 std::vector<std::meta::info> targs{^^T};
323 for (
auto a : lists[i])
325 out[i] = std::meta::substitute(^^
make_object, targs);
335 template <
auto Sigs,
auto Factories,
class Cls, std::size_t... I>
337 cls.template addConstructor<
typename [:Sigs[I]:]...>();
338 cls.addStaticFunction(
"new", &[:Factories[I]:]...);
345 template <
class T,
auto Bases, std::size_t... I>
347 std::index_sequence<I...>) {
348 if constexpr (
sizeof...(I) == 0) {
352 .template deriveClass<T,
typename [:Bases[I]:]...>(name)};
361 template <
auto Grp,
class Target, std::size_t... I>
363 std::index_sequence<I...>) {
370 t.addFunction(name, &[:Grp[I]:]...);
374 template <
auto Grp,
class Target, std::size_t... I>
376 std::index_sequence<I...>) {
378 t.addStaticFunction(name, &[:Grp[I]:]...);
403 template <
class T,
auto Bases, std::size_t... I>
406 std::index_sequence<I...> ) {
420 template <
class T,
auto Bases, std::size_t... I>
422 const char* name,
const char* ,
423 std::index_sequence<I...> ) {
424 std::string temp{outer.name +
"." + name};
426 std::make_index_sequence<Bases.size()>{});
440 lua_State* L{cls.mod.L};
442 lua_pushlstring(L, cls.name.data(), cls.name.size());
444 lua_pushlstring(L, outer.name.data(), outer.name.size());
446 lua_pushstring(L, name);
447 lua_pushvalue(L, -3);
450 lua_pushlstring(L, cls.name.data(), cls.name.size());
463 template <
class T,
auto Ctors,
bool HasDefault,
bool Aggregate,
bool Copyable,
468 if constexpr (sigs.size() != 0) {
471 cls, std::make_index_sequence<sigs.size()>{});
485 template <std::meta::info Mem,
class Style = ::welder::naming::none>
488 constexpr const char* name{
490 constexpr bool read_only{std::meta::is_const_type(std::meta::type_of(Mem)) ||
493 if constexpr (!std::meta::is_public(Mem)) {
499 if constexpr (read_only)
500 cls.addProperty(name, &fa::get);
502 cls.addProperty(name, &fa::get, &fa::set);
504 using Field =
typename [:std::meta::type_of(Mem):];
505 constexpr Field T::* mp{&[:Mem:]};
506 if constexpr (read_only)
507 cls.addProperty(name, mp);
509 cls.addProperty(name, mp, mp);
526 template <
class T, std::meta::info Getter, std::meta::info Setter>
530 using GF =
typename [:std::meta::type_of(Getter):];
531 static constexpr GF T::* get{&[:Getter:]};
532 if constexpr (Setter == std::meta::info{}) {
533 cls.addProperty(name, get);
535 using SF =
typename [:std::meta::type_of(Setter):];
536 static constexpr SF T::* set{&[:Setter:]};
537 if constexpr (std::meta::dealias(std::meta::return_type_of(Setter)) ==
539 cls.addProperty(name, get, set);
545 [:std::meta::type_of(std::meta::parameters_of(Setter)[0]):];
547 name, [](
const T* self) ->
decltype(
auto) {
return (self->*get)(); },
548 [](T* self, Arg v) { (self->*set)(std::forward<Arg>(v)); });
556 template <auto Fns,
class Style = ::welder::naming::none>
563 std::make_index_sequence<Fns.size()>{});
568 template <auto Fns,
class Style = ::welder::naming::none>
576 std::make_index_sequence<Fns.size()>{});
605 template <
class T, auto Fns>
607 constexpr auto Fn{Fns[0]};
610 if constexpr (std::meta::operator_of(Fn) ==
611 std::meta::operators::op_square_brackets) {
612 using Key = std::remove_cvref_t<
typename [:std::meta::type_of(
613 std::meta::parameters_of(Fn)[0]):]>;
614 cls.addIndexMetaMethod(
615 +[](T& self,
const lb::LuaRef& key, lua_State* L) -> lb::LuaRef {
616 if constexpr (std::is_arithmetic_v<Key>) {
619 const lua_Number n{lua_tonumberx(L, -1, &is_num)};
622 return lb::LuaRef(L);
623 return lb::LuaRef(L, self[
static_cast<Key
>(n)]);
625 if (
auto k = key.template cast<Key>())
626 return lb::LuaRef(L, self[*k]);
627 return lb::LuaRef(L);
632 constexpr auto direct{
635 cls, slot, std::make_index_sequence<direct.size()>{});
646 template <
class T, auto Fns, auto Covered>
649 constexpr auto seq{std::make_index_sequence<Fns.size()>{}};
650 if constexpr (!Covered[0])
653 if constexpr (!Covered[1])
660 template <
class T, std::meta::info Fn>
676 template <
class T,
auto Fns,
auto Direct,
class C, std::size_t... I>
678 std::index_sequence<I...>) {
679 template for (
constexpr auto fn : std::define_static_array(Fns)) {
682 if constexpr (Direct.size() == Fns.size())
683 cls.addFunction(slot, &[:Direct[I]:]...);
691 template <
class T, auto Fns>
694 template for (
constexpr auto fn : std::define_static_array(Fns)) {
700 L,
"welder: no matching operator overload for these operands");
708 template <
class T, std::meta::info Fn>
710 if (lua_gettop(L) < 2)
712 const lb::LuaRef a{lb::LuaRef::fromStack(L, 1)};
713 const lb::LuaRef b{lb::LuaRef::fromStack(L, 2)};
714 if constexpr (std::meta::is_class_member(Fn)) {
715 using B_ = std::remove_cvref_t<
typename [:std::meta::type_of(
716 std::meta::parameters_of(Fn)[0]):]>;
717 const auto vb{b.template cast<B_>()};
720 if constexpr (
requires(
const T& s,
const B_& x) { s.[:Fn:](x); }) {
721 const auto pt{a.template cast<const T*>()};
722 if (!pt || *pt ==
nullptr)
726 const auto pt{a.template cast<T*>()};
727 if (!pt || *pt ==
nullptr)
732 using A_ = std::remove_cvref_t<
typename [:std::meta::type_of(
733 std::meta::parameters_of(Fn)[0]):]>;
734 using B_ = std::remove_cvref_t<
typename [:std::meta::type_of(
735 std::meta::parameters_of(Fn)[1]):]>;
736 const auto va{a.template cast<A_>()};
739 const auto vb{b.template cast<B_>()};
749 const auto r{lb::Stack<std::remove_cvref_t<R>>::push(
750 L, std::forward<R>(v))};
752 return luaL_error(L,
"welder: failed to push operator result");
765 std::index_sequence<I...>) {
773 &synthesized_comparison<
783 template <
class T, auto Fns, ::welder::detail::cmp_slot S>
786 template for (
constexpr auto fn : std::define_static_array(Fns)) {
787 using P = std::remove_cvref_t<
791 if constexpr (!std::is_same_v<P, T>) {
798 L,
"welder: no matching comparison for these operands");
804 template <
class T,
class P, ::welder::detail::cmp_slot S,
bool Rev>
806 using A_ = std::conditional_t<Rev, P, T>;
807 using B_ = std::conditional_t<Rev, T, P>;
808 if (lua_gettop(L) < 2)
810 const auto va{lb::LuaRef::fromStack(L, 1).template cast<A_>()};
813 const auto vb{lb::LuaRef::fromStack(L, 2).template cast<B_>()};
830 return enum_handle{m, std::string{name}, std::is_scoped_enum_v<E>};
841 const char* name,
const char* ) {
842 lua_State* L{outer.mod.L};
844 lua_pushlstring(L, outer.name.data(), outer.name.size());
846 lua_pushstring(L, name);
850 return enum_handle{outer.mod, std::string{name}, std::is_scoped_enum_v<E>,
859 template <std::meta::info Enum,
class Style = ::welder::naming::none>
861 constexpr const char* name{
863 const lua_Integer value{
static_cast<lua_Integer
>(std::to_underlying([:Enum:]))};
871 lua_State* L{e.
mod.
L};
875 lua_pushlstring(L, e.
name.data(), e.
name.size());
877 lua_pushstring(L, name);
878 lua_pushinteger(L, value);
882 lua_pushstring(L, name);
883 lua_pushinteger(L, value);
908 template <auto Fns,
class Style = ::welder::naming::none>
915 std::make_index_sequence<Fns.size()>{});
925 template <std::meta::info Var,
class Style = ::welder::naming::none>
927 const char* name =
nullptr) {
931 if constexpr (std::meta::is_const_type(std::meta::type_of(Var))) {
932 ns.addVariable(key, [:Var:]);
934 using VT =
typename [:std::meta::type_of(Var):];
936 key, +[]() -> VT {
return [:Var:]; }, +[](VT v) { [:Var:] = v; });
944 sub.
path.emplace_back(name);
952static_assert(::welder::rod<rod>,
953 "welder::rods::luabridge::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 partition_reflected()
Split slot group Fns by free_operator_reflected — the entries whose reflectedness equals Reflected,...
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...
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 ...
consteval bool has_heterogeneous_comparison()
Whether spaceship group Fns contains a heterogeneous overload (an operand that is not Type itself) — ...
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 const char * lua_metamethod_name(std::meta::info f)
Map an operator (member or anchored free) to its Lua metamethod __name, or nullptr if welder does not...
T make_object(A... args)
A factory that constructs T from the constructor arguments (works for normal constructors and,...
consteval const char * lua_metamethod_name(std::meta::info f)
Map an operator (member or anchored free) to its Lua metamethod __name, or nullptr if welder does not...
void(A...) ctor_sig
The alias void(A...) — a LuaBridge3 constructor signature (a function type whose parameters are the c...
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?
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.
Splice-based accessors for data member Mem — the pointer-to-member-free route the rods bind a protect...
static bool call(const A &a, const B &b)
Evaluate a OP b through C++'s rewriting rules.
The identity style: bind every C++ identifier unchanged.
The class handle threaded from make_class to the add_* hooks: enough to re-open the class (its module...
std::string name
The class's Lua name.
T type
The C++ class type.
module_scope mod
The enclosing module.
The enum handle threaded from make_enum to add_enumerator: the enclosing module, the enum's Lua name ...
A copyable handle to a welded module (or submodule) table: the borrowed Lua state plus the namespace ...
lua_State * L
The borrowed Lua state.
std::vector< std::string > path
Namespace segments under _G.
Per-module session — unused: LuaBridge3 registers namespace variables as live properties eagerly (no ...
static void _make_class(const module_scope &m, const char *name, std::index_sequence< I... >)
Create the class registration with its native (welded nearest-ancestor) bases, in one chained express...
static consteval auto _factory_array()
The make_object<T, A...> factory-function reflections (for the .new static function) as a fixed-size,...
static void _add_static_function(Target &t, const char *name, std::index_sequence< I... >)
As _add_function, for a class's static methods (addStaticFunction).
static int _push_result(lua_State *L, R &&v)
Push an operator result and report success to Lua.
static constexpr lang language
welder::lang::lua.
static void add_operator(auto &h)
Bind operator slot group Fns under its Lua metamethod __name — one (operator, arity) slot whole,...
static module_type add_submodule(module_type &m, const char *name)
Create a submodule (nested namespace) named name under m.
static enum_handle make_enum(module_type &m, const char *name, const char *)
Create the enum's nested namespace (a Name = value table) on the module (doc ignored) and return a re...
static consteval auto _ctor_sigs_array()
The void(A...) constructor-signature reflections (for addConstructor) as a fixed-size,...
static int _try_cmp(lua_State *L)
Try one comparison direction: stack = (T, P), or (P, T) when Rev.
static void add_field(auto &h)
Bind data member Mem as a class property (read-only if const or marked [[=welder::mark::no_reassign]]...
module_scope module_type
A Lua module is a named table.
static constexpr bool _needs_registration
Whether LuaBridge3 can only convert T via runtime class registration.
static class_handle< T > make_nested_class(module_type &, auto &outer, const char *name, const char *, std::index_sequence< I... >)
Register a nested member type T under a temporary dotted module key ("Outer.Inner").
static void _add_synth_cmp(C &cls, const char *name, std::index_sequence< I... >)
Register one synthesized comparison slot.
static enum_handle make_nested_enum(module_type &, auto &outer, const char *name, const char *)
Create the Name = value table for a nested member enum directly inside the enclosing class's table (m...
static consteval std::vector< std::vector< std::meta::info > > _ctor_arg_lists()
The set of constructor argument lists to expose for T, built from the pieces the DRIVER hands to add_...
enum_handle enum_handle_type
static void _push_module_table(const module_scope &m)
Push the module's namespace table onto the Lua stack (a raw walk from _G through the path segments); ...
typename std::remove_cvref_t< H >::type _class_type
The C++ type behind a class_handle<T>& (deduced from the driver's auto&).
static void add_static_method(auto &h)
Bind static-method overload group Fns as a class-table function (T.name(…)), grouped as in add_method...
static void add_function(module_type &m, const char *name=nullptr)
Bind free-function overload group Fns as one module-level function (a single variadic addFunction; na...
static void add_variable(module_type &m, session &, const char *name=nullptr)
Bind namespace variable Var onto the module.
static class_handle< T > make_class(module_type &m, const char *name, const char *, std::index_sequence< I... >)
Register class T (with its native bases and constructors) and return a re-openable handle.
static void _add_constructors(Cls &cls, std::index_sequence< I... >)
Register the whole constructor set on the (live) class cls: both the call form T(…) (addConstructor,...
static void add_method(auto &h)
Bind method overload group Fns as one method (obj:name(…)) via a single variadic addFunction — LuaBri...
static void add_stringifier(auto &h)
Bind the swept free ostream inserter Fn as __tostring (via welder::detail::stringify).
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_comparisons(auto &h)
Synthesize __lt/__le from operator<=> group Fns via rewritten expressions — Lua derives >,...
static void add_constructors(auto &h)
Register T's whole constructor set — exactly what LuaBridge3 wants (one variadic addConstructor for t...
static void _add_function(Target &t, const char *name, std::index_sequence< I... >)
Register overload group Grp on target t (a live class or namespace) under name via LuaBridge3's varia...
static void close_module(module_type &, session &)
Close the session (no-op; see session).
static void add_property(auto &h, const char *name)
Bind the resolved property (Getter + optional Setter) as a class property named name (driver-resolved...
static void finish_enum(auto &)
No whole-enum finalizer needed (unscoped export is done per-enumerator).
static constexpr bool has_native_caster
caster_oracle: T converts without welder registering a class iff LuaBridge3 does not classify it as n...
static void finish_nested_class(module_type &, auto &outer, auto &cls, const char *name)
Move the fully-registered nested class table onto the outer's class table (module....
static int _cmp_dispatch(lua_State *L)
The raw comparison dispatcher: per spaceship overload, try the forward (T, P) order,...
class_handle< T > class_handle_type
The class / enum handles the per-class / per-enum hooks receive — exactly what make_class / make_enum...
static int _try_operator_entry(lua_State *L)
Try one (binary) entry: convert both operands to the entry's declared types — by value via LuaRef::ca...
static lb::Namespace _open_namespace(const module_scope &m)
Open the module's namespace chain from the global namespace, returning the innermost luabridge::Names...
static auto _open_class(const module_scope &m, const char *name)
Re-open class T under name in module m, returning the live luabridge::Namespace::Class<T> (created by...
static void set_module_doc(module_type &, const char *)
No runtime module docstring in Lua (its home is a generated stub).
static session open_module(module_type &)
Open a per-module session (unused; see session).
static void add_enumerator(enum_handle &e)
Add enumerator Enum (as its underlying integer) to the enum's table.
static int _op_dispatch(lua_State *L)
The raw slot dispatcher: try each entry in turn against the operands on the stack (Lua hands a metame...
static void _add_operator_slot(C &cls, const char *slot, std::index_sequence< I... >)
Register one operator slot.
welder's binding entry point: the welder::welder struct.