Move some stuff out of LuaStack

This commit is contained in:
2026-02-24 23:44:10 -05:00
parent 2c2d4e44bb
commit 829537a8d6
11 changed files with 407 additions and 410 deletions

View File

@@ -45,49 +45,6 @@ enum LuaTableType {
////////////////////////////////////////////////////////////////////
struct LuaToken {
private:
// Encode a token string as a fixed-width base38 number.
// Each character is mapped to a digit 1-37 (0 means "no character"),
// and the result is: CH0*38^11 + CH1*38^10 + ... + CH11*38^0.
// This fixed-width encoding ensures that numeric ordering matches
// lexicographic ordering of the original strings.
//
// Digit mapping: _ → 1, 0-9 → 2-11, a-z → 12-37.
//
// WARNING: The Lua lexer in llex.c contains a duplicate of this
// encoding logic (in the '@' token literal case). If you change
// the encoding here, you must update llex.c to match.
// Returns zero if the string is empty, too long, or contains
// invalid characters.
//
static constexpr uint64_t parse(std::string_view str) {
if (str.size() > 12) return 0;
if (str.empty()) return 0;
uint64_t result = 0;
for (int i = 0; i < int(str.size()); i++) {
char c = str[i];
uint64_t digit = 0;
if (c == '_') {
digit = 1;
} else if ((c >= '0') && (c <= '9')) {
digit = uint64_t(c - '0') + 2;
} else if ((c >= 'a') && (c <= 'z')) {
digit = uint64_t(c - 'a') + 12;
} else if ((c >= 'A') && (c <= 'Z')) {
digit = uint64_t(c - 'A') + 12;
} else {
return 0;
}
result = result * 38 + digit;
}
// Pad remaining positions with zeros (no character).
for (int i = int(str.size()); i < 12; i++) {
result = result * 38;
}
return result;
}
public:
uint64_t value;
@@ -101,8 +58,8 @@ public:
// If the string is not a valid token, then this
// initializes the token to the empty token (zero)
//
LuaToken(std::string_view s) : value(parse(s)) {}
LuaToken(const eng::string &s) : value(parse(s)) {}
LuaToken(std::string_view s) : value(util::encode_token(s)) {}
LuaToken(const eng::string &s) : value(util::encode_token(s)) {}
// Construct a token from a compile-time constant string.
//
@@ -111,14 +68,18 @@ public:
// consteval (evaluated at compile time), the error is
// generated during the compilation.
//
consteval LuaToken(const char *s) : value(parse(s)) {
// WARNING: The Lua lexer in llex.c contains a duplicate of the
// encoding logic (in the '@' token literal case). If you change
// the encoding in util::encode_token, you must update llex.c to match.
//
consteval LuaToken(const char *s) : value(util::encode_token(s)) {
if (empty()) throw "cannot parse token";
}
// Construct a token from an int64.
//
LuaToken(uint64_t v) : value(v) {}
// Construct a token from a void pointer.
//
LuaToken(void *v) : value((uint64_t)v) {}
@@ -144,10 +105,7 @@ public:
// Convert the token to a string.
//
// The conversion to string consists of expressing the value
// in base 36.
//
eng::string str() const;
eng::string str() const { return util::decode_token(value); }
};
////////////////////////////////////////////////////////////////////
@@ -898,113 +856,9 @@ public:
}
};
////////////////////////////////////////////////////////////////////
//
// LuaKeywordParser
//
// This is a helper class to help parse tables full of keywords.
// It is meant to make it easier to write LuaDefine functions that
// accept keyword arguments. It helps with the following tasks:
//
// * It makes sure the keyword table actually is a table.
//
// * It makes sure that all required keywords are present.
//
// * It makes sure that you didn't put anything that isn't a
// known keyword into the keyword table.
//
// This module adds two fields to the table:
//
// [ERROR] - stores an error message, initially nil.
// [FOUND] - the set of keywords successfully parsed.
//
// If at any time, this module detects an error, it doesn't throw.
// Instead, it stores an error report in the table key [ERROR].
// Later, you can check for an error string using the function
// final_check or final_check_throw. If an error is
// detected when there is already an error report in the table,
// the error report is not overwritten, so therefore, the error
// reported is always the first error detected.
//
// When this module finds a keyword in the table, it adds the keyword
// to the [FOUND] set of all keywords successfully parsed.
//
// If the keyword table that you pass in isn't a table at all,
// then the keyword-fetching functions will always return false.
// Later, when you call 'check', an appropriate error will be
// generated.
//
// The lua module 'keywords' contains the same functions as this
// C++ class. You can write code where a C++ function does some
// of the parsing, and the lua code does the rest of the parsing.
//
////////////////////////////////////////////////////////////////////
class LuaKeywordParser {
private:
LuaVar found, error, key, val;
LuaSpecial keytab;
LuaCoreStack LS;
bool istable;
void init(const lua_State *L, int slot);
public:
LuaKeywordParser(const LuaCoreStack &LS, LuaSlot slot);
// Fetch the value of the keyword. If the keyword is found, then the
// keyword is added to the [FOUND] set, the value is returned in slot,
// and returns true. Otherwise, sets slot to nil and returns false.
bool optional(LuaSlot slot, std::string_view kw);
// Fetch the value of the keyword. If the keyword is found, then the
// keyword is added to the [FOUND] set, the value is returned in slot,
// and returns true. Otherwise, sets slot to nil, returns false, and
// stores an [ERROR] report in the keyword table.
bool required(LuaSlot slot, std::string_view kw);
// Check if there are any errors so far, by checking for an [ERROR]
// report in the keyword table. If any error has been
// detected, returns an error message, otherwise, returns empty
// string.
eng::string check();
// Check if there are any errors so far, by checking for an [ERROR]
// report in the keyword table. Also check that all keyword
// arguments present in the table are in the [FOUND] set. If there are
// any errors, returns an error message, otherwise returns empty string.
eng::string final_check();
// If check() returns an error, throws the error using luaL_error.
void check_throw();
// If final_check() returns an error, throws the error using luaL_error.
void final_check_throw();
// Fetch the state pointer.
lua_State *state() const { return LS.state(); }
};
////////////////////////////////////////////////////////////////////
//
// Lua Byte Reader
//
// Converts a block of bytes in RAM into a lua_reader.
//
////////////////////////////////////////////////////////////////////
class LuaByteReader {
private:
const char *data_;
int64_t size_;
public:
LuaByteReader(const char *d, int64_t s) : data_(d), size_(s) {}
void *lua_reader_userdata() { return this; }
static const char *lua_reader(lua_State *L, void *ud, size_t *size);
};
////////////////////////////////////////////////////////////////////
//
// The Lua Constant Registry