Added two new stack disciplines to LuaStack
This commit is contained in:
@@ -1,20 +1,20 @@
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// LUASTACK
|
||||
// LuaOldStack
|
||||
//
|
||||
// The standard lua C API asks you to work with a stack machine. You're supposed
|
||||
// to manually push and pop values on the lua stack. I find this difficult, I
|
||||
// find it hard to remember what stack position contains what value.
|
||||
//
|
||||
// To make it easier, I've created this module, "LuaStack." This module
|
||||
// To make it easier, I've created this module, "LuaOldStack." This module
|
||||
// creates the illusion that you're working with local variables that contain
|
||||
// lua values.
|
||||
//
|
||||
// Of course, this is all using the lua stack under the covers. Lua
|
||||
// local variables are actually just lua stack addresses. But that's
|
||||
// all kept fairly well hidden. When you use Lua local variables, and
|
||||
// the accessors inside class LuaStack, it appears that you're
|
||||
// the accessors inside class LuaOldStack, it appears that you're
|
||||
// manipulating data using local variables instead of using a stack.
|
||||
// For people like me, that's easier to think about.
|
||||
//
|
||||
@@ -31,7 +31,7 @@
|
||||
// LuaVar loc1, loc2, loc3; // Declare local variables for other purposes.
|
||||
//
|
||||
// // Assign every local var a stack index.
|
||||
// LuaStack LS(L, arg1, arg2, ret1, loc1, loc2, loc3);
|
||||
// LuaOldStack LS(L, arg1, arg2, ret1, loc1, loc2, loc3);
|
||||
//
|
||||
// // manipulate the data in the lua local variables...
|
||||
// LS.rawget(loc1, arg1, arg2);
|
||||
@@ -39,15 +39,15 @@
|
||||
// }
|
||||
//
|
||||
// Class LuaArg, LuaRet, and LuaVar are all lua local variables.
|
||||
// The luastack constructor assigns each one of them a position on
|
||||
// The LuaOldStack constructor assigns each one of them a position on
|
||||
// the lua stack. It also makes sure that the arguments are in
|
||||
// the LuaArg variables, and it makes sure that the LuaRet values
|
||||
// are the only thing left on the stack at return time.
|
||||
//
|
||||
// Class LuaStack provides a complete catalog of accessors
|
||||
// Class LuaOldStack provides a complete catalog of accessors
|
||||
// like 'rawget' - roughly speaking, it provides equivalents to
|
||||
// every major accessor in the lua API. However, the accessors
|
||||
// provided by LuaStack take input and output from lua locals, not
|
||||
// provided by LuaOldStack take input and output from lua locals, not
|
||||
// from the stack. For example, consider this:
|
||||
//
|
||||
// LS.rawget(value, tab, key);
|
||||
@@ -56,20 +56,20 @@
|
||||
// This does a rawget on 'table', with the specified 'key', and
|
||||
// stores the result in 'value'. Nothing is added to or removed
|
||||
// from the lua stack. In general, none of the accessors in class
|
||||
// LuaStack add anything to the stack, or pop anything from the
|
||||
// LuaOldStack add anything to the stack, or pop anything from the
|
||||
// stack.
|
||||
//
|
||||
// Class LuaStack can also do automatic type conversions. For
|
||||
// Class LuaOldStack can also do automatic type conversions. For
|
||||
// example, suppose you do this:
|
||||
//
|
||||
// LS.rawget(value, tab, key);
|
||||
//
|
||||
// Nominally, you would expect value, tab, and key to be lua local
|
||||
// variables. But if you pass a eng::string for key, then LuaStack will
|
||||
// automatically convert it. In general, class LuaStack can
|
||||
// variables. But if you pass a eng::string for key, then LuaOldStack will
|
||||
// automatically convert it. In general, class LuaOldStack can
|
||||
// convert lua_Integer, lua_Number, eng::string, bool, and LuaNil.
|
||||
//
|
||||
// On output, LuaStack can convert lua_Integers, lua_Numbers, and
|
||||
// On output, LuaOldStack can convert lua_Integers, lua_Numbers, and
|
||||
// eng::strings. In this case, strict type checking is done. If
|
||||
// there is a type mismatch, a lua error is thrown.
|
||||
//
|
||||
@@ -90,20 +90,20 @@
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// LuaStack type checking
|
||||
// LuaOldStack type checking
|
||||
//
|
||||
// LuaStack contains accessors for type checking. These include:
|
||||
// LuaOldStack contains accessors for type checking. These include:
|
||||
//
|
||||
// bool LuaStack::isnumber(LuaSlot s)
|
||||
// bool LuaStack::isinteger(LuaSlot s)
|
||||
// bool LuaStack::isstring(LuaSlot s)
|
||||
// bool LuaOldStack::isnumber(LuaSlot s)
|
||||
// bool LuaOldStack::isinteger(LuaSlot s)
|
||||
// bool LuaOldStack::isstring(LuaSlot s)
|
||||
// etc...
|
||||
//
|
||||
// And it also contains operations that throw errors:
|
||||
//
|
||||
// void LuaStack::checknumber(LuaSlot s)
|
||||
// void LuaStack::checkinteger(LuaSlot s)
|
||||
// void LuaStack::checkstring(LuaSlot s)
|
||||
// void LuaOldStack::checknumber(LuaSlot s)
|
||||
// void LuaOldStack::checkinteger(LuaSlot s)
|
||||
// void LuaOldStack::checkstring(LuaSlot s)
|
||||
// etc...
|
||||
//
|
||||
// These are different from the lua builtins in that they are strict.
|
||||
@@ -112,10 +112,10 @@
|
||||
//
|
||||
// These functions do checking and also conversion at the same time:
|
||||
//
|
||||
// lua_Integer LuaStack::ckinteger(LuaSlot s)
|
||||
// lua_Number LuaStack::cknumber(LuaSlot s)
|
||||
// eng::string LuaStack::ckstring(LuaSlot s)
|
||||
// lua_State *LuaStack::ckthread(LuaSlot s)
|
||||
// lua_Integer LuaOldStack::ckinteger(LuaSlot s)
|
||||
// lua_Number LuaOldStack::cknumber(LuaSlot s)
|
||||
// eng::string LuaOldStack::ckstring(LuaSlot s)
|
||||
// lua_State *LuaOldStack::ckthread(LuaSlot s)
|
||||
//
|
||||
// Like the other operations, they are strict.
|
||||
//
|
||||
@@ -151,8 +151,8 @@
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef LUASTACK_HPP
|
||||
#define LUASTACK_HPP
|
||||
#ifndef LuaOldStack_HPP
|
||||
#define LuaOldStack_HPP
|
||||
|
||||
#include "wrap-string.hpp"
|
||||
#include "wrap-set.hpp"
|
||||
@@ -180,7 +180,7 @@ public:
|
||||
}
|
||||
|
||||
friend class LuaCoreStack;
|
||||
friend class LuaStack;
|
||||
friend class LuaOldStack;
|
||||
friend class LuaExtStack;
|
||||
};
|
||||
|
||||
@@ -476,7 +476,7 @@ public:
|
||||
static bool int64_storable(int64_t v) { return (v <= MAXINT) && (v >= -MAXINT); }
|
||||
};
|
||||
|
||||
class LuaStack : public LuaCoreStack {
|
||||
class LuaOldStack : public LuaCoreStack {
|
||||
private:
|
||||
int narg_;
|
||||
int ngap_;
|
||||
@@ -549,7 +549,7 @@ private:
|
||||
|
||||
public:
|
||||
template<class... SS>
|
||||
LuaStack(lua_State *L, SS & ... stackslots) {
|
||||
LuaOldStack(lua_State *L, SS & ... stackslots) {
|
||||
L_ = L;
|
||||
count_slots<0, 0, 0>(stackslots...);
|
||||
if (lua_gettop(L) < narg_) {
|
||||
@@ -573,10 +573,140 @@ public:
|
||||
return nret_;
|
||||
}
|
||||
|
||||
~LuaStack() {};
|
||||
~LuaOldStack() {};
|
||||
};
|
||||
|
||||
|
||||
class LuaDefStack : public LuaCoreStack {
|
||||
private:
|
||||
int nret_;
|
||||
int narg_;
|
||||
int nvar_;
|
||||
|
||||
template<class... SS>
|
||||
void assign_slots(int retp, int argp, int varp, LuaRet &v, SS & ... stackslots) {
|
||||
v.index_ = retp;
|
||||
assign_slots(retp+1, argp, varp, stackslots...);
|
||||
}
|
||||
template<class... SS>
|
||||
void assign_slots(int retp, int argp, int varp, LuaArg &v, SS & ... stackslots) {
|
||||
v.index_ = argp;
|
||||
assign_slots(retp, argp + 1, varp, stackslots...);
|
||||
}
|
||||
template<class... SS>
|
||||
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<int NRET, int NARG, int NVAR, class... SS>
|
||||
void count_slots(LuaRet &v, SS & ... stackslots)
|
||||
{
|
||||
count_slots<NRET+1, NARG, NVAR>(stackslots...);
|
||||
}
|
||||
template<int NRET, int NARG, int NVAR, class... SS>
|
||||
void count_slots(LuaArg &v, SS & ... stackslots)
|
||||
{
|
||||
count_slots<NRET, NARG+1, NVAR>(stackslots...);
|
||||
}
|
||||
template<int NRET, int NARG, int NVAR, class... SS>
|
||||
void count_slots(LuaVar &v, SS & ... stackslots)
|
||||
{
|
||||
count_slots<NRET, NARG, NVAR+1>(stackslots...);
|
||||
}
|
||||
template<int NRET, int NARG, int NVAR>
|
||||
void count_slots() {
|
||||
nret_ = NRET;
|
||||
narg_ = NARG;
|
||||
nvar_ = NVAR;
|
||||
}
|
||||
|
||||
public:
|
||||
template<class... SS>
|
||||
LuaDefStack(lua_State *L, SS & ... stackslots) {
|
||||
L_ = L;
|
||||
count_slots<0, 0, 0>(stackslots...);
|
||||
if (lua_gettop(L_) != narg_) {
|
||||
luaL_error(L_, "function expects exactly %d arguments", narg_);
|
||||
}
|
||||
int tot = narg_ + nvar_ + nret_;
|
||||
lua_checkstack(L, tot + 20);
|
||||
for (int i = 0; i < nret_; i ++) {
|
||||
lua_pushnil(L_);
|
||||
lua_insert(L_, i + 1);
|
||||
}
|
||||
for (int i = 0; i < nvar_; i++) {
|
||||
lua_pushnil(L_);
|
||||
}
|
||||
assign_slots(1, 1 + nret_, 1 + nret_ + narg_, stackslots...);
|
||||
}
|
||||
|
||||
~LuaDefStack() {
|
||||
if (!lua_isthrowing(L_)) {
|
||||
lua_settop(L_, nret_);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
class LuaExtStack : public LuaCoreStack {
|
||||
private:
|
||||
int oldtop_;
|
||||
int nvar_;
|
||||
|
||||
template<class... SS>
|
||||
void assign_slots(int varp, LuaVar &v, SS & ... stackslots) {
|
||||
v.index_ = varp;
|
||||
assign_slots(varp+1, stackslots...);
|
||||
}
|
||||
void assign_slots(int varp) {}
|
||||
|
||||
template<int NVAR, class... SS>
|
||||
void count_slots(LuaVar &v, SS & ... stackslots)
|
||||
{
|
||||
count_slots<NVAR+1>(stackslots...);
|
||||
}
|
||||
template<int NVAR>
|
||||
void count_slots() {
|
||||
nvar_ = NVAR;
|
||||
}
|
||||
|
||||
public:
|
||||
template<class... SS>
|
||||
LuaExtStack(lua_State *L, SS & ... stackslots) {
|
||||
L_ = L;
|
||||
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...);
|
||||
}
|
||||
|
||||
template<class... SS>
|
||||
LuaExtStack(const LuaCoreStack &LS0, SS & ... stackslots) {
|
||||
L_ = 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() {
|
||||
if (!lua_isthrowing(L_)) {
|
||||
lua_settop(L_, oldtop_);
|
||||
}
|
||||
}
|
||||
|
||||
void forcediscard() {
|
||||
lua_settop(L_, oldtop_);
|
||||
}
|
||||
};
|
||||
|
||||
// This is a helper class to help parse tables full of keywords.
|
||||
class LuaKeywordParser {
|
||||
struct cmp_char {
|
||||
@@ -595,7 +725,7 @@ public:
|
||||
// If the slot is not a table, sets the not_table
|
||||
// flag and creates a dummy table in the slot.
|
||||
LuaKeywordParser(lua_State *L, int slot);
|
||||
LuaKeywordParser(const LuaStack &LS, LuaSlot slot) : LuaKeywordParser(LS.state(), slot.index()) {}
|
||||
LuaKeywordParser(const LuaCoreStack &LS, LuaSlot slot) : LuaKeywordParser(LS.state(), slot.index()) {}
|
||||
|
||||
// Fetch a value from the table. This never throws.
|
||||
// Return true if the value is non-nil.
|
||||
@@ -682,4 +812,4 @@ public:
|
||||
#define LuaAssert(L, x) if (!(x)) { luaL_error((L), "Assert failed: %s (file %s line %d)", LuaStringify(x), __FILE__, __LINE__); }
|
||||
#define LuaAssertStrEq(L, x, y) { eng::string _s1_(x); eng::string _s2_(y); if (_s1_ != _s2_) luaL_error((L), "Assert failed: value=%s (file %s line %d)", _s1_.c_str(), __FILE__, __LINE__); }
|
||||
|
||||
#endif // LUASTACK_HPP
|
||||
#endif // LuaOldStack_HPP
|
||||
|
||||
Reference in New Issue
Block a user