Makeclass cleaned up
This commit is contained in:
@@ -4,10 +4,10 @@
|
|||||||
LuaDefine(globaldb_enable, "c") {
|
LuaDefine(globaldb_enable, "c") {
|
||||||
LuaVar globaldb;
|
LuaVar globaldb;
|
||||||
LuaStack LS(L, globaldb);
|
LuaStack LS(L, globaldb);
|
||||||
LS.getfield(globaldb, LuaRegistry, "globaldb");
|
LS.rawget(globaldb, LuaRegistry, "globaldb");
|
||||||
if (!LS.istable(globaldb)) {
|
if (!LS.istable(globaldb)) {
|
||||||
LS.newtable(globaldb);
|
LS.newtable(globaldb);
|
||||||
LS.setfield(LuaRegistry, "globaldb", globaldb);
|
LS.rawset(LuaRegistry, "globaldb", globaldb);
|
||||||
}
|
}
|
||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ LuaDefine(globaldb_global, "f") {
|
|||||||
LuaStack LS(L, globalname, globaltab, globaldb);
|
LuaStack LS(L, globalname, globaltab, globaldb);
|
||||||
|
|
||||||
// Get a pointer to the globaldb.
|
// Get a pointer to the globaldb.
|
||||||
LS.getfield(globaldb, LuaRegistry, "globaldb");
|
LS.rawget(globaldb, LuaRegistry, "globaldb");
|
||||||
if (!LS.istable(globaldb)) {
|
if (!LS.istable(globaldb)) {
|
||||||
luaL_error(L, "globaldb is not enabled");
|
luaL_error(L, "globaldb is not enabled");
|
||||||
}
|
}
|
||||||
@@ -44,6 +44,6 @@ LuaDefine(globaldb_global, "f") {
|
|||||||
// Create a new globaltab and store it in the globaldb.
|
// Create a new globaltab and store it in the globaldb.
|
||||||
LS.newtable(globaltab);
|
LS.newtable(globaltab);
|
||||||
LS.rawset(globaldb, globalname, globaltab);
|
LS.rawset(globaldb, globalname, globaltab);
|
||||||
LS.setfield(globaltab, "__global", globalname);
|
LS.rawset(globaltab, "__global", globalname);
|
||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ LuaDefine(gui_create, "c") {
|
|||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaDefine(gui_add_menu_item, "c") {
|
LuaDefine(gui_menu_item, "c") {
|
||||||
LuaArg lgui, lid;
|
LuaArg lgui, lid;
|
||||||
LuaStack LS(L, lgui, lid);
|
LuaStack LS(L, lgui, lid);
|
||||||
Gui *gui = LS.ckuserdata<Gui>(lgui);
|
Gui *gui = LS.ckuserdata<Gui>(lgui);
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "luaconsole.hpp"
|
#include "luaconsole.hpp"
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
static bool is_single_letter(const std::string &s) {
|
||||||
|
return ((s.size() == 1) && (s[0] >= 'a') && (s[0] <= 'z'));
|
||||||
|
}
|
||||||
|
|
||||||
LuaConsole::LuaConsole() {
|
LuaConsole::LuaConsole() {
|
||||||
lua_state_ = lua_open();
|
lua_state_ = lua_open();
|
||||||
@@ -52,14 +58,16 @@ void LuaConsole::add(std::string line) {
|
|||||||
// Try to interpret it as a special command.
|
// Try to interpret it as a special command.
|
||||||
if (lines_ == 1) {
|
if (lines_ == 1) {
|
||||||
split_words();
|
split_words();
|
||||||
if ((words_.size() >= 1)&&(words_[0].size() == 1)) {
|
if (words_.size() >= 1) {
|
||||||
|
if (is_single_letter(words_[0]) || (util::validinteger(words_[0]))) {
|
||||||
action_ = DO_COMMAND;
|
action_ = DO_COMMAND;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
words_.clear();
|
words_.clear();
|
||||||
|
|
||||||
// Strip the leading punctuation from lua commands.
|
// Translate lua expression with leading '=' to 'return'
|
||||||
std::string partial;
|
std::string partial;
|
||||||
if (raw_input_[0] == '=') {
|
if (raw_input_[0] == '=') {
|
||||||
partial = std::string("return ") + raw_input_.substr(1);
|
partial = std::string("return ") + raw_input_.substr(1);
|
||||||
@@ -67,7 +75,7 @@ void LuaConsole::add(std::string line) {
|
|||||||
partial = raw_input_;
|
partial = raw_input_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyze lua expressions.
|
// Try to parse the lua expression
|
||||||
int top = lua_gettop(lua_state_);
|
int top = lua_gettop(lua_state_);
|
||||||
int status = luaL_loadbuffer(lua_state_, partial.c_str(), partial.size(), "=stdin");
|
int status = luaL_loadbuffer(lua_state_, partial.c_str(), partial.size(), "=stdin");
|
||||||
if (status == LUA_ERRSYNTAX)
|
if (status == LUA_ERRSYNTAX)
|
||||||
|
|||||||
@@ -189,33 +189,17 @@ int LuaStack::next(LuaSlot tab, LuaSlot key, LuaSlot value) const {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LuaStack::isemptytable(LuaSlot tab) const {
|
|
||||||
if (lua_istable(L_, tab)) {
|
|
||||||
lua_pushnil(L_);
|
|
||||||
if (lua_next(L_, tab) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
lua_pop(L_, 2);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LuaStack::newtable(LuaSlot target) const {
|
void LuaStack::newtable(LuaSlot target) const {
|
||||||
lua_newtable(L_);
|
lua_newtable(L_);
|
||||||
lua_replace(L_, target);
|
lua_replace(L_, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaStack::makeclass(LuaSlot classtab, LuaSlot classname) const {
|
void LuaStack::makeclass(LuaSlot classtab, LuaSlot classname) const {
|
||||||
int top = lua_gettop(L_);
|
|
||||||
checkstring(classname);
|
checkstring(classname);
|
||||||
|
|
||||||
// Special case: if the classname is _G, return global env.
|
// Special case: if the classname is _G, detect and error.
|
||||||
lua_pushstring(L_, "_G");
|
if (equal(classname, "_G")) {
|
||||||
int eqlg = lua_equal(L_, -1, classname.index());
|
luaL_error(L_, "_G is explicitly not allowed as a class name");
|
||||||
lua_settop(L_, top);
|
|
||||||
if (eqlg) {
|
|
||||||
set(classtab, LuaGlobals);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the classtab from the global environment.
|
// Get the classtab from the global environment.
|
||||||
@@ -236,6 +220,19 @@ void LuaStack::makeclass(LuaSlot classtab, LuaSlot classname) const {
|
|||||||
setfield(classtab, "__class", classname);
|
setfield(classtab, "__class", classname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaStack::makesubtable(LuaSlot sub, LuaSlot tab, const char *name) const {
|
||||||
|
rawget(sub, tab, name);
|
||||||
|
if (istable(sub)) {
|
||||||
|
return;
|
||||||
|
} else if (isnil(sub)) {
|
||||||
|
newtable(sub);
|
||||||
|
rawset(tab, name, sub);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
luaL_error(L_, "%s is not a table", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LuaStack::setlightuserdata(LuaSlot target, void *p) const {
|
void LuaStack::setlightuserdata(LuaSlot target, void *p) const {
|
||||||
lua_pushlightuserdata(L_, p);
|
lua_pushlightuserdata(L_, p);
|
||||||
lua_replace(L_, target);
|
lua_replace(L_, target);
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ public:
|
|||||||
|
|
||||||
void newtable(LuaSlot target) const;
|
void newtable(LuaSlot target) const;
|
||||||
|
|
||||||
void makeclass(LuaSlot tab, LuaSlot name) const;
|
void makesubtable(LuaSlot sub, LuaSlot tab, const char *name) const;
|
||||||
|
|
||||||
void setlightuserdata(LuaSlot target, void *p) const;
|
void setlightuserdata(LuaSlot target, void *p) const;
|
||||||
|
|
||||||
@@ -456,12 +456,27 @@ public:
|
|||||||
void clearuserdata(LuaSlot target) { clear_tagged_pointer(target); }
|
void clearuserdata(LuaSlot target) { clear_tagged_pointer(target); }
|
||||||
|
|
||||||
int next(LuaSlot tab, LuaSlot key, LuaSlot value) const;
|
int next(LuaSlot tab, LuaSlot key, LuaSlot value) const;
|
||||||
bool isemptytable(LuaSlot s) const;
|
|
||||||
|
|
||||||
bool equal(LuaSlot v1, LuaSlot v2) {
|
void makeclass(LuaSlot tab, LuaSlot name) const;
|
||||||
|
|
||||||
|
void makeclass(LuaSlot tab, const char *name) const {
|
||||||
|
push_any_value(name);
|
||||||
|
LuaSpecial classname(lua_gettop(L_));
|
||||||
|
makeclass(tab, classname);
|
||||||
|
lua_pop(L_, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool equal(LuaSlot v1, LuaSlot v2) const {
|
||||||
return lua_equal(L_, v1, v2);
|
return lua_equal(L_, v1, v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool equal(LuaSlot v1, const char *name) const {
|
||||||
|
push_any_value(name);
|
||||||
|
bool result = lua_equal(L_, v1, -1);
|
||||||
|
lua_pop(L_, 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
void set(T1 &target, T2 value) const {
|
void set(T1 &target, T2 value) const {
|
||||||
push_any_value(value);
|
push_any_value(value);
|
||||||
|
|||||||
@@ -40,6 +40,16 @@ LuaDefine(source_makeclass, "f") {
|
|||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LuaDefine(source_maketangible, "f") {
|
||||||
|
LuaArg classname;
|
||||||
|
LuaRet classtab;
|
||||||
|
LuaVar subtab;
|
||||||
|
LuaStack LS(L, classname, classtab, subtab);
|
||||||
|
LS.makeclass(classtab, classname);
|
||||||
|
LS.makesubtable(subtab, classtab, "action");
|
||||||
|
return LS.result();
|
||||||
|
}
|
||||||
|
|
||||||
// Load the builtins.
|
// Load the builtins.
|
||||||
|
|
||||||
static void load_builtin(lua_State *L, const char *name, lua_CFunction func) {
|
static void load_builtin(lua_State *L, const char *name, lua_CFunction func) {
|
||||||
@@ -189,18 +199,22 @@ static void source_clear_globals(lua_State *L) {
|
|||||||
// Restore the lua builtins from the backup snapshot.
|
// Restore the lua builtins from the backup snapshot.
|
||||||
//
|
//
|
||||||
static void source_restore_builtins(lua_State *L) {
|
static void source_restore_builtins(lua_State *L) {
|
||||||
LuaVar snapshot, key, value, skey, svalue, subglobal;
|
LuaVar snapshot, key, value, skey, svalue, target;
|
||||||
LuaStack LS(L, snapshot, key, value, skey, svalue, subglobal);
|
LuaStack LS(L, snapshot, key, value, skey, svalue, target);
|
||||||
|
|
||||||
LS.getfield(snapshot, LuaRegistry, "source_snapshot_builtins");
|
LS.getfield(snapshot, LuaRegistry, "source_snapshot_builtins");
|
||||||
LS.setfield(LuaGlobals, "_G", LuaGlobals);
|
LS.setfield(LuaGlobals, "_G", LuaGlobals);
|
||||||
LS.set(key, LuaNil);
|
LS.set(key, LuaNil);
|
||||||
while (LS.next(snapshot, key, value) != 0) {
|
while (LS.next(snapshot, key, value) != 0) {
|
||||||
LS.checktable(value);
|
LS.checktable(value);
|
||||||
LS.makeclass(subglobal, key);
|
if (LS.equal(key, "_G")) {
|
||||||
|
LS.set(target, LuaGlobals);
|
||||||
|
} else {
|
||||||
|
LS.makeclass(target, key);
|
||||||
|
}
|
||||||
LS.set(skey, LuaNil);
|
LS.set(skey, LuaNil);
|
||||||
while (LS.next(value, skey, svalue) != 0) {
|
while (LS.next(value, skey, svalue) != 0) {
|
||||||
LS.rawset(subglobal, skey, svalue);
|
LS.rawset(target, skey, svalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LS.result();
|
LS.result();
|
||||||
|
|||||||
@@ -109,13 +109,18 @@ void TextGame::do_menu_command(const StringVec &cmd) {
|
|||||||
|
|
||||||
void TextGame::do_choose_command(const StringVec &cmd) {
|
void TextGame::do_choose_command(const StringVec &cmd) {
|
||||||
int64_t index;
|
int64_t index;
|
||||||
if (cmd.size() == 2) {
|
if (cmd.size() == 1) {
|
||||||
index = util::strtoint(cmd[1], -1);
|
index = util::strtoint(cmd[0], -1);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "c command (choose) expects a menu line number" << std::endl;
|
std::cerr << "c command (choose) expects a menu line number" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::cerr << "Choose command (index " << index << ") not implemented yet." << std::endl;
|
const Gui::EltVec &elts = gui_.elts();
|
||||||
|
if ((index < 0) || (index >= int(elts.size()))) {
|
||||||
|
std::cerr << "No menu item #" << index << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::cerr << "Choosing menu item: " << elts[index].id() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextGame::do_snapshot_command(const StringVec &cmd) {
|
void TextGame::do_snapshot_command(const StringVec &cmd) {
|
||||||
@@ -143,14 +148,13 @@ void TextGame::do_quit_command(const StringVec &cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextGame::do_command(const StringVec &words) {
|
void TextGame::do_command(const StringVec &words) {
|
||||||
switch (words[0][0]) {
|
if (words[0] == "v") do_view_command(words);
|
||||||
case 'v': do_view_command(words); break;
|
else if (words[0] == "m") do_menu_command(words);
|
||||||
case 'm': do_menu_command(words); break;
|
else if (words[0] == "q") do_quit_command(words);
|
||||||
case 'c': do_choose_command(words); break;
|
else if (words[0] == "s") do_snapshot_command(words);
|
||||||
case 'q': do_quit_command(words); break;
|
else if (words[0] == "r") do_rollback_command(words);
|
||||||
case 's': do_snapshot_command(words); break;
|
else if (util::validinteger(words[0])) do_choose_command(words);
|
||||||
case 'r': do_rollback_command(words); break;
|
else {
|
||||||
default:
|
|
||||||
std::cerr << "Unknown command: " << words[0] << std::endl;
|
std::cerr << "Unknown command: " << words[0] << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ std::string toupper(std::string input) {
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool validinteger(const std::string &value) {
|
||||||
|
char *endptr;
|
||||||
|
strtoll(value.c_str(), &endptr, 10);
|
||||||
|
return (endptr == value.c_str() + value.size());
|
||||||
|
}
|
||||||
|
|
||||||
int64_t strtoint(const std::string &value, int64_t errval) {
|
int64_t strtoint(const std::string &value, int64_t errval) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
int64_t result = strtoll(value.c_str(), &endptr, 10);
|
int64_t result = strtoll(value.c_str(), &endptr, 10);
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ using stringset = std::set<std::string>;
|
|||||||
std::string tolower(std::string input);
|
std::string tolower(std::string input);
|
||||||
std::string toupper(std::string input);
|
std::string toupper(std::string input);
|
||||||
|
|
||||||
|
// Return true if the string can be parsed as an integer.
|
||||||
|
bool validinteger(const std::string &value);
|
||||||
|
|
||||||
// String to integer. Returns errval if the number is not parseable.
|
// String to integer. Returns errval if the number is not parseable.
|
||||||
int64_t strtoint(const std::string &value, int64_t errval);
|
int64_t strtoint(const std::string &value, int64_t errval);
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ void Tangible::be_a_player() {
|
|||||||
LuaVar classtab, mt, place, tangibles;
|
LuaVar classtab, mt, place, tangibles;
|
||||||
LuaStack LS(world_->state(), classtab, mt, place, tangibles);
|
LuaStack LS(world_->state(), classtab, mt, place, tangibles);
|
||||||
|
|
||||||
LS.call(classtab, source_makeclass, "player");
|
LS.makeclass(classtab, "player");
|
||||||
LS.getfield(tangibles, LuaRegistry, "tangibles");
|
LS.getfield(tangibles, LuaRegistry, "tangibles");
|
||||||
LS.rawget(place, tangibles, anim_queue_.get_id());
|
LS.rawget(place, tangibles, anim_queue_.get_id());
|
||||||
LS.getmetatable(mt, place);
|
LS.getmetatable(mt, place);
|
||||||
|
|||||||
@@ -6,4 +6,4 @@
|
|||||||
inspect.lua
|
inspect.lua
|
||||||
ut-table.lua
|
ut-table.lua
|
||||||
ut-globaldb.lua
|
ut-globaldb.lua
|
||||||
|
player.lua
|
||||||
|
|||||||
24
luprex/core/lua/player.lua
Normal file
24
luprex/core/lua/player.lua
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
maketangible('player')
|
||||||
|
|
||||||
|
function player.interface(actor, place, gui)
|
||||||
|
gui:menu_item("North")
|
||||||
|
gui:menu_item("South")
|
||||||
|
gui:menu_item("East")
|
||||||
|
gui:menu_item("West")
|
||||||
|
end
|
||||||
|
|
||||||
|
function player.action.north(actor, place, gui)
|
||||||
|
print("Moving north")
|
||||||
|
end
|
||||||
|
|
||||||
|
function player.action.south(actor, place, gui)
|
||||||
|
print("Moving south")
|
||||||
|
end
|
||||||
|
|
||||||
|
function player.action.east(actor, place, gui)
|
||||||
|
print("Moving east")
|
||||||
|
end
|
||||||
|
|
||||||
|
function player.action.west(actor, place, gui)
|
||||||
|
print("Moving west")
|
||||||
|
end
|
||||||
@@ -47,11 +47,6 @@
|
|||||||
#define LUA_ERRMEM 4
|
#define LUA_ERRMEM 4
|
||||||
#define LUA_ERRERR 5
|
#define LUA_ERRERR 5
|
||||||
|
|
||||||
/* Additional thread status codes for luprex */
|
|
||||||
#define LUA_ERRPARTIAL 15
|
|
||||||
#define LUA_ERREOF 16
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct lua_State lua_State;
|
typedef struct lua_State lua_State;
|
||||||
|
|
||||||
typedef int (*lua_CFunction) (lua_State *L);
|
typedef int (*lua_CFunction) (lua_State *L);
|
||||||
|
|||||||
Reference in New Issue
Block a user