From 5d1b998a7793268182c283ca7e47b63bdc13bd09 Mon Sep 17 00:00:00 2001 From: SilasD Date: Thu, 5 Nov 2026 19:18:17 -0800 Subject: [PATCH] first pass at implementing Lua df.new({assignment_table}) --- docs/dev/Lua API.rst | 14 +++++++++----- library/LuaWrapper.cpp | 16 ++++++++++++++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index a5c2146634..ca52126552 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -129,10 +129,12 @@ All typed objects have the following built-in features: Returns *size, address* -* ``ref:new()`` +* ``ref:new([assign_table])`` Allocates a new instance of the same type, and copies data - from the current object. + from the current object, + then optionally calls ``ref:assign`` with a Lua table of + :ref:`data to be assigned ` to the new instance. * ``ref:delete()`` @@ -355,9 +357,11 @@ Types excluding the global object also support: Returns the size of an object of the type. -* ``type:new()`` +* ``type:new([assign_table])`` - Creates a new instance of an object of the type. + Creates a new instance of an object of the type, + then optionally calls ``ref:assign`` with a Lua table of + :ref:`data to be assigned ` to the new instance. * ``type:is_instance(object)`` @@ -427,7 +431,7 @@ The ``df`` table itself contains the following functions and values: For types and refs identical to ``obj:sizeof()``. For lightuserdata returns *nil, address* -* ``df.new(obj)``, ``df.delete(obj)``, ``df.assign(obj, obj2)`` +* ``df.new(obj[,assign_data])``, ``df.delete(obj)``, ``df.assign(obj, obj2)`` Equivalent to using the matching methods of obj. diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp index 0d30429297..36ed1b81b9 100644 --- a/library/LuaWrapper.cpp +++ b/library/LuaWrapper.cpp @@ -695,15 +695,17 @@ static int meta_new(lua_State *state) int argc = lua_gettop(state); if (argc != 1 && argc != 2) - luaL_error(state, "Usage: object:new() or df.new(object) or df.new(ptype,count)"); + luaL_error(state, "Usage: object:new() or object:new(assign_table) or df.new(object) or df.new(object, assign_table) or df.new(ptype,count)"); const type_identity *id = get_object_identity(state, 1, "df.new()", true); void *ptr = nullptr; std::string err_context; + auto has_assign_table = (argc == 2 && lua_istable(state, 2)); + // Support arrays of primitive types - if (argc == 2) + if (argc == 2 && !has_assign_table) { int cnt = luaL_checkint(state, 2); if (cnt <= 0) @@ -745,6 +747,16 @@ static int meta_new(lua_State *state) else push_object_internal(state, id, ptr); + if (has_assign_table) { + // stack: 1 = the source object or type, 2 = the assign table, (... there could be junk here but currently isn't...), -1 = the new object that will be returned. + lua_dup(state); // duplicate the object we just new'ed + lua_getfield(state, -1, "assign"); // get its assign method + lua_swap(state); // shuffle the two + lua_pushvalue(state, 2); // copy arg 2, the table of assign data + lua_call(state, 2, 0); // call assign(), two args, we don't care what it returns. + // TODO this leaks the allocated object if assign fails. + // TODO maybe we should copy the table and insert a field "new = false". + } return 1; }