neolithos / neolua

A Lua implementation for the Dynamic Language Runtime (DLR).
https://neolua.codeplex.com/
Apache License 2.0
466 stars 76 forks source link

Table concat with metamethod fails when the table is RHS #169

Closed powercode closed 1 year ago

powercode commented 1 year ago

NeoLua Version: 1.3.14

Have a table with a __concat metamethod, and call it with a table as the RHS.

Example to reproduce:

mytable = {}
function mytable.__concat(lhs, rhs)
    if getmetatable(rhs) ~= mytable then
        error("Right-hand side must be a mytable object", 2)
    end

    local t = type(lhs)
    if t == "string" then
        table.insert(rhs, lhs)
        ret
    end

    if t == "table" then
        local ret = {}
        for _, i in ipairs(lhs) do
            table.insert(ret, i .. rhs)
        end
        return ret
    end

    error("Left-hand side must be a string or a table of strings", 2)
end

"some string" .. mytable

The C version checks both operands for the event, in this case "__concat," before invoking that event, potentially with the dispatching table as the RHS argument.

static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
                       StkId res, TMS event) {
  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
  if (ttisnil(tm))
    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
  if (ttisnil(tm)) return 0;
  callTM(L, tm, p1, p2, res, 1);
  return 1;
}

The code here does not consider that the table may be the RHS of the concat operator. https://github.com/neolithos/neolua/blob/c5d987ba2ce5f702a98a0a4f26da5064966981ff/NeoLua/Lua.Runtime.cs#L1303

neolithos commented 1 year ago

Is merged.