Rewrite 'getclass' and 'classname' operators. These were flaky and inconsistent.
This commit is contained in:
@@ -381,103 +381,87 @@ lua_State *LuaCoreStack::newthread(LuaSlot target) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
eng::string LuaCoreStack::classname(LuaSlot input) const {
|
||||
LuaVar lookup, classtab, classname, metatable;
|
||||
LuaExtStack LS(L_, lookup, classtab, classname, metatable);
|
||||
void LuaCoreStack::getclassinfo(LuaSlot classtab,
|
||||
eng::string &classname, eng::string &error, LuaSlot input) const {
|
||||
LuaVar lookup, cname;
|
||||
LuaExtStack LS(L_, lookup, cname);
|
||||
|
||||
// Step 1: Resolve input to a class table.
|
||||
int xt = xtype(input);
|
||||
if (xt == LUA_TSTRING) {
|
||||
LS.rawget(lookup, LuaRegistry, "classes");
|
||||
LS.rawget(classtab, lookup, input);
|
||||
if (xtype(classtab) != LUA_TT_CLASS) {
|
||||
return "";
|
||||
}
|
||||
return LS.ckstring(input);
|
||||
} else if (xt == LUA_TT_TANGIBLE) {
|
||||
if (!LS.getmetatable(lookup, input)) {
|
||||
return "";
|
||||
if (LS.getmetatable(lookup, input)) {
|
||||
LS.rawget(classtab, lookup, "__index");
|
||||
} else {
|
||||
LS.set(classtab, LuaNil);
|
||||
}
|
||||
LS.rawget(classtab, lookup, "__index");
|
||||
if (xtype(classtab) != LUA_TT_CLASS) {
|
||||
return "";
|
||||
}
|
||||
LS.rawget(lookup, LuaRegistry, "classnames");
|
||||
LS.rawget(classname, lookup, classtab);
|
||||
if (!LS.isstring(classname)) {
|
||||
return "";
|
||||
}
|
||||
return LS.ckstring(classname);
|
||||
} else if (xt == LUA_TT_CLASS) {
|
||||
LS.rawget(lookup, LuaRegistry, "classnames");
|
||||
LS.rawget(classname, lookup, input);
|
||||
if (!LS.isstring(classname)) {
|
||||
return "";
|
||||
}
|
||||
return LS.ckstring(classname);
|
||||
LS.set(classtab, input);
|
||||
} else if (xt == LUA_TT_GENERAL) {
|
||||
LS.getmetatable(metatable, input);
|
||||
LS.rawget(lookup, LuaRegistry, "classnames");
|
||||
LS.rawget(classname, lookup, metatable);
|
||||
if (!LS.isstring(classname)) {
|
||||
return "";
|
||||
}
|
||||
return LS.ckstring(classname);
|
||||
LS.getmetatable(classtab, input);
|
||||
} else {
|
||||
return "";
|
||||
LS.set(classtab, LuaNil);
|
||||
}
|
||||
|
||||
// Step 2: Validate classtab and get classname, or generate error.
|
||||
// A class table is only valid if it's registered in classnames.
|
||||
if (xtype(classtab) == LUA_TT_CLASS) {
|
||||
LS.rawget(lookup, LuaRegistry, "classnames");
|
||||
LS.rawget(cname, lookup, classtab);
|
||||
auto name = LS.trystring(cname);
|
||||
if (name) {
|
||||
classname = *name;
|
||||
error = "";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: We didn't find a valid classtab and classname.
|
||||
// Clear the classtab and classname return-values, then
|
||||
// figure out what went wrong and generate an error message.
|
||||
LS.set(classtab, LuaNil);
|
||||
classname = "";
|
||||
if (xt == LUA_TSTRING) {
|
||||
eng::string s = LS.ckstring(input);
|
||||
if (!sv::is_lua_classname(s)) {
|
||||
error = "invalid class name: " + s;
|
||||
} else {
|
||||
error = "class does not exist: " + s;
|
||||
}
|
||||
} else if (xt == LUA_TT_TANGIBLE) {
|
||||
error = "tangible has no valid class";
|
||||
} else if (xt == LUA_TT_GENERAL) {
|
||||
error = "table has no valid class";
|
||||
} else if (xt == LUA_TT_CLASS) {
|
||||
error = "class is no longer valid";
|
||||
} else {
|
||||
error = "expected a string, class, tangible, or table";
|
||||
}
|
||||
}
|
||||
|
||||
static eng::string nonexistentclass(eng::string name) {
|
||||
eng::string err;
|
||||
if (!sv::is_lua_classname(name)) {
|
||||
err = "invalid class name: " + name;
|
||||
} else {
|
||||
err = "not a class: " + name;
|
||||
}
|
||||
return err;
|
||||
eng::string LuaCoreStack::classname(LuaSlot input) const {
|
||||
LuaVar tab;
|
||||
LuaExtStack LS(L_, tab);
|
||||
eng::string name, error;
|
||||
getclassinfo(tab, name, error, input);
|
||||
return name;
|
||||
}
|
||||
|
||||
eng::string LuaCoreStack::getclass(LuaSlot classtab, LuaSlot input) const {
|
||||
LuaVar lookup;
|
||||
LuaExtStack LS(L_, lookup);
|
||||
|
||||
int xt = xtype(input);
|
||||
if (xt == LUA_TSTRING) {
|
||||
LS.rawget(lookup, LuaRegistry, "classes");
|
||||
LS.rawget(classtab, lookup, input);
|
||||
if (xtype(classtab) != LUA_TT_CLASS) {
|
||||
eng::string classname = LS.ckstring(input);
|
||||
return nonexistentclass(LS.ckstring(input));
|
||||
}
|
||||
return "";
|
||||
} else if (xt == LUA_TT_TANGIBLE) {
|
||||
if (!LS.getmetatable(lookup, input)) {
|
||||
eng::string err = "inactive tangible has no class";
|
||||
return err;
|
||||
}
|
||||
LS.rawget(classtab, lookup, "__index");
|
||||
if (xtype(classtab) != LUA_TT_CLASS) {
|
||||
eng::string err = "tangible has invalid class";
|
||||
}
|
||||
return "";
|
||||
} else if (xt == LUA_TT_CLASS) {
|
||||
LS.set(classtab, input);
|
||||
return "";
|
||||
} else {
|
||||
eng::string err = "getclass must be passed a string, class, or tangible";
|
||||
return err;
|
||||
}
|
||||
eng::string name, error;
|
||||
getclassinfo(classtab, name, error, input);
|
||||
return error;
|
||||
}
|
||||
|
||||
eng::string LuaCoreStack::getclass(LuaSlot classtab, std::string_view classname) const {
|
||||
LuaVar lookup;
|
||||
LuaExtStack LS(L_, lookup);
|
||||
LS.rawget(lookup, LuaRegistry, "classes");
|
||||
LS.rawget(classtab, lookup, classname);
|
||||
if (xtype(classtab) != LUA_TT_CLASS) {
|
||||
return nonexistentclass(eng::string(classname));
|
||||
}
|
||||
return "";
|
||||
LuaVar input;
|
||||
LuaExtStack LS(L_, input);
|
||||
LS.set(input, classname);
|
||||
eng::string name, error;
|
||||
getclassinfo(classtab, name, error, input);
|
||||
return error;
|
||||
}
|
||||
|
||||
void LuaCoreStack::makeclass(LuaSlot classtab, LuaSlot classname) const {
|
||||
|
||||
Reference in New Issue
Block a user