From b2b7e457570e87c87a3c158271ae3bffd823987c Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 11 Jan 2014 22:51:10 +0100 Subject: [PATCH] Removed internal methods from public cLuaState interface. PushFunction(), CallFunction() and GetReturn() are not to be called independently, but rather only by using the Call() templated overrides. Push() needs to be left in the public part, it is used for pushing results in the ManualBindings. Preparation for #418. --- src/Bindings/LuaState.cpp | 26 ++++++--- src/Bindings/LuaState.h | 98 ++++++++++++++++++++------------- src/Bindings/ManualBindings.cpp | 98 +++++++++------------------------ 3 files changed, 103 insertions(+), 119 deletions(-) diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index 83351591c..1dd2b4dd8 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -264,27 +264,26 @@ bool cLuaState::PushFunction(int a_FnRef) -bool cLuaState::PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName) +bool cLuaState::PushFunction(const cTableRef & a_TableRef) { ASSERT(IsValid()); ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack - - lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_TableRef); // Get the table ref + + lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_TableRef.GetTableRef()); // Get the table ref if (!lua_istable(m_LuaState, -1)) { // Not a table, bail out lua_pop(m_LuaState, 1); return false; } - lua_getfield(m_LuaState, -1, a_FnName); + lua_getfield(m_LuaState, -1, a_TableRef.GetFnName()); if (lua_isnil(m_LuaState, -1) || !lua_isfunction(m_LuaState, -1)) { // Not a valid function, bail out lua_pop(m_LuaState, 2); return false; } - lua_remove(m_LuaState, -2); // Remove the table ref from the stack - m_CurrentFunctionName = ""; + Printf(m_CurrentFunctionName, "", a_TableRef.GetFnName()); m_NumCurrentFunctionArgs = 0; return true; } @@ -963,16 +962,25 @@ bool cLuaState::ReportErrors(lua_State * a_LuaState, int a_Status) void cLuaState::LogStackTrace(void) +{ + LogStackTrace(m_LuaState); +} + + + + + +void cLuaState::LogStackTrace(lua_State * a_LuaState) { LOGWARNING("Stack trace:"); lua_Debug entry; int depth = 0; - while (lua_getstack(m_LuaState, depth, &entry)) + while (lua_getstack(a_LuaState, depth, &entry)) { - int status = lua_getinfo(m_LuaState, "Sln", &entry); + int status = lua_getinfo(a_LuaState, "Sln", &entry); assert(status); - LOGWARNING(" %s(%d): %s", entry.short_src, entry.currentline, entry.name ? entry.name : "?"); + LOGWARNING(" %s(%d): %s", entry.short_src, entry.currentline, entry.name ? entry.name : "(no name)"); depth++; } LOGWARNING("Stack trace end"); diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index 796559b6f..c77dbeb7f 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -85,6 +85,23 @@ public: } ; + /** Used for calling functions stored in a reference-stored table */ + class cTableRef + { + int m_TableRef; + const char * m_FnName; + public: + cTableRef(int a_TableRef, const char * a_FnName) : + m_TableRef(a_TableRef), + m_FnName(a_FnName) + { + } + + int GetTableRef(void) const { return m_TableRef; } + const char * GetFnName(void) const { return m_FnName; } + } ; + + /// A dummy class that's used only to delimit function args from return values for cLuaState::Call() class cRet { @@ -133,24 +150,6 @@ public: /// Returns true if a_FunctionName is a valid Lua function that can be called bool HasFunction(const char * a_FunctionName); - /** Pushes the function of the specified name onto the stack. - Returns true if successful. Logs a warning on failure (incl. m_SubsystemName) - */ - bool PushFunction(const char * a_FunctionName); - - /** Pushes a function that has been saved into the global registry, identified by a_FnRef. - Returns true if successful. Logs a warning on failure - */ - bool PushFunction(int a_FnRef); - - /** Pushes a function that is stored in a table ref. - Returns true if successful, false on failure. Doesn't log failure. - */ - bool PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName); - - /// Pushes a usertype of the specified class type onto the stack - void PushUserType(void * a_Object, const char * a_Type); - // Push a value onto the stack void Push(const AString & a_String); void Push(const AStringVector & a_Vector); @@ -183,7 +182,7 @@ public: void Push(void * a_Ptr); void Push(cHopperEntity * a_Hopper); void Push(cBlockEntity * a_BlockEntity); - + /// Call any 0-param 0-return Lua function in a single line: template bool Call(FnT a_FnName) @@ -802,25 +801,6 @@ public: } - /// Retrieve value returned at a_StackPos, if it is a valid bool. If not, a_ReturnedVal is unchanged - void GetReturn(int a_StackPos, bool & a_ReturnedVal); - - /// Retrieve value returned at a_StackPos, if it is a valid string. If not, a_ReturnedVal is unchanged - void GetReturn(int a_StackPos, AString & a_ReturnedVal); - - /// Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged - void GetReturn(int a_StackPos, int & a_ReturnedVal); - - /// Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged - void GetReturn(int a_StackPos, double & a_ReturnedVal); - - /** - Calls the function that has been pushed onto the stack by PushFunction(), - with arguments pushed by PushXXX(). - Returns true if successful, logs a warning on failure. - */ - bool CallFunction(int a_NumReturnValues); - /// Returns true if the specified parameters on the stack are of the specified usertable type; also logs warning if not. Used for static functions bool CheckParamUserTable(int a_StartParam, const char * a_UserTable, int a_EndParam = -1); @@ -848,6 +828,9 @@ public: /// Logs all items in the current stack trace to the server console void LogStackTrace(void); + /// Logs all items in the current stack trace to the server console + static void LogStackTrace(lua_State * a_LuaState); + /// Returns the type of the item on the specified position in the stack AString GetTypeText(int a_StackPos); @@ -867,6 +850,45 @@ protected: /// Number of arguments currently pushed (for the Push / Call chain) int m_NumCurrentFunctionArgs; + + + /** Pushes the function of the specified name onto the stack. + Returns true if successful. Logs a warning on failure (incl. m_SubsystemName) + */ + bool PushFunction(const char * a_FunctionName); + + /** Pushes a function that has been saved into the global registry, identified by a_FnRef. + Returns true if successful. Logs a warning on failure + */ + bool PushFunction(int a_FnRef); + + /** Pushes a function that is stored in a referenced table by name + Returns true if successful. Logs a warning on failure + */ + bool PushFunction(const cTableRef & a_TableRef); + + /// Pushes a usertype of the specified class type onto the stack + void PushUserType(void * a_Object, const char * a_Type); + + /// Retrieve value returned at a_StackPos, if it is a valid bool. If not, a_ReturnedVal is unchanged + void GetReturn(int a_StackPos, bool & a_ReturnedVal); + + /// Retrieve value returned at a_StackPos, if it is a valid string. If not, a_ReturnedVal is unchanged + void GetReturn(int a_StackPos, AString & a_ReturnedVal); + + /// Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged + void GetReturn(int a_StackPos, int & a_ReturnedVal); + + /// Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged + void GetReturn(int a_StackPos, double & a_ReturnedVal); + + /** + Calls the function that has been pushed onto the stack by PushFunction(), + with arguments pushed by PushXXX(). + Returns true if successful, logs a warning on failure. + */ + bool CallFunction(int a_NumReturnValues); + } ; diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index f0dd00300..a9368f613 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -1980,118 +1980,72 @@ public: virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override { - if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlock")) + bool res = false; + if (!m_LuaState.Call( + cLuaState::cTableRef(m_TableRef, "OnNextBlock"), + a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_EntryFace, + cLuaState::Return, res + )) { // No such function in the table, skip the callback return false; } - m_LuaState.Push(a_BlockX); - m_LuaState.Push(a_BlockY); - m_LuaState.Push(a_BlockZ); - m_LuaState.Push(a_BlockType); - m_LuaState.Push(a_BlockMeta); - m_LuaState.Push(a_EntryFace); - if (!m_LuaState.CallFunction(1)) - { - return false; - } - bool res = false; - if (lua_isboolean(m_LuaState, -1)) - { - res = (lua_toboolean(m_LuaState, -1) != 0); - } - lua_pop(m_LuaState, 1); return res; } virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) override { - if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlockNoData")) + bool res = false; + if (!m_LuaState.Call( + cLuaState::cTableRef(m_TableRef, "OnNextBlockNoData"), + a_BlockX, a_BlockY, a_BlockZ, a_EntryFace, + cLuaState::Return, res + )) { // No such function in the table, skip the callback return false; } - m_LuaState.Push(a_BlockX); - m_LuaState.Push(a_BlockY); - m_LuaState.Push(a_BlockZ); - m_LuaState.Push(a_EntryFace); - if (!m_LuaState.CallFunction(1)) - { - return false; - } - bool res = false; - if (lua_isboolean(m_LuaState, -1)) - { - res = (lua_toboolean(m_LuaState, -1) != 0); - } - lua_pop(m_LuaState, 1); return res; } virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override { - if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnOutOfWorld")) + bool res = false; + if (!m_LuaState.Call( + cLuaState::cTableRef(m_TableRef, "OnOutOfWorld"), + a_BlockX, a_BlockY, a_BlockZ, + cLuaState::Return, res + )) { // No such function in the table, skip the callback return false; } - m_LuaState.Push(a_BlockX); - m_LuaState.Push(a_BlockY); - m_LuaState.Push(a_BlockZ); - if (!m_LuaState.CallFunction(1)) - { - return false; - } - bool res = false; - if (lua_isboolean(m_LuaState, -1)) - { - res = (lua_toboolean(m_LuaState, -1) != 0); - } - lua_pop(m_LuaState, 1); return res; } virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override { - if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnIntoWorld")) + bool res = false; + if (!m_LuaState.Call( + cLuaState::cTableRef(m_TableRef, "OnIntoWorld"), + a_BlockX, a_BlockY, a_BlockZ, + cLuaState::Return, res + )) { // No such function in the table, skip the callback return false; } - m_LuaState.Push(a_BlockX); - m_LuaState.Push(a_BlockY); - m_LuaState.Push(a_BlockZ); - if (!m_LuaState.CallFunction(1)) - { - return false; - } - bool res = false; - if (lua_isboolean(m_LuaState, -1)) - { - res = (lua_toboolean(m_LuaState, -1) != 0); - } - lua_pop(m_LuaState, 1); return res; } virtual void OnNoMoreHits(void) override { - if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNoMoreHits")) - { - // No such function in the table, skip the callback - return; - } - m_LuaState.CallFunction(0); + m_LuaState.Call(cLuaState::cTableRef(m_TableRef, "OnNoMoreHits")); } virtual void OnNoChunk(void) override { - if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNoChunk")) - { - // No such function in the table, skip the callback - return; - } - m_LuaState.CallFunction(0); + m_LuaState.Call(cLuaState::cTableRef(m_TableRef, "OnNoChunk")); } protected: