From 69cb659d789642ee1066ddfa311872df2fc8bb72 Mon Sep 17 00:00:00 2001 From: jyelon Date: Tue, 21 Jan 2025 20:20:54 -0500 Subject: [PATCH] Added constructors to tangible.build, more work on keyword argument parsing, added LS.tailcall. --- build-everything.py | 8 +++++++ luprex/cpp/core/luastack.cpp | 19 +++++++++++++++- luprex/cpp/core/luastack.hpp | 35 +++++++++++++++++++++++++++--- luprex/cpp/core/world-accessor.cpp | 19 +++++++++------- luprex/cpp/core/world-core.cpp | 2 +- luprex/lua/login.lua | 18 ++++++++++----- 6 files changed, 83 insertions(+), 18 deletions(-) diff --git a/build-everything.py b/build-everything.py index 203b8c8e..4f39c396 100755 --- a/build-everything.py +++ b/build-everything.py @@ -183,6 +183,14 @@ LUPREXBUILDTASK["type"] = "shell" LUPREXBUILDTASK["options"] = {} LUPREXBUILDTASK["options"]["cwd"] = f"{INTEGRATION}/luprex" +# +# Add a presentation { clear=true } to all build tasks. +# + +for task in WORKSPACE["tasks"]["tasks"]: + task["presentation"] = {} + task["presentation"]["clear"] = True + # # Convert all launch configurations to lldb. # diff --git a/luprex/cpp/core/luastack.cpp b/luprex/cpp/core/luastack.cpp index 3134e67c..feeb00ca 100644 --- a/luprex/cpp/core/luastack.cpp +++ b/luprex/cpp/core/luastack.cpp @@ -653,9 +653,26 @@ void LuaCoreStack::guard_nopredict(const char *fn) { } } +static int tailcall_continuation(lua_State *L) +{ + int base; + lua_getctx(L, &base); + return lua_gettop(L) - base; +} + +int LuaDefStack::tailcall_internal(bool passup, int base, int nargs) { + lua_callk(L_, nargs, passup ? LUA_MULTRET : 0, base, tailcall_continuation); + return lua_gettop(L_) - base; +} LuaKeywordParser::LuaKeywordParser(const LuaCoreStack &LS0, LuaSlot slot) - : keytab(slot.index()), LS(LS0.state(), found, error, key, val) { + : keytab(slot.index()), LS(LS0.state()) { + lua_State *L = LS0.state(); + lua_pushnil(L); found.index_ = lua_gettop(L); + lua_pushnil(L); error.index_ = lua_gettop(L); + lua_pushnil(L); key.index_ = lua_gettop(L); + lua_pushnil(L); val.index_ = lua_gettop(L); + istable = LS.istable(keytab); if (istable) { LS.rawget(found, keytab, token_found); diff --git a/luprex/cpp/core/luastack.hpp b/luprex/cpp/core/luastack.hpp index e1bca9d2..2e743fe2 100644 --- a/luprex/cpp/core/luastack.hpp +++ b/luprex/cpp/core/luastack.hpp @@ -493,6 +493,7 @@ private: friend class LuaCoreStack; friend class LuaDefStack; friend class LuaExtStack; + friend class LuaKeywordParser; }; class LuaArg : public LuaSlot {}; @@ -1136,7 +1137,33 @@ public: return nret_; } + // Tail-call into lua. + // + // This is meant to be used as follows: return LS.tailcall(passup, func, arg, arg...) + // + // If passup is true, the return value to our caller consists of our + // LuaRet arguments concatenated to the return values from the tail-call. + // If passup is false, the return value to our caller consists solely + // of our LuaRet arguments. + // + template + int tailcall(bool passup, LuaSlot func, T... args) { + lua_checkstack(L_, nret_ + 20); + int base = lua_gettop(L_); + for (int i = 1; i <= nret_; i++) { + lua_pushvalue(L_, i); + } + push_any_value(func); + int argbase = lua_gettop(L_); + push_any_values(args...); + int nargs = lua_gettop(L_) - argbase; + return tailcall_internal(passup, base, nargs); + } + ~LuaDefStack() { } + +private: + int tailcall_internal(bool passup, int base, int nargs); }; //////////////////////////////////////////////////////////////////// @@ -1237,7 +1264,7 @@ class LuaKeywordParser { private: LuaVar found, error, key, val; LuaSpecial keytab; - LuaExtStack LS; + LuaCoreStack LS; bool istable; void init(const lua_State *L, int slot); @@ -1255,12 +1282,14 @@ public: // stores an [ERROR] report in the keyword table. bool required(LuaSlot slot, std::string_view kw); - // Check if there are any errors so far. If any error has been + // 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. Also check that all keyword + // 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(); diff --git a/luprex/cpp/core/world-accessor.cpp b/luprex/cpp/core/world-accessor.cpp index 0690c52b..b81532c2 100644 --- a/luprex/cpp/core/world-accessor.cpp +++ b/luprex/cpp/core/world-accessor.cpp @@ -109,8 +109,8 @@ LuaDefine(tangible_animinit, "tan,config", "|get persisted: they stay the same unless you change them in" "|the 'animate' command." "|" - "|There are five hardwired persistent variables: plane,xyz,facing,bp,model." - "|These five variables are persistent no matter what. This function," + "|There are four hardwired persistent variables: plane,xyz,facing,bp." + "|These variables are persistent no matter what. This function," "|tangible.animinit, optionally allows you to create more persistent" "|variables. For example, let's say you have a pirate chest. You might" "|want to add two persistent variables in addition to the usual set:" @@ -302,9 +302,9 @@ LuaDefine(tangible_build, "config", "|The constructor is not allowed to block." ){ LuaArg config; - LuaVar classname, classtab, bp, plane, xyz, facing, mt; + LuaVar classname, classtab, bp, plane, xyz, facing, mt, func; LuaRet database; - LuaDefStack LS(L, config, classname, classtab, bp, plane, xyz, facing, mt, database); + LuaDefStack LS(L, config, classname, classtab, bp, plane, xyz, facing, mt, func, database); World *w = World::fetch_global_pointer(L); LuaKeywordParser kp(LS, config); @@ -356,10 +356,13 @@ LuaDefine(tangible_build, "config", // Initialize the animstate of the new tangible. tan->anim_queue_.clear(state); tan->update_plane_item(); - - // TODO: call the constructor. - - return LS.result(); + + // Call the constructor and finish. + LS.rawget(func, classtab, "init"); + if (!LS.isfunction(func)) { + return LS.result(); + } + return LS.tailcall(false, func, database, config); } LuaDefine(tangible_get, "id", diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index 9ddbdb73..e2a33b4e 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -331,7 +331,7 @@ int64_t World::create_login_actor() { tan->print_buffer_.clear(); if (is_authoritative()) { - LS.rawget(func, classtab, "initialize"); + LS.rawget(func, classtab, "init"); spawn(LS, id, id, func, true, 0, false); } } diff --git a/luprex/lua/login.lua b/luprex/lua/login.lua index 47272f26..2076d01b 100644 --- a/luprex/lua/login.lua +++ b/luprex/lua/login.lua @@ -1,16 +1,24 @@ makeclass('login') makeclass("engio") +makeclass('tree') -function login.initialize(actor, place) - dprint("login.initialize:", actor) +function tree.init(self, config) + print("In tree.init:") + pprint{self=self, config=config} + wait(1) + print("tick"); + wait(1) +end + +function login.init(actor, place) + dprint("login.init:", actor) local x = math.random(1, 100) local y = math.random(1, 100) tangible.animate(actor, nil, {bp="tangiblecharacter", action="warpto", plane="earth", xyz={x, y, 90}}) - end - +end function engio.move(actor, place, action, xyz, facing) -- todo: sanity check the parameters. dprint("engio.move ", action, " ", xyz[1], " ", xyz[2], " ", xyz[3]) tangible.animate(actor, nil, {action=action, xyz=xyz, facing=facing}) - end +end