lua-users home
lua-l archive

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


Hello list!

One possible way for integrating Lua with C++ code is to build a C++ 
class that represent a Lua variable and manages its corresponding 
stack slot. 

C++ objects of this class type are holding their stack index and are 
responsible for releasing the corresponding stack slot on destruction
(e.g. using the function lua_remove).

This works well as long as objects are destructed in reverse order
of their constructions, which is normally the case, e.g.

    class C
    {...};
    
    void f(C c1)
    {
        C c2;
        C c3;
    } // <- destruction order: c3, c2, c1


But in some cases the destruction order may change, especially for 
temporary objects, e.g.

    C g()
    {
        C c1;
        return C(); // c1 is destructed before this temporary object
    }               // is destroyed (at least with g++)

The problem here is that removing a stack index that is not on the top
shifts all stack slots above down.

To solve this problem it would be fine if Lua supported "unused" stack 
indices.

To accomplish this I made the following modifications to Lua 5.1:

In lua.h:

    #define LUA_TUNUSED  (-2)
    #define LUA_TNONE    (-1)
    
    #define lua_isunused(L,n) (lua_type(L, (n)) == LUA_TUNUSED)
    
In lapi.c:
    
    LUA_API void lua_unuse (lua_State *L, int idx) {
      StkId p;
      StkId b;
      lua_lock(L);
      p = index2adr(L, idx);
      api_checkvalidindex(L, p);
      p->tt = LUA_TUNUSED;
      p = L->top - 1;
      b = L->base;
      while (p >= b && p->tt == LUA_TUNUSED) --p;
      L->top = p + 1;
      lua_unlock(L);
    }

The function lua_unuse can be used to mark a stack slot as unused. 
If the top of the stack consists of unused slots all these slots 
are removed.

In lapi.c:

    LUA_API void lua_removeunusedbefore (lua_State *L, int idx) {
      StkId p;
      StkId q;
      StkId b;
      lua_lock(L);
      q = index2adr(L, idx);
      api_checkvalidindex(L, q);
    
      p = q - 1;
      b = L->base;
      while (p >= b && p->tt == LUA_TUNUSED) --p;
      p += 1;
    
      if (p < q) {
        while (q < L->top) {
            setobjs2s(L, p, q);
            q += 1;
            p += 1;   
        }
        L->top = p;
      }
      lua_unlock(L);
    }

The function lua_removeunusedbefore is useful if at the end of a 
function some lua values have been pushed onto the stack and 
should be valid after the functions returns.

In lapi.c:

    LUA_API const char *lua_typename (lua_State *L, int t) {
      UNUSED(L);
      switch (t)
      {
        case LUA_TNONE:   return "no value";
        case LUA_TUNUSED: return "unused";
        default:          return luaT_typenames[t];
      }
    }
    
Of course an unused stack index should under normal conditions 
not be exposed from C/C++ to Lua code.

What do you think of the above modifications? 

IMHO it would be nice if this small modification (or something 
similar) could be added to the standard lua core.

Best regards,
Oliver