[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Are two arguments always passed to the Unary Minus metamethod?
- From: Dirk Laurie <dirk.laurie@...>
- Date: Mon, 31 Oct 2016 11:25:28 +0200
2016-10-31 4:58 GMT+02:00 dl acc <nydlacc123@gmail.com>:
> I'm hoping for a bit of confirmation that my understanding of how Lua passes
> arguments to __unm is correct. I have a library that dispatches to the
> correct C++ function depending on the contents of the Lua stack. It checks
> that the number and type of the Lua data on the stack is appropriate for the
> C++ function being called.
>
> Everything was working until I got an unexpected failure after setting a C++
> function to be called as the unary minus operation of a userdata. The Lua
> documentation says that the __unm handler is called as handler(operand) so I
> wrote the C++ function to take one argument and therefore one value should
> be on the Lua stack when it is invoked as a lua_CFunction. However, two
> values were on the stack instead and so my library refused to call the
> one-argument C++ function in that case.
>
> I rebuilt with both Luajit and Lua 5.3 and got the same behavior so I did a
> bit of digging and found this in lapi.c
>
> LUA_API void lua_arith (lua_State *L, int op) {
> lua_lock(L);
> if (op != LUA_OPUNM && op != LUA_OPBNOT)
> api_checknelems(L, 2); /* all other operations expect two operands */
> else { /* for unary operations, add fake 2nd operand */
> api_checknelems(L, 1);
> setobjs2s(L, L->top, L->top - 1);
> api_incr_top(L);
> }
> /* first operand at top - 2, second at top - 1; result go to top - 2 */
> luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
> L->top--; /* remove second operand */
> lua_unlock(L);
> }
>
> It seems that the addition of the "fake" operand is reason for the
> unexpected extra value on the stack. Is my understanding correct? I can
> accomodate this by rewriting my C++ __unm handler to take two arguments
> instead and ignore the second one. Of course, it will break if this Lua
> implementation detail changes in the future. Alternatively my library could
> stop requiring an exact match for the number of parameters, instead allowing
> the call if at least as many Lua values as there are C++ parameters is on
> the stack. I don't really want to do that though, because the library allows
> overloading so not requiring an exact match of parameter counts and Lua
> stack size complicates the set of applicable functions.
"For the unary operators (negation, length, and bitwise not), the metamethod
is computed and called with a dummy second operand, equal to the first one.
This extra operand is only to simplify Lua's internals (by making
these operators
behave like a binary operation) and may be removed in future versions.
(For most uses this extra operand is irrelevant.)" -- Lua 5.3 User's Manual