lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Sat, Jan 9, 2010 at 8:50 PM, Patrick Donnelly <batrick@batbytes.com> wrote:
> o lua_arith undocumented.

It's in the readme but not in the reference doc of 5.2.0work3.  I've
argued for this function, as well as lua_compare, because the need
comes up in lua2c [1], it seems it should be there for orthogonality,
and its relatively easy for Lua to implement (via the private
luaO_arith/luaV_arith functions).

One thing unclear is support for the sole unary arithmetic operation
(LUA_OPUNM).  Seemingly, this would be supported since lua_arith is
implemented in terms of luaO_arith, which implements it.  My first
thought was to push a single value and then call lua_arith(L,
LUA_OPUNM), but as you see it always pops two values and uses the
first:

  #include <lua.h>
  #include <lauxlib.h>
  int main() {
    lua_State * L = luaL_newstate();
    double f;
    luaL_openlibs(L);
    luaL_dostring(L, "return setmetatable({}, {__unm=function() return
2 end})");
    luaL_dostring(L, "return setmetatable({}, {__unm=function() return
3 end})");
    lua_arith(L, LUA_OPUNM);
    f = lua_tonumber(L, -1);
    printf("%f\n", f);
    return 0;
  }

I thought replacing the second luaL_dostring with a `lua_pushni(L)`
could be acceptable, as this is a rare operation anyway.  That works
unless I also replace the first luaL_dostring with just a
`lua_pushnumber(L, 2)`, in which case the checks in lua_arith raise an
error unless I make the `lua_pushnil(L)` instead a `lua_pushnumber(L,
0)` or force it via a `if (op == LUA_OPUNM) setnvalue(L->top - 1, 0)`
near the top of lua_arith.

An alternative implementation passing only a single value might be

LUA_API void  lua_arith (lua_State *L, int op) {
  TValue * v1;
  TValue * v2;
  lua_lock(L);
  v2 = L->top - 1;
  if (op == LUA_OPUNM) {
    v1 = v2;
    api_checknelems(L, 1);
  }
  else {
    v1 = v2 - 1;
    api_checknelems(L, 2);
  }
  if (ttisnumber(v1) && ttisnumber(v2))
    changenvalue(v1, luaO_arith(op, nvalue(v1), nvalue(v2)));
  else
    luaV_arith(L, v1, v1, v2, cast(TMS, op - LUA_OPADD + TM_ADD));
  L->top = v1 + 1;
  lua_unlock(L);
}

[1] http://lua-users.org/lists/lua-l/2009-06/msg00418.html