From 9b956f00e7376ff13b16e6357a44e8a2b8b0eb9e Mon Sep 17 00:00:00 2001 From: jyelon Date: Thu, 16 Dec 2021 13:06:15 -0500 Subject: [PATCH] Add support for doc(builtin) --- luprex/core/cpp/luastack.cpp | 4 +-- luprex/core/cpp/luastack.hpp | 7 +++- luprex/core/cpp/main.cpp | 2 ++ luprex/core/cpp/source.cpp | 68 +++++++++++++++++++++++++++++++++++- luprex/core/cpp/source.hpp | 3 ++ 5 files changed, 80 insertions(+), 4 deletions(-) diff --git a/luprex/core/cpp/luastack.cpp b/luprex/core/cpp/luastack.cpp index 560464b7..26464c1f 100644 --- a/luprex/core/cpp/luastack.cpp +++ b/luprex/core/cpp/luastack.cpp @@ -17,7 +17,7 @@ LuaFunctionReg::LuaFunctionReg(const char *n, const char *a, const char *d, lua_ LuaFunctionReg::List LuaFunctionReg::all() { LuaFunctionReg::List result; - for (const LuaFunctionReg *r = LuaFunctionRegistry; r != 0; r = r->next_) { + for (LuaFunctionReg *r = LuaFunctionRegistry; r != 0; r = r->next_) { result.push_back(r); } return result; @@ -366,7 +366,7 @@ std::string LuaStack::get_function_name(LuaSlot fn) { LS.getglobaltable(globals); LS.set(key, LuaNil); while (LS.next(globals, key, val)) { - if (LS.isstring(key)) { + if (LS.isstring(key) && !LS.rawequal(globals, val)) { if (LS.rawequal(val, fn)) { return LS.ckstring(key); } diff --git a/luprex/core/cpp/luastack.hpp b/luprex/core/cpp/luastack.hpp index a236101d..65539bc8 100644 --- a/luprex/core/cpp/luastack.hpp +++ b/luprex/core/cpp/luastack.hpp @@ -478,7 +478,7 @@ private: static LuaFunctionReg *LuaFunctionRegistry; public: - using List = std::vector; + using List = std::vector; LuaFunctionReg(const char *name, const char *args, const char *docs, lua_CFunction f); static List all(); @@ -488,6 +488,7 @@ public: const char *get_args() const { return args_; } const char *get_docs() const { return docs_; } lua_CFunction get_func() const { return func_; } + void set_func(lua_CFunction fn) { func_ = fn; } }; @@ -497,6 +498,10 @@ public: int lfn_##name(lua_State *L) +#define LuaDefineBuiltin(name, args, docs) \ + LuaFunctionReg reg_##name(#name, args, docs, nullptr); + + #define LuaStringify(x) #x #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) { std::string _s1_ = (x); std::string _s2_ = (y); if (_s1_ != _s2_) luaL_error((L), "Assert failed: value=%s (file %s line %d)", _s1_.c_str(), __FILE__, __LINE__); } diff --git a/luprex/core/cpp/main.cpp b/luprex/core/cpp/main.cpp index 7f0aedb6..9d1a3712 100644 --- a/luprex/core/cpp/main.cpp +++ b/luprex/core/cpp/main.cpp @@ -4,6 +4,7 @@ #include "lpxserver.hpp" #include "drivertests.hpp" #include "driver.hpp" +#include "source.hpp" #include struct EngineMaker { @@ -33,6 +34,7 @@ static void usage() { int main(int argc, char **argv) { + SourceDB::register_lua_builtins(); UniqueDrivenEngine engine; if (argc < 2) usage(); std::string mode = argv[1]; diff --git a/luprex/core/cpp/source.cpp b/luprex/core/cpp/source.cpp index e0ecf96b..c70f7308 100644 --- a/luprex/core/cpp/source.cpp +++ b/luprex/core/cpp/source.cpp @@ -78,6 +78,19 @@ static void load_builtin_class(lua_State *L, const char *name, lua_CFunction fun LS.result(); } +static void erase_builtin(LuaStack &LS, LuaSlot globtab, const std::string &classname, const std::string &funcname) { + if (classname.empty()) { + LS.rawset(globtab, funcname, LuaNil); + } else { + LuaVar classtab; + LuaStack LSX(LS.state(), classtab); + LS.rawget(classtab, globtab, classname); + if (LS.istable(classtab)) { + LS.rawset(classtab, funcname, LuaNil); + } + } +} + static void source_install_builtins(lua_State *L) { LuaVar nullstring, stringclass, globtab; LuaStack LS(L, nullstring, stringclass, globtab); @@ -90,7 +103,10 @@ static void source_install_builtins(lua_State *L) { // Nuke a few of the builtin functions for sandboxing reasons. LS.getglobaltable(globtab); - LS.rawset(globtab, "loadfile", LuaNil); + erase_builtin(LS, globtab, "", "loadfile"); + erase_builtin(LS, globtab, "", "loadstring"); + erase_builtin(LS, globtab, "string", "dump"); + // Set the metatable for strings. // Normally, this would be done by luaopen_string, but we're @@ -468,6 +484,35 @@ void SourceDB::deserialize_source(util::LuaSourceVec *sv, StreamBuffer *sb) { } } +void SourceDB::register_lua_builtins() { + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + LuaVar globals,classtab,func; + LuaStack LS(L, globals, classtab, func); + LS.getglobaltable(globals); + auto regs = LuaFunctionReg::all(); + for (LuaFunctionReg *reg : regs) { + std::string funcname; + std::string classname; + get_reg_name(reg, classname, funcname); + if (classname.empty()) { + LS.rawget(func, globals, funcname); + if (LS.iscfunction(func)) { + reg->set_func(lua_tocfunction(L, func.index())); + } + } else { + LS.rawget(classtab, globals, classname); + if (LS.istable(classtab)) { + LS.rawget(func, classtab, funcname); + if (LS.iscfunction(func)) { + reg->set_func(lua_tocfunction(L, func.index())); + } + } + } + } + lua_close(L); +} + std::string SourceDB::function_docs(const LuaStack &LS0, LuaSlot fn) { lua_State *L = LS0.state(); LuaVar sourcedb, fname, finfo, code; @@ -636,3 +681,24 @@ LuaDefine(unittests_sourcedb, "", "some unit tests") { return 0; } + +LuaDefineBuiltin(table_concat, "vector1, vector2", "concatenate two vectors"); +LuaDefineBuiltin(table_insert, "vector, pos, value", "insert an element into a vector"); +LuaDefineBuiltin(table_remove, "vector, pos", "remove an element from a vector"); +LuaDefineBuiltin(table_sort, "vector [,comparefn]", "sort a vector"); +LuaDefineBuiltin(table_pack, "v1, v2, v3...", "turn a sequence of arguments into a vector"); +LuaDefineBuiltin(table_unpack, "vector", "turn a vector into a sequence of return values"); + +LuaDefineBuiltin(string_byte, "str [,index]", "get a single byte from a string"); +LuaDefineBuiltin(string_char, "byte, byte,...", "convert sequence of bytes to a string"); +LuaDefineBuiltin(string_find, "str, pattern [,index]", "return start and end of pattern in a string"); +LuaDefineBuiltin(string_len, "str", "return the length of the string, in bytes"); +LuaDefineBuiltin(string_rep, "str, count", "repeat the string some number of times"); +LuaDefineBuiltin(string_reverse, "str", "reverse the bytes of the string"); +LuaDefineBuiltin(string_lower, "str", "convert string to lowercase"); +LuaDefineBuiltin(string_upper, "str", "convert string to uppercase"); +LuaDefineBuiltin(string_format, "formatstr, v1,v2,v3...", "generate formatted output string"); +LuaDefineBuiltin(string_gmatch, "str, pattern", "iterate over pattern-matched substrings"); +LuaDefineBuiltin(string_gsub, "str, pattern, replace", "global replace pattern in string"); +LuaDefineBuiltin(string_match, "str, pattern", "return start and end of pattern in string"); +LuaDefineBuiltin(string_sub, "str, pos1, pos2", "return substring of str from pos1 to pos2"); diff --git a/luprex/core/cpp/source.hpp b/luprex/core/cpp/source.hpp index 8b7c6585..9af97b0c 100644 --- a/luprex/core/cpp/source.hpp +++ b/luprex/core/cpp/source.hpp @@ -173,6 +173,9 @@ public: void set(const std::string &fn, const std::string &code, int sequence); std::string get(const std::string &fn); + // Add builtins to the global function registry. + static void register_lua_builtins(); + // Get function documentation. static std::string function_docs(const LuaStack &LS, LuaSlot slot);