diff --git a/luprex/cpp/core/luastack.hpp b/luprex/cpp/core/luastack.hpp index 255cf21f..6edbc988 100644 --- a/luprex/cpp/core/luastack.hpp +++ b/luprex/cpp/core/luastack.hpp @@ -146,6 +146,7 @@ #include "wrap-string.hpp" #include "wrap-set.hpp" #include +#include #include "lua.h" #include "lauxlib.h" @@ -277,6 +278,34 @@ class LuaCoreStack : public eng::nevernew { protected: lua_State *L_; +protected: + struct Counts { + int nret; + int narg; + int nvar; + constexpr Counts(int r, int a, int v) : nret(r), narg(a), nvar(v) {} + }; + + template + constexpr static Counts count_slots(LuaRet &v, SS & ... stackslots) + { + return count_slots(stackslots...); + } + template + constexpr static Counts count_slots(LuaArg &v, SS & ... stackslots) + { + return count_slots(stackslots...); + } + template + constexpr static Counts count_slots(LuaVar &v, SS & ... stackslots) + { + return count_slots(stackslots...); + } + template + constexpr static Counts count_slots() { + return Counts(NRET, NARG, NVAR); + } + private: // Push any value on the stack, by type. void push_any_value(LuaNewTableMarker s) const { lua_newtable(L_); } @@ -529,23 +558,23 @@ private: void assign_slots(int argp, int varp, int retp) {} template - void count_slots(LuaArg &v, SS & ... stackslots) + void count_slotsx(LuaArg &v, SS & ... stackslots) { - count_slots(stackslots...); + count_slotsx(stackslots...); } template - void count_slots(LuaVar &v, SS & ... stackslots) + void count_slotsx(LuaVar &v, SS & ... stackslots) { - count_slots(stackslots...); + count_slotsx(stackslots...); } template - void count_slots(LuaRet &v, SS & ... stackslots) + void count_slotsx(LuaRet &v, SS & ... stackslots) { - count_slots(stackslots...); + count_slotsx(stackslots...); } template - void count_slots() { + void count_slotsx() { narg_ = NARG; nret_ = NRET; nvar_ = NVAR; @@ -565,7 +594,7 @@ private: public: template LuaOldStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - count_slots<0, 0, 0>(stackslots...); + count_slotsx<0, 0, 0>(stackslots...); if (lua_gettop(L) < narg_) { luaL_error(L, "not enough arguments to function"); } @@ -621,65 +650,42 @@ public: class LuaDefStack : public LuaCoreStack { private: int nret_; - int narg_; - int nvar_; - template - void assign_slots(int retp, int argp, int varp, LuaRet &v, SS & ... stackslots) { - v.index_ = retp; - assign_slots(retp+1, argp, varp, stackslots...); + template + void assign_slots(LuaRet &v, SS & ... stackslots) { + v.index_ = RETP; + assign_slots(stackslots...); } - template - void assign_slots(int retp, int argp, int varp, LuaArg &v, SS & ... stackslots) { - v.index_ = argp; - assign_slots(retp, argp + 1, varp, stackslots...); + template + void assign_slots(LuaArg &v, SS & ... stackslots) { + v.index_ = ARGP; + assign_slots(stackslots...); } - template - void assign_slots(int retp, int argp, int varp, LuaVar &v, SS & ... stackslots) { - v.index_ = varp; - assign_slots(retp, argp, varp+1, stackslots...); - } - void assign_slots(int retp, int argp, int varp) {} - - template - void count_slots(LuaRet &v, SS & ... stackslots) - { - count_slots(stackslots...); - } - template - void count_slots(LuaArg &v, SS & ... stackslots) - { - count_slots(stackslots...); - } - template - void count_slots(LuaVar &v, SS & ... stackslots) - { - count_slots(stackslots...); + template + void assign_slots(LuaVar &v, SS & ... stackslots) { + v.index_ = VARP; + assign_slots(stackslots...); } template - void count_slots() { - nret_ = NRET; - narg_ = NARG; - nvar_ = NVAR; - } + void assign_slots() {} public: template - LuaDefStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - count_slots<0, 0, 0>(stackslots...); - if (lua_gettop(L_) != narg_) { - luaL_error(L_, "function expects exactly %d arguments", narg_); + inline LuaDefStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { + constexpr Counts counts = count_slots<0, 0, 0>(stackslots...); + if (lua_gettop(L_) != counts.narg) { + luaL_error(L_, "function expects exactly %d arguments", counts.narg); } - int tot = narg_ + nvar_ + nret_; - lua_checkstack(L, tot + 20); - for (int i = 0; i < nret_; i ++) { + lua_checkstack(L, counts.narg + counts.nvar + counts.nret + 20); + for (int i = 0; i < counts.nret; i ++) { lua_pushnil(L_); lua_insert(L_, i + 1); } - for (int i = 0; i < nvar_; i++) { + for (int i = 0; i < counts.nvar; i++) { lua_pushnil(L_); } - assign_slots(1, 1 + nret_, 1 + nret_ + narg_, stackslots...); + assign_slots<1, 1 + counts.nret, 1 + counts.nret + counts.narg>(stackslots...); + nret_ = counts.nret; } int result() { @@ -713,7 +719,6 @@ public: class LuaExtStack : public LuaCoreStack { private: int oldtop_; - int nvar_; template void assign_slots(int varp, LuaVar &v, SS & ... stackslots) { @@ -722,38 +727,22 @@ private: } void assign_slots(int varp) {} - template - void count_slots(LuaVar &v, SS & ... stackslots) - { - count_slots(stackslots...); - } - template - void count_slots() { - nvar_ = NVAR; - } - public: template LuaExtStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - count_slots<0>(stackslots...); - lua_checkstack(L_, nvar_ + 20); + constexpr Counts counts = count_slots<0, 0, 0>(stackslots...); + static_assert(counts.narg == 0, "LuaExtStack doesn't allow LuaArg parameters"); + static_assert(counts.nret == 0, "LuaExtStack doesn't allow LuaRet parameters"); + lua_checkstack(L_, counts.nvar + 20); oldtop_ = lua_gettop(L_); - for (int i = 0; i < nvar_; i++) { + for (int i = 0; i < counts.nvar; i++) { lua_pushnil(L_); } assign_slots(oldtop_ + 1, stackslots...); } template - LuaExtStack(const LuaCoreStack &LS0, SS & ... stackslots) : LuaCoreStack(LS0.state()) { - count_slots<0>(stackslots...); - lua_checkstack(L_, nvar_ + 20); - oldtop_ = lua_gettop(L_); - for (int i = 0; i < nvar_; i++) { - lua_pushnil(L_); - } - assign_slots(oldtop_ + 1, stackslots...); - } + LuaExtStack(const LuaCoreStack &LS0, SS & ... stackslots) : LuaCoreStack(LS0.state(), stackslots...) {} ~LuaExtStack() { if (!lua_isthrowing(L_)) {