Index: /branches/script_engine/src/lib/script_engine/account.cc
===================================================================
--- /branches/script_engine/src/lib/script_engine/account.cc	(revision 7821)
+++ /branches/script_engine/src/lib/script_engine/account.cc	(revision 7821)
@@ -0,0 +1,50 @@
+    #include "luaincl.h"
+
+    #include "lunar.h"
+
+    class Account {
+      lua_Number m_balance;
+    public:
+      static const char className[];
+      static Lunar<Account>::RegType methods[];
+
+      Account(lua_State *L)      { m_balance = luaL_checknumber(L, 1); }
+      int deposit (lua_State *L) { m_balance += luaL_checknumber(L, 1); return 0; }
+      int withdraw(lua_State *L) { m_balance -= luaL_checknumber(L, 1); return 0; }
+      int balance (lua_State *L) { lua_pushnumber(L, m_balance); return 1; }
+      ~Account() { printf("deleted Account (%p)\n", this); }
+    };
+
+    const char Account::className[] = "Account";
+
+
+    #define method(class, name) {#name, &class::name}
+
+    Lunar<Account>::RegType Account::methods[] = {
+      method(Account, deposit),
+      method(Account, withdraw),
+      method(Account, balance),
+      {0,0}
+    };
+
+
+    int main(int argc, char *argv[])
+    {
+      lua_State *L = lua_open();
+
+      luaopen_base(L);
+      luaopen_table(L);
+      luaopen_io(L);
+      luaopen_string(L);
+      luaopen_math(L);
+      luaopen_debug(L);
+
+      Lunar<Account>::Register(L);
+
+      if(argc>1) lua_dofile(L, argv[1]);
+
+      lua_setgcthreshold(L, 0);  // collected garbage
+      lua_close(L);
+      return 0;
+    }
+
Index: anches/script_engine/src/lib/script_engine/luna.h
===================================================================
--- /branches/script_engine/src/lib/script_engine/luna.h	(revision 7820)
+++ 	(revision )
@@ -1,130 +1,0 @@
-/*
- * Lenny Palozzi - lenny.palozzi@home.com
- */
-
-#include <string>
-#include <iostream>
-
-#include "luaincl.h"
-
-/*extern "C" {
-#include <lua.h>
-}
-*/
-template <class T>
-class Luna
-{
-
-
- public:
-   /* member function map */
-   struct RegType {
-      const char* name;
-      int(T::*mfunc)(lua_State*);
-   };
-   /* register class T */
-   static void Register(lua_State* L) {
-      lua_pushcfunction(L, &Luna<T>::constructor);
-      lua_setglobal(L, T::className);
-
-
-     /* if (otag == 0) {
-        otag = lua_newtag(L);
-        lua_pushcfunction(L, &Luna<T>::gc_obj);
-        lua_settagmethod(L, otag, "gc"); /* tm to release objects
-      }*/
-   }
-
- private:
-   static int otag; /* object tag */
-
-   /* member function dispatcher */
-   static int thunk(lua_State* L) {
-      /* stack = closure(-1), [args...], 'self' table(1) */
-      //int i = static_cast<int>(lua_tonumber(L,-1));
-
-       int i = lua_upvalueindex (1);
-
-      //lua_pushnumber(L, 0); /* userdata object at index 0 */
-      //lua_gettable(L, 1);
-      lua_rawgeti (L, 1, 0);
-      T* obj = (T*)(lua_touserdata(L,-1));
-      lua_pop(L, 1); /* pop closure value and obj */
-
-        printf("FUNCTION:: %d\n", i );
-        printf("OBJECT %p\n", obj);
-
-
-      return (obj->*(T::Register[i].mfunc))(L);
-   }
-
-
-    static int setScriptable(T* obj)
-     {
-     //return registerObject(obj);
-     }
-
-   static int setScriptable(const std::string& objectName)
-    {
-   //#warning 'implement do not use'
-  //   return registerObject(obj);
-    }
-
-   /* constructs T objects */
-   static int constructor(lua_State* L) {
-      T* obj= new T(L); /* new T */
-       printf("OBJECT CREATED %p\n", obj);
-
-      return registerObject(obj, L);
-   }
-
-
-   /* releases objects */
-   static int gc_obj(lua_State* L) {
-      T* obj = static_cast<T*>(lua_touserdata(L, -1));
-      delete obj;
-      return 0;
-   }
- protected:
-   Luna(); /* hide default constructor */
-
- private:
-
-   static int registerObject(T* obj, lua_State* L)
-    {
-      lua_newtable(L); /* new table object */
-      //int  objRef = luaL_ref (L, LUA_REGISTRYINDEX);
-
-      //lua_pushnumber(L, 0); /* userdata obj at index 0 */
-      //lua_rawgeti(L, LUA_REGISTRYINDEX, objRef);
-      lua_pushlightuserdata(L, obj);
-      lua_rawseti(L,-2,0);
-      //lua_pushusertag(L, obj, otag); /* have gc call tm */
-      //lua_settable(L, -3);
-      //std::cout<<"test"<<std::endl;
-
-    /* Set up garbage collection
-      if(lua_getmetatable(L, objRef) != 0)
-       {
-        //std::cout<<"test"<<std::endl;
-        lua_pushstring (L, "__gc");
-        lua_pushcfunction(L, &Luna<T>::gc_obj);
-        lua_settable(L,-3);
-       }
-    */
-      //lua_rawgeti (L, LUA_REGISTRYINDEX, objRef);
-      /* register the member functions */
-      for (int i=0; T::Register[i].name; i++)
-      {
-         lua_pushstring(L, T::Register[i].name);
-         lua_pushnumber(L, i);
-         lua_pushcclosure(L, &Luna<T>::thunk, 1);
-         lua_settable(L,-3);
-      }
-      return 1; /* return the table object */
-}
-
-
-};
-template <class T>
-int Luna<T>::otag = 0;
Index: /branches/script_engine/src/lib/script_engine/luna/luna.h
===================================================================
--- /branches/script_engine/src/lib/script_engine/luna/luna.h	(revision 7821)
+++ /branches/script_engine/src/lib/script_engine/luna/luna.h	(revision 7821)
@@ -0,0 +1,130 @@
+/*
+ * Lenny Palozzi - lenny.palozzi@home.com
+ */
+
+#include <string>
+#include <iostream>
+
+#include "luaincl.h"
+
+/*extern "C" {
+#include <lua.h>
+}
+*/
+template <class T>
+class Luna
+{
+
+
+ public:
+   /* member function map */
+   struct RegType {
+      const char* name;
+      int(T::*mfunc)(lua_State*);
+   };
+   /* register class T */
+   static void Register(lua_State* L) {
+      lua_pushcfunction(L, &Luna<T>::constructor);
+      lua_setglobal(L, T::className);
+
+
+     /* if (otag == 0) {
+        otag = lua_newtag(L);
+        lua_pushcfunction(L, &Luna<T>::gc_obj);
+        lua_settagmethod(L, otag, "gc"); /* tm to release objects
+      }*/
+   }
+
+ private:
+   static int otag; /* object tag */
+
+   /* member function dispatcher */
+   static int thunk(lua_State* L) {
+      /* stack = closure(-1), [args...], 'self' table(1) */
+      //int i = static_cast<int>(lua_tonumber(L,-1));
+
+       int i = lua_upvalueindex (1);
+
+      //lua_pushnumber(L, 0); /* userdata object at index 0 */
+      //lua_gettable(L, 1);
+      lua_rawgeti (L, 1, 0);
+      T* obj = (T*)(lua_touserdata(L,-1));
+      lua_pop(L, 1); /* pop closure value and obj */
+
+        printf("FUNCTION:: %d\n", i );
+        printf("OBJECT %p\n", obj);
+
+
+      return (obj->*(T::Register[i].mfunc))(L);
+   }
+
+
+    static int setScriptable(T* obj)
+     {
+     //return registerObject(obj);
+     }
+
+   static int setScriptable(const std::string& objectName)
+    {
+   //#warning 'implement do not use'
+  //   return registerObject(obj);
+    }
+
+   /* constructs T objects */
+   static int constructor(lua_State* L) {
+      T* obj= new T(L); /* new T */
+       printf("OBJECT CREATED %p\n", obj);
+
+      return registerObject(obj, L);
+   }
+
+
+   /* releases objects */
+   static int gc_obj(lua_State* L) {
+      T* obj = static_cast<T*>(lua_touserdata(L, -1));
+      delete obj;
+      return 0;
+   }
+ protected:
+   Luna(); /* hide default constructor */
+
+ private:
+
+   static int registerObject(T* obj, lua_State* L)
+    {
+      lua_newtable(L); /* new table object */
+      //int  objRef = luaL_ref (L, LUA_REGISTRYINDEX);
+
+      //lua_pushnumber(L, 0); /* userdata obj at index 0 */
+      //lua_rawgeti(L, LUA_REGISTRYINDEX, objRef);
+      lua_pushlightuserdata(L, obj);
+      lua_rawseti(L,-2,0);
+      //lua_pushusertag(L, obj, otag); /* have gc call tm */
+      //lua_settable(L, -3);
+      //std::cout<<"test"<<std::endl;
+
+    /* Set up garbage collection
+      if(lua_getmetatable(L, objRef) != 0)
+       {
+        //std::cout<<"test"<<std::endl;
+        lua_pushstring (L, "__gc");
+        lua_pushcfunction(L, &Luna<T>::gc_obj);
+        lua_settable(L,-3);
+       }
+    */
+      //lua_rawgeti (L, LUA_REGISTRYINDEX, objRef);
+      /* register the member functions */
+      for (int i=0; T::Register[i].name; i++)
+      {
+         lua_pushstring(L, T::Register[i].name);
+         lua_pushnumber(L, i);
+         lua_pushcclosure(L, &Luna<T>::thunk, 1);
+         lua_settable(L,-3);
+      }
+      return 1; /* return the table object */
+}
+
+
+};
+template <class T>
+int Luna<T>::otag = 0;
Index: /branches/script_engine/src/lib/script_engine/lunar.h
===================================================================
--- /branches/script_engine/src/lib/script_engine/lunar.h	(revision 7821)
+++ /branches/script_engine/src/lib/script_engine/lunar.h	(revision 7821)
@@ -0,0 +1,207 @@
+    #include "luaincl.h"
+
+    template <typename T> class Lunar {
+      typedef struct { T *pT; } userdataType;
+    public:
+      typedef int (T::*mfp)(lua_State *L);
+      typedef struct { const char *name; mfp mfunc; } RegType;
+
+      static void Register(lua_State *L) {
+        lua_newtable(L);
+        int methods = lua_gettop(L);
+
+        luaL_newmetatable(L, T::className);
+        int metatable = lua_gettop(L);
+
+        // store method table in globals so that
+        // scripts can add functions written in Lua.
+        lua_pushvalue(L, methods);
+        set(L, LUA_GLOBALSINDEX, T::className);
+
+        // hide metatable from Lua getmetatable()
+        lua_pushvalue(L, methods);
+        set(L, metatable, "__metatable");
+
+        lua_pushvalue(L, methods);
+        set(L, metatable, "__index");
+
+        lua_pushcfunction(L, tostring_T);
+        set(L, metatable, "__tostring");
+
+        lua_pushcfunction(L, gc_T);
+        set(L, metatable, "__gc");
+
+        lua_newtable(L);                // mt for method table
+        lua_pushcfunction(L, new_T);
+        lua_pushvalue(L, -1);           // dup new_T function
+        set(L, methods, "new");         // add new_T to method table
+        set(L, -3, "__call");           // mt.__call = new_T
+        lua_setmetatable(L, methods);
+
+        // fill method table with methods from class T
+        for (RegType *l = T::methods; l->name; l++) {
+          lua_pushstring(L, l->name);
+          lua_pushlightuserdata(L, (void*)l);
+          lua_pushcclosure(L, thunk, 1);
+          lua_settable(L, methods);
+        }
+
+        lua_pop(L, 2);  // drop metatable and method table
+      }
+
+      // call named lua method from userdata method table
+      static int call(lua_State *L, const char *method,
+                      int nargs=0, int nresults=LUA_MULTRET, int errfunc=0)
+      {
+        int base = lua_gettop(L) - nargs;  // userdata index
+        if (!luaL_checkudata(L, base, T::className)) {
+          lua_settop(L, base-1);           // drop userdata and args
+          lua_pushfstring(L, "not a valid %s userdata", T::className);
+          return -1;
+        }
+
+        lua_pushstring(L, method);         // method name
+        lua_gettable(L, base);             // get method from userdata
+        if (lua_isnil(L, -1)) {            // no method?
+          lua_settop(L, base-1);           // drop userdata and args
+          lua_pushfstring(L, "%s missing method '%s'", T::className, method);
+          return -1;
+        }
+        lua_insert(L, base);               // put method under userdata, args
+
+        int status = lua_pcall(L, 1+nargs, nresults, errfunc);  // call method
+        if (status) {
+          const char *msg = lua_tostring(L, -1);
+          if (msg == NULL) msg = "(error with no message)";
+          lua_pushfstring(L, "%s:%s status = %d\n%s",
+                          T::className, method, status, msg);
+          lua_remove(L, base);             // remove old message
+          return -1;
+        }
+        return lua_gettop(L) - base + 1;   // number of results
+      }
+
+      // push onto the Lua stack a userdata containing a pointer to T object
+      static int push(lua_State *L, T *obj, bool gc=false) {
+        if (!obj) { lua_pushnil(L); return 0; }
+        luaL_getmetatable(L, T::className);  // lookup metatable in Lua registry
+        if (lua_isnil(L, -1)) luaL_error(L, "%s missing metatable", T::className);
+        int mt = lua_gettop(L);
+        subtable(L, mt, "userdata", "v");
+        userdataType *ud =
+          static_cast<userdataType*>(pushuserdata(L, obj, sizeof(userdataType)));
+        if (ud) {
+          ud->pT = obj;  // store pointer to object in userdata
+          lua_pushvalue(L, mt);
+          lua_setmetatable(L, -2);
+          if (gc == false) {
+            lua_checkstack(L, 3);
+            subtable(L, mt, "do not trash", "k");
+            lua_pushvalue(L, -2);
+            lua_pushboolean(L, 1);
+            lua_settable(L, -3);
+            lua_pop(L, 1);
+          }
+        }
+        lua_replace(L, mt);
+        lua_settop(L, mt);
+        return mt;  // index of userdata containing pointer to T object
+      }
+
+      // get userdata from Lua stack and return pointer to T object
+      static T *check(lua_State *L, int narg) {
+        userdataType *ud =
+          static_cast<userdataType*>(luaL_checkudata(L, narg, T::className));
+        if(!ud) luaL_typerror(L, narg, T::className);
+        return ud->pT;  // pointer to T object
+      }
+
+    private:
+      Lunar();  // hide default constructor
+
+      // member function dispatcher
+      static int thunk(lua_State *L) {
+        // stack has userdata, followed by method args
+        T *obj = check(L, 1);  // get 'self', or if you prefer, 'this'
+        lua_remove(L, 1);  // remove self so member function args start at index 1
+        // get member function from upvalue
+        RegType *l = static_cast<RegType*>(lua_touserdata(L, lua_upvalueindex(1)));
+        return (obj->*(l->mfunc))(L);  // call member function
+      }
+
+      // create a new T object and
+      // push onto the Lua stack a userdata containing a pointer to T object
+      static int new_T(lua_State *L) {
+        lua_remove(L, 1);   // use classname:new(), instead of classname.new()
+        T *obj = new T(L);  // call constructor for T objects
+        push(L, obj, true); // gc_T will delete this object
+        return 1;           // userdata containing pointer to T object
+      }
+
+      // garbage collection metamethod
+      static int gc_T(lua_State *L) {
+        if (luaL_getmetafield(L, 1, "do not trash")) {
+          lua_pushvalue(L, 1);  // dup userdata
+          lua_gettable(L, -2);
+          if (!lua_isnil(L, -1)) return 0;  // do not delete object
+        }
+        userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1));
+        T *obj = ud->pT;
+        if (obj) delete obj;  // call destructor for T objects
+        return 0;
+      }
+
+      static int tostring_T (lua_State *L) {
+        char buff[32];
+        userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1));
+        T *obj = ud->pT;
+        sprintf(buff, "%p", obj);
+        lua_pushfstring(L, "%s (%s)", T::className, buff);
+        return 1;
+      }
+
+      static void set(lua_State *L, int table_index, const char *key) {
+        lua_pushstring(L, key);
+        lua_insert(L, -2);  // swap value and key
+        lua_settable(L, table_index);
+      }
+
+      static void weaktable(lua_State *L, const char *mode) {
+        lua_newtable(L);
+        lua_pushvalue(L, -1);  // table is its own metatable
+        lua_setmetatable(L, -2);
+        lua_pushliteral(L, "__mode");
+        lua_pushstring(L, mode);
+        lua_settable(L, -3);   // metatable.__mode = mode
+      }
+
+      static void subtable(lua_State *L, int tindex, const char *name, const char *mode) {
+        lua_pushstring(L, name);
+        lua_gettable(L, tindex);
+        if (lua_isnil(L, -1)) {
+          lua_pop(L, 1);
+          lua_checkstack(L, 3);
+          weaktable(L, mode);
+          lua_pushstring(L, name);
+          lua_pushvalue(L, -2);
+          lua_settable(L, tindex);
+        }
+      }
+
+      static void *pushuserdata(lua_State *L, void *key, size_t sz) {
+        void *ud = 0;
+        lua_pushlightuserdata(L, key);
+        lua_gettable(L, -2);     // lookup[key]
+        if (lua_isnil(L, -1)) {
+          lua_pop(L, 1);         // drop nil
+          lua_checkstack(L, 3);
+          ud = lua_newuserdata(L, sz);  // create new userdata
+          lua_pushlightuserdata(L, key);
+          lua_pushvalue(L, -2);  // dup userdata
+          lua_settable(L, -4);   // lookup[key] = userdata
+        }
+        return ud;
+      }
+    };
+
+
Index: /branches/script_engine/src/lib/script_engine/lunartest.lua
===================================================================
--- /branches/script_engine/src/lib/script_engine/lunartest.lua	(revision 7821)
+++ /branches/script_engine/src/lib/script_engine/lunartest.lua	(revision 7821)
@@ -0,0 +1,28 @@
+ function printf(...) io.write(string.format(unpack(arg))) end
+
+function Account:show()
+  printf("Account balance = $%0.02f\n", self:balance())
+end
+
+a = Account(100)
+b = Account:new(30)
+
+print('a =', a)
+print('b =', b)
+print('metatable =', getmetatable(a))
+print('Account =', Account)
+table.foreach(Account, print)
+
+a:show() a:deposit(50.30) a:show() a:withdraw(25.10) a:show()
+
+parent = {}
+
+function parent:rob(amount)
+  amount = amount or self:balance()
+  self:withdraw(amount)
+  return amount
+end
+
+getmetatable(Account).__index = parent
+
+debug.debug()
