10 using error::throwTrace;
15 const char *
str = lua_tostring(L, -1);
20 m_what = msg +
": " +
str;
29 int atpanic(lua_State *L)
31 error::throwTrace<std::runtime_error>(
"Lua panic");
39 const luaL_Reg loadedlibs[] = {
40 {
"_G", luaopen_base },
42 { LUA_COLIBNAME, luaopen_coroutine },
43 { LUA_TABLIBNAME, luaopen_table },
46 { LUA_STRLIBNAME, luaopen_string },
47 { LUA_MATHLIBNAME, luaopen_math },
48 { LUA_UTF8LIBNAME, luaopen_utf8 },
53 LUALIB_API
void my_luaL_openlibs(lua_State *L) {
56 for (lib = loadedlibs; lib->func; lib++) {
57 luaL_requiref(L, lib->name, lib->func, 1);
67 void Lua::LuaDeleter::operator()(lua_State *lua)
72 void *Lua::luaAlloc(
void *ud,
void *ptr,
size_t osize,
size_t nsize)
74 auto *lua =
reinterpret_cast<Lua *
>(ud);
79 BOOL ret = ::HeapFree(lua->m_heap.get(), 0, ptr);
88 if (nsize >= 0x7FFF8) {
89 debug::writef(L
"[warning] Attempt to allocate %zu bytes", nsize);
93 return ::HeapAlloc(lua->m_heap.get(), 0, nsize);
97 return ::HeapReAlloc(lua->m_heap.get(), 0, ptr, nsize);
102 Lua::Lua(
bool debugEnable,
size_t maxHeapSize,
size_t initHeapSize,
104 m_debugEnable(debugEnable)
108 HANDLE tmpHeap = ::HeapCreate(HeapOption, initHeapSize, maxHeapSize);
110 m_heap.reset(tmpHeap);
112 lua_State *tmpLua = lua_newstate(luaAlloc,
this);
113 if (tmpLua ==
nullptr) {
114 throw std::bad_alloc();
118 m_dbg = std::make_unique<debugger::LuaDebugger>(
119 m_lua.get(), debugEnable, instLimit, maxHeapSize);
123 ::lua_atpanic(m_lua.get(), atpanic);
124 my_luaL_openlibs(m_lua.get());
126 lua_State *L = m_lua.get();
129 lua_setglobal(L,
"print");
132 lua_setglobal(L,
"dofile");
134 lua_setglobal(L,
"loadfile");
136 lua_setglobal(L,
"load");
151 lua_State *L = m_lua.get();
153 lua_setglobal(L,
"trace");
157 lua_setglobal(L,
"print");
162 lua_State *L = m_lua.get();
165 lua_pushlightuserdata(L,
this);
167 lua_setglobal(L,
"sys");
172 lua_State *L = m_lua.get();
174 lua_setglobal(L,
"rand");
179 lua_State *L = m_lua.get();
182 lua_pushlightuserdata(L, app);
184 lua_setglobal(L,
"resource");
189 lua_State *L = m_lua.get();
192 lua_pushlightuserdata(L, app);
194 lua_setglobal(L,
"graph");
199 lua_State *L = m_lua.get();
202 lua_pushlightuserdata(L, app);
204 lua_setglobal(L,
"sound");
209 lua_State *L = m_lua.get();
214 std::string chunkName(
"@");
216 int ret = ::luaL_loadbufferx(L,
217 reinterpret_cast<const char *>(buf.data()), buf.size(),
218 chunkName.c_str(),
"t");
220 throwTrace<LuaError>(
"Load script failed", L);
223 m_dbg->loadDebugInfo(chunkName.c_str(),
224 reinterpret_cast<const char *
>(buf.data()), buf.size());
227 pcallInternal(0, 0, autoBreak);
234 void Lua::pcallInternal(
int narg,
int nret,
bool autoBreak)
236 m_dbg->pcall(narg, nret, autoBreak);
242 std::vector<std::string> luaValueToStrListInternal(
243 lua_State *L,
int ind,
int maxDepth,
244 int depth,
int indent,
char kind,
int kindIndent,
245 std::vector<const void *> visitedTable)
247 std::vector<std::string> result;
249 int tind = lua_absindex(L, ind);
251 int type = lua_type(L, ind);
252 if (type == LUA_TNONE) {
253 throwTrace<std::logic_error>(
"invalid index: " + std::to_string(ind));
255 const char *typestr = lua_typename(L, type);
257 lua_pushvalue(L, ind);
258 const char *valstr = lua_tostring(L, -1);
259 valstr = (valstr == NULL) ?
"" : valstr;
263 if (type == LUA_TBOOLEAN) {
264 valstr = lua_toboolean(L, ind) ?
"true" :
"false";
269 for (
int i = 0; i < indent; i++) {
270 if (i == kindIndent) {
281 result.emplace_back(std::move(str));
284 if (type == LUA_TTABLE && depth < maxDepth) {
288 lua_getglobal(L,
"pairs");
289 lua_pushvalue(L, tind);
294 int nextInd = lua_absindex(L, -3);
295 int tableInd = lua_absindex(L, -2);
299 lua_pushvalue(L, nextInd);
300 lua_pushvalue(L, tableInd);
301 lua_pushvalue(L, -3);
307 if (lua_isnil(L, -1)) {
312 auto visited = [&visitedTable, L](
int ind) ->
bool {
313 return std::find(visitedTable.cbegin(), visitedTable.cend(),
314 lua_topointer(L, -2)) != visitedTable.cend();
318 visitedTable.emplace_back(lua_topointer(L, -2));
319 auto key = luaValueToStrListInternal(
320 L, -2, maxDepth, depth + 1, indent + 4,
'K', indent, visitedTable);
321 result.insert(result.end(), key.begin(), key.end());
322 visitedTable.pop_back();
325 visitedTable.emplace_back(lua_topointer(L, -1));
326 auto val = luaValueToStrListInternal(
327 L, -1, maxDepth, depth + 1, indent + 4,
'V', indent, visitedTable);
328 result.insert(result.end(), val.begin(), val.end());
329 visitedTable.pop_back();
347 lua_State *L,
int ind,
int maxDepth)
349 return luaValueToStrListInternal(L, ind, maxDepth, 0, 0,
'\0', 0,
350 std::vector<const void *>());
std::unique_ptr< char[]> wc2utf8(const wchar_t *in)
Wide char to UTF-8.
void loadFile(const wchar_t *fileName, bool autoBreak, bool prot=true)
Load script file and eval it.
LuaError(const std::string &msg, lua_State *L)
const luaL_Reg graph_RegList[]
void writef(const wchar_t *fmt,...) noexcept
Write debug message using format string like printf.
std::vector< uint8_t > loadFile(const wchar_t *fileName)
Load file from abstract file system.
lua_State * getLuaState() const
Returns lua_State which this object has.
const luaL_Reg sys_RegList[]
const luaL_Reg rand_RegList[]
void loadSoundLib(framework::Application *app)
void writeLine(const wchar_t *str=L"") noexcept
Write debug string and new line.
Lua(bool debugEnable, size_t maxHeapSize, size_t initHeapSize=1024 *1024, int instLimit=10 *10000)
Create new lua_State and open standard libs.
void loadGraphLib(framework::Application *app)
const luaL_Reg resource_RegList[]
std::vector< uint8_t > Bytes
File byte sequence. Vector of uint8_t.
char msg[LINE_DATA_SIZE-sizeof(LARGE_INTEGER)-sizeof(uint32_t)]
const luaL_Reg trace_RegList[]
~Lua()
Destruct lua_State.
void checkWin32Result(bool cond, const std::string &msg)
static int write(lua_State *L)
デバッグ出力する。
const luaL_Reg sound_RegList[]
void loadResourceLib(framework::Application *app)
User application base, which manages a window and DirectX objects.
std::vector< std::string > luaValueToStrList(lua_State *L, int ind, int maxDepth)