-
Notifications
You must be signed in to change notification settings - Fork 31
/
interpreter.h
125 lines (111 loc) · 4.22 KB
/
interpreter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
* Copyright (c) 2010-2015, Argon Sun (Fluorohydride)
* Copyright (c) 2017-2024, Edoardo Lolletti (edo9300) <[email protected]>
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#ifndef INTERPRETER_H_
#define INTERPRETER_H_
// Due to longjmp behaviour, we must build Lua as C++ to avoid UB
#include <cstdio> //std::snprintf
#include <list>
#include <type_traits> //std::is_integral_v
#include <unordered_map>
#include <utility> //std::forward
#include <vector>
#include "common.h"
#include "lua_obj.h"
#include "ocgapi_types.h"
#include "scriptlib.h"
class card;
class effect;
class group;
class duel;
struct lua_State;
using lua_invalid = lua_obj_helper<LuaParam::DELETED>;
class interpreter {
char msgbuf[128]{};
public:
using coroutine_map = std::unordered_map<int32_t, std::pair<lua_State*, int32_t>>;
union lua_param {
void* ptr;
lua_Integer integer;
};
private:
void add_param(lua_param param, LuaParam type, bool front) {
if(front)
params.emplace_front(param, type);
else
params.emplace_back(param, type);
}
public:
using param_list = std::list<std::pair<lua_param, LuaParam>>;
duel* pduel;
lua_State* lua_state;
lua_State* current_state;
param_list params;
coroutine_map coroutines;
int32_t no_action;
int32_t call_depth;
lua_invalid deleted;
interpreter(duel* pd, const OCG_DuelOptions& options);
~interpreter();
void register_card(card* pcard);
void register_effect(effect* peffect);
void unregister_effect(effect* peffect);
void register_group(group* pgroup);
void unregister_group(group* pgroup);
void register_obj(lua_obj* obj, const char* tablename);
bool load_script(const char* buffer, int len = 0, const char* script_name = nullptr);
bool load_card_script(uint32_t code);
template<LuaParam type, typename T>
void add_param(T param, bool front = false) {
lua_param p;
if constexpr(std::is_integral_v<T>) {
static_assert(type == LuaParam::INT || type == LuaParam::FUNCTION || type == LuaParam::BOOLEAN || type == LuaParam::INDEX,
"Passed parameter type doesn't match provided LuaParam");
p.integer = param;
} else {
static_assert(scriptlib::get_lua_param_type<T>() == type);
p.ptr = param;
}
add_param(p, type, front);
}
void push_param(lua_State* L, bool is_coroutine = false);
bool call_function(int32_t f, uint32_t param_count, int32_t ret_count);
bool call_card_function(card* pcard, const char* f, uint32_t param_count, int32_t ret_count, bool forced = true);
bool call_code_function(uint32_t code, const char* f, uint32_t param_count, int32_t ret_count);
bool check_condition(int32_t f, uint32_t param_count);
bool check_matching(card* pcard, int32_t findex, int32_t extraargs);
bool check_matching_table(card* pcard, int32_t findex, int32_t table_index);
lua_Integer get_operation_value(card* pcard, int32_t findex, int32_t extraargs);
bool get_operation_value(card* pcard, int32_t findex, int32_t extraargs, std::vector<lua_Integer>& result);
lua_Integer get_function_value(int32_t f, uint32_t param_count);
bool get_function_value(int32_t f, uint32_t param_count, std::vector<lua_Integer>& result);
int32_t call_coroutine(int32_t f, uint32_t param_count, lua_Integer* yield_value, uint16_t step);
int32_t clone_lua_ref(int32_t lua_ref);
void* get_ref_object(int32_t ref_handler);
bool call_function(int param_count, int ret_count);
inline bool ret_fail(const char* message);
inline bool ret_fail(const char* message, bool error);
inline int call_lua(lua_State* L, int nargs, int nresults);
static void pushobject(lua_State* L, lua_obj* obj);
static void pushobject(lua_State* L, int32_t lua_ptr);
static int pushExpandedTable(lua_State* L, int32_t table_index);
static int32_t get_function_handle(lua_State* L, int32_t index);
static void print_stacktrace(lua_State* L);
template <size_t N, typename... TR>
static inline const char* format_to(char (&out)[N], const char* format, TR&&... args) {
if(std::snprintf(out, sizeof(out), format, std::forward<TR>(args)...) >= 0)
return out;
return "";
}
template <typename... TR>
inline const char* format(const char* format, TR&&... args) {
return format_to(msgbuf, format, std::forward<TR>(args)...);
}
};
#define COROUTINE_FINISH 1
#define COROUTINE_YIELD 2
#define COROUTINE_ERROR 3
#endif /* INTERPRETER_H_ */