dep-ygopro-core/function_array_helper.h

101 lines
3.4 KiB
C
Raw Permalink Normal View History

2022-05-14 19:53:46 +02:00
/*
* Copyright (c) 2022-2025, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
2022-05-14 19:53:46 +02:00
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#ifndef FUNCTION_ARRAY_HELPER_H
#define FUNCTION_ARRAY_HELPER_H
#include "scriptlib.h"
#include <meta>
#include <string_view>
#define LUA_NAMESPACE lua_functions
2025-07-05 19:50:36 +02:00
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define MAKE_LUA_MODULE_IMPL(module) c_lua_##module##_
#define MAKE_LUA_MODULE(module) MAKE_LUA_MODULE_IMPL(module)
#define LUA_PREFIX STR(MAKE_LUA_MODULE(LUA_MODULE))
#define MAKE_LUA_NAME_IMPL(module, name) c_lua_##module##_##name
#define MAKE_LUA_NAME(module, name) MAKE_LUA_NAME_IMPL(module, name)
#define LUA_FUNCTION(name) [[maybe_unused]] static int32_t MAKE_LUA_NAME(LUA_MODULE,name) \
([[maybe_unused]] lua_State* const L, \
[[maybe_unused]] LUA_CLASS* const self, [[maybe_unused]] duel* const pduel)
#define LUA_STATIC_FUNCTION(name) [[maybe_unused]] static int32_t MAKE_LUA_NAME(LUA_MODULE,name) \
([[maybe_unused]] lua_State* const L, [[maybe_unused]] duel* const pduel)
#define LUA_FUNCTION_ALIAS(name) [[maybe_unused]] static lua_alias MAKE_LUA_NAME(LUA_MODULE,name)
#define LUA_FUNCTION_EXISTING(name,...) [[maybe_unused]] [[=aliases(__VA_ARGS__)]] static int32_t MAKE_LUA_NAME(LUA_MODULE,name) \
([[maybe_unused]] lua_State* const L)
2022-05-14 19:53:46 +02:00
namespace {
struct aliases { lua_CFunction field; };
struct lua_alias { };
template<std::meta::info Namespace>
constexpr auto get_lua_functions() {
constexpr auto lua_symbols = [] {
constexpr auto ctx = std::meta::access_context::current();
std::vector<std::meta::info> res;
template for (constexpr auto M : define_static_array(members_of(Namespace, ctx))) {
if constexpr(identifier_of(M).starts_with(LUA_PREFIX)) {
res.push_back(M);
}
}
return define_static_array(res);
}();
std::array<luaL_Reg, lua_symbols.size()+1> ret_array{};
int i = 0;
template for (constexpr auto M : define_static_array(lua_symbols)) {
constexpr auto identifier = identifier_of(M).substr(std::string_view{LUA_PREFIX}.size());
if constexpr(is_function(M)) {
constexpr auto annotations = define_static_array(annotations_of_with_type(M, ^^aliases));
static_assert(annotations.size() <= 1);
if constexpr(annotations.size() == 1) {
constexpr auto annotation = extract<aliases>(annotations[0]);
static_assert(annotation.field != nullptr);
ret_array[i] = luaL_Reg{identifier.data(), annotation.field};
} else {
static constexpr auto func_ptr = [:M:];
static constexpr auto parameters = define_static_array(parameters_of(M));
static constexpr auto num_of_parameters = parameters.size();
ret_array[i] = luaL_Reg{identifier.data(), [](lua_State* L) -> int {
using namespace scriptlib;
#if defined(LUA_CLASS)
if constexpr(num_of_parameters == 3) {
return func_ptr(L, lua_get<LUA_CLASS*, true>(L, 1), lua_get<duel*>(L));
} else
#endif
if constexpr(num_of_parameters == 2) {
return func_ptr(L, lua_get<duel*>(L));
}
}};
}
} else if constexpr(is_variable(M)) {
static_assert(type_of(M) == ^^lua_alias);
ret_array[i] = luaL_Reg{identifier.data(), ret_array[i - 1].func};
}
i++;
}
ret_array[i] = {nullptr,nullptr};
return ret_array;
2022-05-14 19:53:46 +02:00
}
}
#undef LUA_PREFIX
#undef STR
#undef STR_HELPER
#undef MAKE_LUA_MODULE_IMPL
#undef MAKE_LUA_MODULE
2022-05-14 19:53:46 +02:00
#define GET_LUA_FUNCTIONS_ARRAY() get_lua_functions<^^LUA_NAMESPACE>()
2022-05-14 19:53:46 +02:00
#endif // FUNCTION_ARRAY_HELPER_H