nngn
Loading...
Searching...
No Matches
lua.h
Go to the documentation of this file.
1
40#ifndef NNGN_LUA_LUA_H
41#define NNGN_LUA_LUA_H
42
43#include <numeric>
44#include <optional>
45
46#include <lua.hpp>
47
48#include "utils/concepts.h"
49#include "utils/fixed_string.h"
50#include "utils/fn.h"
51#include "utils/ranges.h"
52#include "utils/utils.h"
53
54struct lua_State;
55
56namespace nngn::lua {
57
58class global_table;
59class state_view;
60struct table;
61struct value;
62class value_view;
63
64#define NNGN_LUA_TYPES(X) \
65 X(none, LUA_TNONE) \
66 X(nil, LUA_TNIL) \
67 X(boolean, LUA_TBOOLEAN) \
68 X(light_user_data, LUA_TLIGHTUSERDATA) \
69 X(number, LUA_TNUMBER) \
70 X(string, LUA_TSTRING) \
71 X(table, LUA_TTABLE) \
72 X(function, LUA_TFUNCTION) \
73 X(user_data, LUA_TUSERDATA) \
74 X(thread, LUA_TTHREAD)
75
77enum class type : int {
78#define X(n, v) n = v,
80#undef X
81};
82
84inline constexpr struct nil_type {} nil;
85
87template<typename T> struct error { T e; };
88
89// XXX clang
90template<typename T> error(T) -> error<T>;
91
93inline constexpr std::array types = [] {
94 using U = std::underlying_type_t<type>;
95 constexpr auto f = to_underlying<type>;
96 constexpr auto b = f(type::none), e = f(type::thread) + 1;
97 constexpr auto n = e - b;
98 std::array<U, n> u = {};
99 std::array<type, n> ret = {};
100 std::iota(begin(u), end(u), b);
101 std::transform(
102 std::ranges::begin(u), std::ranges::end(u),
103 std::ranges::begin(ret), to<type>{});
104 return ret;
105}();
106static_assert(is_sequence(types, to_underlying<type>));
107
109inline constexpr type type_from_lua(int t) {
111 assert(t <= to_underlying(types.back()));
112 constexpr auto b = std::find(begin(types), end(types), type::nil);
113 static_assert(b != end(types));
114 return b[t];
115}
116
118template<typename> struct stack_get;
120template<typename = void> struct stack_push;
121
123// Note: a function template would remove the need for the `stack_push<>::push`
124// circumlocution, but non dependent names (e.g. `stack_push(L, x)`) are bound
125// when a template is defined, not instantiated:
126//
127// https://en.cppreference.com/w/cpp/language/dependent_name#Binding_rules
128//
129// This meant any members of the overload set defined after a particular use of
130// \ref stack_push would not be seen.
131template<>
132struct stack_push<void> {
133 template<typename T>
134 static int push(lua_State *L, T &&t) {
136 }
137};
138
145template<typename T> inline constexpr auto is_user_type = false;
146
148template<typename T> concept user_type = is_user_type<std::decay_t<T>>;
149
156template<typename T> inline constexpr empty metatable_name = {};
157
158template<typename R, typename ...Args>
159R call(lua_State *L, R(*f)(Args...), int i = 1);
160template<typename R, typename T, typename ...Args>
161R call(lua_State *L, R(T::*f)(Args...), int i = 1);
162template<typename R, typename T, typename ...Args>
163R call(lua_State *L, R(T::*f)(Args...) const, int i = 1);
164template<stateless_lambda T>
165decltype(auto) call(lua_State *L, T, int i = 1);
166
167namespace detail {
168
169template<typename CRTP, typename T> class table_iter_base;
170template<typename T> class table_iter;
171template<typename T> class table_seq_iter;
173enum op_mode { normal, raw };
174
176struct table_base_tag {};
177
179struct table_proxy_tag {};
180
182template<typename T>
183inline constexpr bool can_get = requires(lua_State *L) {
184 stack_get<T>::get(L, 0);
185};
186
188template<typename T>
189inline constexpr bool can_push = requires(lua_State *L, T t) {
190 stack_push<T>::push(L, t);
191};
192
194template<typename T>
195concept stack_value = can_get<T> && can_push<T>;
196
198template<typename T>
199concept stack_type = requires(lua_State *L, int i, T t) {
200 { T{L, i} };
201 { t.state() } -> std::same_as<state_view>;
202 { t.push() } -> std::same_as<int>;
203};
204
206template<typename T>
207concept integer = convertible_to_strict<T, lua_Integer>;
208
210template<typename T>
211concept number = convertible_to_strict<T, lua_Number>;
212
213template<typename T> inline constexpr bool is_optional = false;
214template<typename T> inline constexpr bool is_optional<std::optional<T>> = true;
215
216}
217
223template<typename T> inline constexpr bool is_stack_ref = false;
224
225template<typename T>
226inline constexpr bool is_stack_ref<std::optional<T>> = is_stack_ref<T>;
227
229template<typename T> concept stack_ref = is_stack_ref<std::decay_t<T>>;
230
231std::string_view type_str(type t);
233int msgh(lua_State *L);
235void print_stack(lua_State *L);
237void print_traceback(lua_State *L);
238
239inline std::string_view type_str(type t) {
240 switch(t) {
241#define X(n, _) case type::n: return #n;
243#undef X
244 default: return "unknown";
245 }
246}
247
248}
249
250#endif
function DEMO text end
Definition: demo0.lua:6
for i
Definition: font.lua:5
assert
Definition: debug.lua:3
n
Definition: dump_lights.lua:5
function f()) end
#define NNGN_LUA_TYPES(X)
Definition: lua.h:64
error
Definition: strict.lua:2
#define FWD(...)
Definition: utils.h:18
#define T(f0, f1, f2)
e
Definition: math.lua:4
constexpr bool is_optional
Definition: lua.h:212
op_mode
Definition: lua.h:172
@ raw
Definition: lua.h:172
@ normal
Definition: lua.h:172
constexpr bool can_push
Whether this library knows how to push a T value onto the stack.
Definition: lua.h:188
constexpr bool can_get
Whether this library knows how to read a T value from the stack.
Definition: lua.h:182
Definition: lua_audio.cpp:19
constexpr type type_from_lua(int t)
Maps LUA_T* values to type.
Definition: lua.h:108
void print_stack(lua_State *L)
Logs the current data stack.
Definition: lua.cpp:26
int msgh(lua_State *L)
Default message handler for lua_pcall.
Definition: lua.cpp:15
T push(nngn::lua::state_view lua, auto &&v)
Definition: state.h:186
std::string_view type_str(type t)
Definition: lua.h:238
constexpr bool is_stack_ref
Determines whether a type is a reference to a value on the stack.
Definition: lua.h:222
constexpr bool is_stack_ref< T >
Definition: table.h:452
type
LUA_T* constants as a scoped enumeration.
Definition: lua.h:77
constexpr auto is_user_type
Flag which indicates that a type is to be treated as a user type.
Definition: lua.h:144
R call(lua_State *L, R(*f)(Args...), int i)
Calls the regular function f with arguments taken from the stack.
Definition: function.h:125
constexpr struct nngn::lua::nil_type nil
constexpr empty metatable_name
Key in the global table where the meta-table for T is stored.
Definition: lua.h:155
void print_traceback(lua_State *L)
Logs the current call stack.
Definition: lua.cpp:59
constexpr std::array types
type values as a sequential array.
Definition: lua.h:92
constexpr const R * begin(const T< R > &v)
Definition: vec.h:207
constexpr auto to_underlying(T t)
Definition: utils.h:138
constexpr bool is_sequence(R &&r, Proj proj={})
Definition: ranges.h:119
empty
Definition: utils.h:89
T e
Definition: lua.h:86
Pushes a value onto the Lua stack.
Definition: lua.h:119