Implement LuaExtraArgs
This commit is contained in:
@@ -33,10 +33,17 @@ void LuaSnap::serialize(StreamBuffer *sb) {
|
|||||||
// Lua stack should be empty.
|
// Lua stack should be empty.
|
||||||
assert(lua_gettop(state_) == 0);
|
assert(lua_gettop(state_) == 0);
|
||||||
|
|
||||||
// lua variables that we'll need.
|
// We'll allocate stack slots manually, to ensure
|
||||||
LuaVar key, value;
|
// that the thread serializes as we expect it to.
|
||||||
LuaRet permstable, regcopy;
|
lua_pushnil(state_); // permstable
|
||||||
LuaDefStack LS(state_, permstable, regcopy, key, value);
|
lua_pushnil(state_); // regcopy
|
||||||
|
lua_pushnil(state_); // key
|
||||||
|
lua_pushnil(state_); // value
|
||||||
|
LuaSpecial permstable(1);
|
||||||
|
LuaSpecial regcopy(2);
|
||||||
|
LuaSpecial key(3);
|
||||||
|
LuaSpecial value(4);
|
||||||
|
LuaCoreStack LS(state_);
|
||||||
|
|
||||||
// Construct a copy of the registry table.
|
// Construct a copy of the registry table.
|
||||||
LS.set(regcopy, LuaNewTable);
|
LS.set(regcopy, LuaNewTable);
|
||||||
@@ -62,10 +69,8 @@ void LuaSnap::serialize(StreamBuffer *sb) {
|
|||||||
LS.rawget(permstable, LuaRegistry, "persist");
|
LS.rawget(permstable, LuaRegistry, "persist");
|
||||||
assert(LS.istable(permstable));
|
assert(LS.istable(permstable));
|
||||||
|
|
||||||
// When we call 'LS.result', this should leave the
|
// Remove key and value from stack, leaving permstable and regcopy.
|
||||||
// permstable and the regcopy on the stack.
|
lua_settop(state_, 2);
|
||||||
LS.result();
|
|
||||||
assert(lua_gettop(state_) == 2);
|
|
||||||
|
|
||||||
// Write dummy length, use eris to write data, then overwrite length.
|
// Write dummy length, use eris to write data, then overwrite length.
|
||||||
sb->write_int64(0);
|
sb->write_int64(0);
|
||||||
@@ -88,13 +93,17 @@ void LuaSnap::deserialize(StreamBuffer *sb) {
|
|||||||
lua_pushstring(state_, "unpersist");
|
lua_pushstring(state_, "unpersist");
|
||||||
lua_rawget(state_, LUA_REGISTRYINDEX);
|
lua_rawget(state_, LUA_REGISTRYINDEX);
|
||||||
eris_undump(state_, sb->lua_reader, ud);
|
eris_undump(state_, sb->lua_reader, ud);
|
||||||
|
|
||||||
|
// Set up a stack frame manually. Eris deserialization
|
||||||
|
// should have left permstable and regcopy on the stack.
|
||||||
assert(lua_gettop(state_) == 2);
|
assert(lua_gettop(state_) == 2);
|
||||||
|
LuaSpecial permstable(1);
|
||||||
// Set up a stack frame.
|
LuaSpecial regcopy(2);
|
||||||
LuaArg permstable, regcopy;
|
lua_pushnil(state_);
|
||||||
LuaVar key, value;
|
lua_pushnil(state_);
|
||||||
LuaDefStack LS(state_, permstable, regcopy, key, value);
|
LuaSpecial key(3);
|
||||||
|
LuaSpecial value(4);
|
||||||
|
LuaCoreStack LS(state_);
|
||||||
assert(LS.istable(regcopy));
|
assert(LS.istable(regcopy));
|
||||||
|
|
||||||
// Copy the contents of the snapshot over to the registry.
|
// Copy the contents of the snapshot over to the registry.
|
||||||
@@ -102,8 +111,7 @@ void LuaSnap::deserialize(StreamBuffer *sb) {
|
|||||||
while (LS.next(regcopy, key, value) != 0) {
|
while (LS.next(regcopy, key, value) != 0) {
|
||||||
LS.rawset(LuaRegistry, key, value);
|
LS.rawset(LuaRegistry, key, value);
|
||||||
}
|
}
|
||||||
LS.result();
|
lua_settop(state_, 0);
|
||||||
assert(lua_gettop(state_) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Snapshot and rollback can trivially be implemented on top of serialize and
|
// Snapshot and rollback can trivially be implemented on top of serialize and
|
||||||
|
|||||||
@@ -156,16 +156,18 @@
|
|||||||
class LuaSlot : public eng::nevernew {
|
class LuaSlot : public eng::nevernew {
|
||||||
protected:
|
protected:
|
||||||
int index_;
|
int index_;
|
||||||
|
|
||||||
|
constexpr LuaSlot(int n) : index_(n) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline operator int() const {
|
inline operator int() const {
|
||||||
return index_;
|
return index_;
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
LuaSlot() {
|
|
||||||
index_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index() const {
|
public:
|
||||||
|
constexpr LuaSlot() : index_(0) {}
|
||||||
|
|
||||||
|
inline int index() const {
|
||||||
return index_;
|
return index_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,20 +183,30 @@ class LuaVar : public LuaSlot {};
|
|||||||
|
|
||||||
class LuaSpecial : public LuaSlot {
|
class LuaSpecial : public LuaSlot {
|
||||||
public:
|
public:
|
||||||
LuaSpecial(int n) {
|
constexpr LuaSpecial(int n) : LuaSlot(n) {}
|
||||||
index_ = n;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern LuaSpecial LuaRegistry;
|
extern LuaSpecial LuaRegistry;
|
||||||
|
|
||||||
class LuaUpvalue : public LuaSlot {
|
class LuaExtraArgs {
|
||||||
public:
|
private:
|
||||||
LuaUpvalue(int n) {
|
int index_;
|
||||||
index_ = lua_upvalueindex(n);
|
int size_;
|
||||||
}
|
|
||||||
|
public:
|
||||||
|
LuaExtraArgs() {
|
||||||
|
index_ = 0;
|
||||||
|
size_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaSpecial operator[] (int n) const { return LuaSpecial(index_ + n); }
|
||||||
|
int size() const { return size_; }
|
||||||
|
|
||||||
|
friend class LuaCoreStack;
|
||||||
|
friend class LuaDefStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class LuaNilMarker {};
|
class LuaNilMarker {};
|
||||||
extern LuaNilMarker LuaNil;
|
extern LuaNilMarker LuaNil;
|
||||||
|
|
||||||
@@ -283,27 +295,33 @@ protected:
|
|||||||
int nret;
|
int nret;
|
||||||
int narg;
|
int narg;
|
||||||
int nvar;
|
int nvar;
|
||||||
constexpr Counts(int r, int a, int v) : nret(r), narg(a), nvar(v) {}
|
int nextra;
|
||||||
|
constexpr Counts(int nr, int na, int nv, int ne) : nret(nr), narg(na), nvar(nv), nextra(ne) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int NRET, int NARG, int NVAR, class... SS>
|
template<int NRET, int NARG, int NVAR, int NEXTRA, class... SS>
|
||||||
constexpr static Counts count_slots(LuaRet &v, SS & ... stackslots)
|
constexpr static Counts count_slots(LuaRet &v, SS & ... stackslots)
|
||||||
{
|
{
|
||||||
return count_slots<NRET+1, NARG, NVAR>(stackslots...);
|
return count_slots<NRET+1, NARG, NVAR, NEXTRA>(stackslots...);
|
||||||
}
|
}
|
||||||
template<int NRET, int NARG, int NVAR, class... SS>
|
template<int NRET, int NARG, int NVAR, int NEXTRA, class... SS>
|
||||||
constexpr static Counts count_slots(LuaArg &v, SS & ... stackslots)
|
constexpr static Counts count_slots(LuaArg &v, SS & ... stackslots)
|
||||||
{
|
{
|
||||||
return count_slots<NRET, NARG+1, NVAR>(stackslots...);
|
return count_slots<NRET, NARG+1, NVAR, NEXTRA>(stackslots...);
|
||||||
}
|
}
|
||||||
template<int NRET, int NARG, int NVAR, class... SS>
|
template<int NRET, int NARG, int NVAR, int NEXTRA, class... SS>
|
||||||
constexpr static Counts count_slots(LuaVar &v, SS & ... stackslots)
|
constexpr static Counts count_slots(LuaVar &v, SS & ... stackslots)
|
||||||
{
|
{
|
||||||
return count_slots<NRET, NARG, NVAR+1>(stackslots...);
|
return count_slots<NRET, NARG, NVAR+1, NEXTRA>(stackslots...);
|
||||||
}
|
}
|
||||||
template<int NRET, int NARG, int NVAR>
|
template<int NRET, int NARG, int NVAR, int NEXTRA, class... SS>
|
||||||
|
constexpr static Counts count_slots(LuaExtraArgs &v, SS & ... stackslots)
|
||||||
|
{
|
||||||
|
return count_slots<NRET, NARG, NVAR, NEXTRA+1>(stackslots...);
|
||||||
|
}
|
||||||
|
template<int NRET, int NARG, int NVAR, int NEXTRA>
|
||||||
constexpr static Counts count_slots() {
|
constexpr static Counts count_slots() {
|
||||||
return Counts(NRET, NARG, NVAR);
|
return Counts(NRET, NARG, NVAR, NEXTRA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -649,47 +667,76 @@ public:
|
|||||||
|
|
||||||
class LuaDefStack : public LuaCoreStack {
|
class LuaDefStack : public LuaCoreStack {
|
||||||
private:
|
private:
|
||||||
|
int top_;
|
||||||
int nret_;
|
int nret_;
|
||||||
|
|
||||||
template<int RETP, int ARGP, int VARP, class... SS>
|
template<int RETP, int ARGP, int VARP, int EXTRAP, int EXTRAC, class... SS>
|
||||||
void assign_slots(LuaRet &v, SS & ... stackslots) {
|
void assign_slots(LuaRet &v, SS & ... stackslots) {
|
||||||
v.index_ = RETP;
|
v.index_ = RETP;
|
||||||
assign_slots<RETP+1, ARGP, VARP>(stackslots...);
|
assign_slots<RETP+1, ARGP, VARP, EXTRAP, EXTRAC>(stackslots...);
|
||||||
}
|
}
|
||||||
template<int RETP, int ARGP, int VARP, class... SS>
|
template<int RETP, int ARGP, int VARP, int EXTRAP, int EXTRAC, class... SS>
|
||||||
void assign_slots(LuaArg &v, SS & ... stackslots) {
|
void assign_slots(LuaArg &v, SS & ... stackslots) {
|
||||||
v.index_ = ARGP;
|
v.index_ = ARGP;
|
||||||
assign_slots<RETP, ARGP+1, VARP>(stackslots...);
|
assign_slots<RETP, ARGP+1, VARP, EXTRAP, EXTRAC>(stackslots...);
|
||||||
}
|
}
|
||||||
template<int RETP, int ARGP, int VARP, class... SS>
|
template<int RETP, int ARGP, int VARP, int EXTRAP, int EXTRAC, class... SS>
|
||||||
void assign_slots(LuaVar &v, SS & ... stackslots) {
|
void assign_slots(LuaVar &v, SS & ... stackslots) {
|
||||||
v.index_ = VARP;
|
v.index_ = VARP;
|
||||||
assign_slots<RETP, ARGP, VARP+1>(stackslots...);
|
assign_slots<RETP, ARGP, VARP+1, EXTRAP, EXTRAC>(stackslots...);
|
||||||
}
|
}
|
||||||
template<int NRET, int NARG, int NVAR>
|
template<int RETP, int ARGP, int VARP, int EXTRAP, int EXTRAC, class... SS>
|
||||||
|
void assign_slots(LuaExtraArgs &v, SS & ... stackslots) {
|
||||||
|
v.index_ = EXTRAP;
|
||||||
|
v.size_ = EXTRAC;
|
||||||
|
assign_slots<RETP, ARGP, VARP, EXTRAP, EXTRAC>(stackslots...);
|
||||||
|
}
|
||||||
|
template<int RETP, int ARGP, int VARP, int EXTRAP, int EXTRAC>
|
||||||
void assign_slots() {}
|
void assign_slots() {}
|
||||||
|
|
||||||
|
template<class... SS>
|
||||||
|
void vassign_slots(int retp, int argp, int varp, int extrap, int extrac, LuaRet &v, SS & ... stackslots) {
|
||||||
|
v.index_ = retp;
|
||||||
|
vassign_slots(retp+1, argp, varp, extrap, extrac, stackslots...);
|
||||||
|
}
|
||||||
|
template<class... SS>
|
||||||
|
void vassign_slots(int retp, int argp, int varp, int extrap, int extrac, LuaArg &v, SS & ... stackslots) {
|
||||||
|
v.index_ = argp;
|
||||||
|
vassign_slots(retp, argp+1, varp, extrap, extrac, stackslots...);
|
||||||
|
}
|
||||||
|
template<class... SS>
|
||||||
|
void vassign_slots(int retp, int argp, int varp, int extrap, int extrac, LuaVar &v, SS & ... stackslots) {
|
||||||
|
v.index_ = varp;
|
||||||
|
vassign_slots(retp, argp, varp+1, extrap, extrac, stackslots...);
|
||||||
|
}
|
||||||
|
template<class... SS>
|
||||||
|
void vassign_slots(int retp, int argp, int varp, int extrap, int extrac, LuaExtraArgs &v, SS & ... stackslots) {
|
||||||
|
v.index_ = extrap;
|
||||||
|
v.size_ = extrac;
|
||||||
|
vassign_slots(retp, argp, varp, extrap, extrac, stackslots...);
|
||||||
|
}
|
||||||
|
void vassign_slots(int retp, int argp, int varp, int extrap, int extrac) {}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<class... SS>
|
template<class... SS>
|
||||||
inline LuaDefStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) {
|
inline LuaDefStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) {
|
||||||
constexpr Counts counts = count_slots<0, 0, 0>(stackslots...);
|
constexpr Counts counts = count_slots<0, 0, 0, 0>(stackslots...);
|
||||||
if (lua_gettop(L_) != counts.narg) {
|
if (lua_gettop(L_) < counts.narg) {
|
||||||
luaL_error(L_, "function expects exactly %d arguments", counts.narg);
|
luaL_error(L_, "function expects at least %d arguments", counts.narg);
|
||||||
}
|
}
|
||||||
lua_checkstack(L, counts.narg + counts.nvar + counts.nret + 20);
|
lua_checkstack(L, counts.nvar + counts.nret + 20);
|
||||||
for (int i = 0; i < counts.nret; i ++) {
|
int top = lua_gettop(L);
|
||||||
lua_pushnil(L_);
|
for (int i = 0; i < counts.nvar + counts.nret; i ++) {
|
||||||
lua_insert(L_, i + 1);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < counts.nvar; i++) {
|
|
||||||
lua_pushnil(L_);
|
lua_pushnil(L_);
|
||||||
}
|
}
|
||||||
assign_slots<1, 1 + counts.nret, 1 + counts.nret + counts.narg>(stackslots...);
|
vassign_slots(1 + counts.nvar + top, 1, 1 + top, 1 + counts.narg, top - counts.narg, stackslots...);
|
||||||
|
top_ = top + counts.nvar + counts.nret;
|
||||||
nret_ = counts.nret;
|
nret_ = counts.nret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int result() {
|
int result() {
|
||||||
lua_settop(L_, nret_);
|
lua_settop(L_, top_);
|
||||||
return nret_;
|
return nret_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,9 +777,10 @@ private:
|
|||||||
public:
|
public:
|
||||||
template<class... SS>
|
template<class... SS>
|
||||||
LuaExtStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) {
|
LuaExtStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) {
|
||||||
constexpr Counts counts = count_slots<0, 0, 0>(stackslots...);
|
constexpr Counts counts = count_slots<0, 0, 0, 0>(stackslots...);
|
||||||
static_assert(counts.narg == 0, "LuaExtStack doesn't allow LuaArg parameters");
|
static_assert(counts.narg == 0, "LuaExtStack doesn't allow LuaArg parameters");
|
||||||
static_assert(counts.nret == 0, "LuaExtStack doesn't allow LuaRet parameters");
|
static_assert(counts.nret == 0, "LuaExtStack doesn't allow LuaRet parameters");
|
||||||
|
static_assert(counts.nextra == 0, "LuaExtStack doesn't allow LuaExtraArgs parameters");
|
||||||
lua_checkstack(L_, counts.nvar + 20);
|
lua_checkstack(L_, counts.nvar + 20);
|
||||||
oldtop_ = lua_gettop(L_);
|
oldtop_ = lua_gettop(L_);
|
||||||
for (int i = 0; i < counts.nvar; i++) {
|
for (int i = 0; i < counts.nvar; i++) {
|
||||||
|
|||||||
@@ -270,19 +270,17 @@ LuaDefine(string_pprint, "obj1, obj2, ...",
|
|||||||
"|start at indentation level zero, and always expand the"
|
"|start at indentation level zero, and always expand the"
|
||||||
"|top-level table."
|
"|top-level table."
|
||||||
"|") {
|
"|") {
|
||||||
int n = lua_gettop(L);
|
LuaRet result;
|
||||||
LuaCoreStack LS(L);
|
LuaExtraArgs extra;
|
||||||
|
LuaDefStack LS(L, result, extra);
|
||||||
|
|
||||||
util::ostringstream oss;
|
util::ostringstream oss;
|
||||||
for (int i = 1; i <= n; i++) {
|
for (int i = 0; i < extra.size(); i++) {
|
||||||
LuaSpecial root(i);
|
pprint(LS, extra[i], PrettyPrintOptions(), &oss);
|
||||||
pprint(LS, root, PrettyPrintOptions(), &oss);
|
oss << "\n";
|
||||||
if (i < n) oss << "\n";
|
|
||||||
}
|
}
|
||||||
oss << std::endl;
|
|
||||||
lua_settop(L, 1);
|
|
||||||
LuaSpecial result(1);
|
|
||||||
LS.set(result, oss.view());
|
LS.set(result, oss.view());
|
||||||
return 1;
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaDefine(string_pprintx, "options",
|
LuaDefine(string_pprintx, "options",
|
||||||
|
|||||||
@@ -728,14 +728,12 @@ LuaDefine(pprint, "obj1, obj2, ...",
|
|||||||
"|") {
|
"|") {
|
||||||
World *w = World::fetch_global_pointer(L);
|
World *w = World::fetch_global_pointer(L);
|
||||||
std::ostream *ostream = w->lthread_print_stream();
|
std::ostream *ostream = w->lthread_print_stream();
|
||||||
int n = lua_gettop(L);
|
LuaExtraArgs extra;
|
||||||
LuaDefStack LS(L);
|
LuaDefStack LS(L, extra);
|
||||||
for (int i = 1; i <= n; i++) {
|
for (int i = 0; i < extra.size(); i++) {
|
||||||
LuaSpecial root(i);
|
pprint(LS, extra[i], PrettyPrintOptions(), ostream);
|
||||||
pprint(LS, root, PrettyPrintOptions(), ostream);
|
(*ostream) << std::endl;
|
||||||
if (i < n) (*ostream) << "\n";
|
|
||||||
}
|
}
|
||||||
(*ostream) << std::endl;
|
|
||||||
return LS.result();
|
return LS.result();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user