diff --git a/luprex/cpp/core/luastack.hpp b/luprex/cpp/core/luastack.hpp index 1cb3ab44..c64ac676 100644 --- a/luprex/cpp/core/luastack.hpp +++ b/luprex/cpp/core/luastack.hpp @@ -206,6 +206,41 @@ public: friend class LuaDefStack; }; +struct LuaArgCounts { + int nret; + int narg; + int nvar; + int nextra; + constexpr LuaArgCounts(int nr, int na, int nv, int ne) : nret(nr), narg(na), nvar(nv), nextra(ne) {} + constexpr LuaArgCounts operator +(LuaArgCounts b) const { + return LuaArgCounts(nret + b.nret, narg + b.narg, nvar + b.nvar, nextra + b.nextra); + } +}; + + +template +struct LuaCountArgs; +template<> +struct LuaCountArgs<> { + static constexpr LuaArgCounts value = LuaArgCounts(0,0,0,0); +}; +template +struct LuaCountArgs { + static constexpr LuaArgCounts value = LuaArgCounts(1, 0, 0, 0) + LuaCountArgs::value; +}; +template +struct LuaCountArgs { + static constexpr LuaArgCounts value = LuaArgCounts(0, 1, 0, 0) + LuaCountArgs::value; +}; +template +struct LuaCountArgs { + static constexpr LuaArgCounts value = LuaArgCounts(0, 0, 1, 0) + LuaCountArgs::value; +}; +template +struct LuaCountArgs { + static constexpr LuaArgCounts value = LuaArgCounts(0, 0, 0, 1) + LuaCountArgs::value; +}; + class LuaNilMarker {}; extern LuaNilMarker LuaNil; @@ -291,51 +326,8 @@ protected: lua_State *L_; protected: - struct Counts { - int nret; - int narg; - int nvar; - int nextra; - constexpr Counts(int nr, int na, int nv, int ne) : nret(nr), narg(na), nvar(nv), nextra(ne) {} - constexpr Counts(Counts a, Counts b) - : nret(a.nret+b.nret), narg(a.narg+b.narg), nvar(a.nvar+b.nvar), nextra(a.nextra+b.nextra) {} - }; - template - constexpr static Counts count_slots(LuaRet &v, SS && ... stackslots) - { - return Counts(Counts(1, 0, 0, 0), count_slots(stackslots...)); - } - template - constexpr static Counts count_slots(LuaArg &v, SS && ... stackslots) - { - return Counts(Counts(0, 1, 0, 0), count_slots(stackslots...)); - } - template - constexpr static Counts count_slots(LuaVar &v, SS && ... stackslots) - { - return Counts(Counts(0, 0, 1, 0), count_slots(stackslots...)); - } - template - constexpr static Counts count_slots(LuaExtraArgs &v, SS && ... stackslots) - { - return Counts(Counts(0, 0, 0, 1), count_slots(stackslots...)); - } - constexpr static Counts count_slots() { - return Counts(0, 0, 0, 0); - } - - - template - constexpr static int count_vars(LuaVar &v, SS && ... stackslots) - { - return 1 + count_vars(stackslots...); - } - constexpr static int count_vars() { - return 0; - } - - private: +private: // Push any value on the stack, by type. void push_any_value(LuaNewTableMarker s) const { lua_newtable(L_); } void push_any_value(LuaNilMarker s) const { lua_pushnil(L_); } @@ -599,7 +591,7 @@ private: public: template inline LuaDefStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - Counts counts = count_slots(stackslots...); + constexpr LuaArgCounts counts = LuaCountArgs::value; int nargs = lua_gettop(L); if (counts.nextra == 0) { if (nargs != counts.narg) { @@ -657,10 +649,13 @@ private: public: template LuaExtStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - int nvars = count_vars(stackslots...); - lua_checkstack(L_, nvars + 20); + constexpr LuaArgCounts counts = LuaCountArgs::value; + static_assert(counts.narg == 0, "LuaExtStack only allows LuaVar, not LuaArg"); + static_assert(counts.nret == 0, "LuaExtStack only allows LuaVar, not LuaRet"); + static_assert(counts.nextra == 0, "LuaExtStack only allows LuaVar, not LuaExtraArgs"); + lua_checkstack(L_, counts.nvar + 20); oldtop_ = lua_gettop(L_); - for (int i = 0; i < nvars; i++) { + for (int i = 0; i < counts.nvar; i++) { lua_pushnil(L_); } assign_slots(oldtop_ + 1, stackslots...);