yet another multi-ABI bundle installer fix
[ardour.git] / libs / lua / LuaBridge / detail / Namespace.h
index f7f484b1187f4d039d2d84d2f3cafc6ff777c7d4..92aed815305aa1f4cf68532dd769cf6f6ddbd06d 100644 (file)
@@ -2,6 +2,7 @@
 /*
   https://github.com/vinniefalco/LuaBridge
 
+  Copyright 2016, Robin Gareus <robin@gareus.org>
   Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
   Copyright 2007, Nathan Reed
 
 */
 //==============================================================================
 
+#ifdef LUABINDINGDOC
+#include <iostream>
+#include <typeinfo>
+#include <execinfo.h>
+#include <type_traits>
+#include <cxxabi.h>
+#include <memory>
+#include <string>
+#include <cstdlib>
+
+template <class T>
+std::string type_name()
+{
+       typedef typename std::remove_reference<T>::type TR;
+       std::unique_ptr<char, void(*)(void*)> own
+               (
+                abi::__cxa_demangle(typeid(TR).name(), nullptr,
+                        nullptr, nullptr),
+                std::free
+               );
+       std::string r = own != nullptr ? own.get() : typeid(TR).name();
+       if (std::is_const<TR>::value)
+               r += " const";
+       if (std::is_volatile<TR>::value)
+               r += " volatile";
+       if (std::is_lvalue_reference<T>::value)
+               r += "&";
+       else if (std::is_rvalue_reference<T>::value)
+               r += "&&";
+       return r;
+}
+
+//#define LUADOCOUT
+
+#ifdef LUADOCOUT // lua
+#define KEYSTA "[\""
+#define KEYEND "\"] = "
+#else // JSON
+#define KEYSTA "\""
+#define KEYEND "\" : "
+#endif
+
+#define CLASSDOC(TYPE, LUANAME, DECL, PARENTDECL) \
+  if (LuaBindingDoc::printBindings ()) { \
+    std::cout <<   "{ " << KEYSTA << "type"   << KEYEND << "  \""  << TYPE << "\",\n"; \
+    std::cout <<   "  " << KEYSTA << "lua"    << KEYEND << "   \"" << LUANAME << "\",\n"; \
+    std::cout <<   "  " << KEYSTA << "decl"   << KEYEND << "  \"" << DECL << "\",\n"; \
+    std::cout <<   "  " << KEYSTA << "parent" << KEYEND << "\""  << PARENTDECL << "\"\n"; \
+    std::cout <<   "},\n"; \
+  }
+
+#define PRINTDOC(TYPE, LUANAME, RETVAL, DECL) \
+  if (LuaBindingDoc::printBindings ()) { \
+    std::cout <<   "{ " << KEYSTA << "type"   << KEYEND << "  \""  << TYPE << "\",\n"; \
+    std::cout <<   "  " << KEYSTA << "lua"    << KEYEND << "   \"" << LUANAME << "\",\n"; \
+    if (!(RETVAL).empty()) { \
+      std::cout << "  " << KEYSTA << "ret"    << KEYEND << "   \"" << (RETVAL) << "\",\n"; \
+    } \
+    std::cout <<   "  " << KEYSTA << "decl"   << KEYEND << "  \""  << DECL << "\"\n"; \
+    std::cout <<   "},\n"; \
+  }
+
+#define FUNDOC(TYPE, NAME, FUNCTOR) \
+  PRINTDOC(TYPE, _name << NAME, \
+      type_name< typename FuncTraits <FUNCTOR>::ReturnType >(), \
+      type_name< typename FuncTraits <FUNCTOR>::DeclType >())
+
+#define DATADOC(TYPE, NAME, FUNCTOR) \
+  PRINTDOC(TYPE, _name << NAME, \
+      std::string(), \
+      type_name< decltype(FUNCTOR) >())\
+
+
+#else
+
+#define CLASSDOC(TYPE, LUANAME, DECL, PARENTDECL)
+#define PRINTDOC(TYPE, LUANAME, RETVAL, DECL)
+#define FUNDOC(TYPE, NAME, FUNCTOR)
+#define DATADOC(TYPE, NAME, FUNCTOR)
+
+#endif
+
 /** Provides C++ to Lua registration capabilities.
 
     This class is not instantiated directly, call `getGlobalNamespace` to start
@@ -108,6 +191,11 @@ private:
     lua_State* const L;
     int mutable m_stackSize;
 
+#ifdef LUABINDINGDOC
+    std::string _name;
+    const Namespace* _parent;
+#endif
+
   protected:
     //--------------------------------------------------------------------------
     /**
@@ -417,6 +505,10 @@ private:
     ClassBase (ClassBase const& other)
       : L (other.L)
       , m_stackSize (0)
+#ifdef LUABINDINGDOC
+      , _name (other._name)
+      , _parent (other._parent)
+#endif
     {
       m_stackSize = other.m_stackSize;
       other.m_stackSize = 0;
@@ -443,7 +535,7 @@ private:
       -4 (enclosing namespace)
   */
   template <class T>
-  class Class : public ClassBase
+  class Class : virtual public ClassBase
   {
   public:
     //==========================================================================
@@ -452,6 +544,11 @@ private:
     */
     Class (char const* name, Namespace const* parent) : ClassBase (parent->L)
     {
+#ifdef LUABINDINGDOC
+      _parent = parent;
+      _name = parent->_name + name + ":";
+#endif
+      PRINTDOC ("[C] Class", parent->_name << name, std::string(), type_name <T>())
       m_stackSize = parent->m_stackSize + 3;
       parent->m_stackSize = 0;
 
@@ -482,6 +579,8 @@ private:
       }
       else
       {
+        lua_pop (L, 1);
+        lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
         rawgetfield (L, -1, "__class");
         rawgetfield (L, -1, "__const");
 
@@ -498,6 +597,10 @@ private:
     Class (char const* name, Namespace const* parent, void const* const staticKey)
       : ClassBase (parent->L)
     {
+#ifdef LUABINDINGDOC
+      _parent = parent;
+      _name = parent->_name + name + ":";
+#endif
       m_stackSize = parent->m_stackSize + 3;
       parent->m_stackSize = 0;
 
@@ -548,6 +651,7 @@ private:
     template <class U>
     Class <T>& addStaticData (char const* name, U* pu, bool isWritable = true)
     {
+      DATADOC ("Static Data Member", name, pu)
       assert (lua_istable (L, -1));
 
       rawgetfield (L, -1, "__propget");
@@ -576,6 +680,7 @@ private:
     }
 
     //--------------------------------------------------------------------------
+#if 0 // unused
     /**
       Add or replace a static property member.
 
@@ -613,6 +718,7 @@ private:
 
       return *this;
     }
+#endif
 
     //--------------------------------------------------------------------------
     /**
@@ -621,6 +727,7 @@ private:
     template <class FP>
     Class <T>& addStaticFunction (char const* name, FP const fp)
     {
+      FUNDOC ("Static Member Function", name, FP)
       new (lua_newuserdata (L, sizeof (fp))) FP (fp);
       lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
       rawsetfield (L, -2, name);
@@ -634,6 +741,7 @@ private:
     */
     Class <T>& addStaticCFunction (char const* name, int (*const fp)(lua_State*))
     {
+      DATADOC ("Static C Function", name, fp)
       lua_pushcfunction (L, fp);
       rawsetfield (L, -2, name);
       return *this;
@@ -646,6 +754,7 @@ private:
     template <class U>
     Class <T>& addData (char const* name, const U T::* mp, bool isWritable = true)
     {
+      DATADOC ("Data Member", name, mp)
       typedef const U T::*mp_t;
 
       // Add to __propget in class and const tables.
@@ -674,6 +783,7 @@ private:
       return *this;
     }
 
+#if 0 // unused
     //--------------------------------------------------------------------------
     /**
       Add or replace a property member.
@@ -785,7 +895,7 @@ private:
 
       return *this;
     }
-
+#endif
     //--------------------------------------------------------------------------
     /**
         Add or replace a member function.
@@ -793,16 +903,43 @@ private:
     template <class MemFn>
     Class <T>& addFunction (char const* name, MemFn mf)
     {
+      FUNDOC("Member Function", name, MemFn)
       CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
       return *this;
     }
 
+    template <class MemFn>
+    Class <T>& addPtrFunction (char const* name, MemFn mf)
+    {
+      FUNDOC("Member Pointer Function", name, MemFn)
+      CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
+      return *this;
+    }
+
+    template <class MemFn>
+    Class <T>& addWPtrFunction (char const* name, MemFn mf)
+    {
+      FUNDOC("Member Weak Pointer Function", name, MemFn)
+      CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
+      return *this;
+    }
+
+    template <class MemFn>
+    Class <T>& addRefFunction (char const* name, MemFn mf)
+    {
+      FUNDOC("Member Function RefReturn", name, MemFn)
+      CFunc::CallMemberRefFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
+      return *this;
+    }
+
+
     //--------------------------------------------------------------------------
     /**
         Add or replace a member lua_CFunction.
     */
     Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*))
     {
+      DATADOC ("C Function", name, mfp)
       typedef int (T::*MFP)(lua_State*);
       assert (lua_istable (L, -1));
       new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
@@ -812,12 +949,24 @@ private:
       return *this;
     }
 
+    // custom callback - extend existing classes
+    // with non-class member functions (e.g STL iterator)
+    Class <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
+    {
+      DATADOC ("Ext C Function", name, fp)
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, fp, 0);
+      rawsetfield (L, -3, name); // class table
+      return *this;
+    }
+
     //--------------------------------------------------------------------------
     /**
         Add or replace a const member lua_CFunction.
     */
     Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*) const)
     {
+      DATADOC ("Const C Member Function", name, mfp)
       typedef int (T::*MFP)(lua_State*) const;
       assert (lua_istable (L, -1));
       new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
@@ -829,6 +978,29 @@ private:
       return *this;
     }
 
+    /**
+        Add or replace a static const data
+    */
+    template <typename U>
+      Class <T>& addConst (char const* name, const U val)
+      {
+        DATADOC ("Constant/Enum Member", name, val)
+        assert (lua_istable (L, -1));
+
+        rawgetfield (L, -1, "__propget"); // static
+        new (lua_newuserdata (L, sizeof (val))) U (val);
+        lua_pushcclosure (L, &CFunc::getConst <U>, 1);
+        rawsetfield (L, -2, name);
+        lua_pop (L, 1);
+
+        rawgetfield (L, -1, "__propset"); // static
+        lua_pushstring (L, name);
+        lua_pushcclosure (L, &CFunc::readOnlyError, 1);
+        rawsetfield (L, -2, name);
+        lua_pop (L, 1);
+        return *this;
+      }
+
     //--------------------------------------------------------------------------
     /**
       Add or replace a primary Constructor.
@@ -843,6 +1015,7 @@ private:
     template <class MemFn, class C>
     Class <T>& addConstructor ()
     {
+      FUNDOC("Constructor", "", MemFn)
       lua_pushcclosure (L,
         &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0);
       rawsetfield(L, -2, "__call");
@@ -853,14 +1026,303 @@ private:
     template <class MemFn>
     Class <T>& addConstructor ()
     {
+      FUNDOC("Constructor", "", MemFn)
       lua_pushcclosure (L,
         &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0);
       rawsetfield(L, -2, "__call");
 
       return *this;
     }
+
+    Class <T>& addVoidConstructor ()
+    {
+      return addConstructor <void (*) ()> ();
+    }
+
+    Class <T>& addEqualCheck ()
+    {
+      PRINTDOC("Member Function", _name << "sameinstance", std::string("bool"), std::string("void (*)(" + type_name <T>() + ")"))
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
+      rawsetfield (L, -3, "sameinstance");
+      return *this;
+    }
+
+    template <class U>
+    Class <T>& addCast (char const* name)
+    {
+      PRINTDOC("Cast", _name << name,
+          type_name< U >(),
+          type_name< U >() << " (" << type_name< T >() << "::*)()")
+
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, &CFunc::CastClass <T, U>::f, 0);
+      rawsetfield (L, -3, name); // class table
+
+      lua_pushcclosure (L, &CFunc::CastConstClass <T, U>::f, 0);
+      rawsetfield (L, -4, name); // const table
+      return *this;
+    }
+
+  };
+
+  /** C Array to/from table */
+  template <typename T>
+  class Array : virtual public ClassBase
+  {
+  public:
+    Array (char const* name, Namespace const* parent) : ClassBase (parent->L)
+    {
+#ifdef LUABINDINGDOC
+      _parent = parent;
+      _name = parent->_name + name + ":";
+#endif
+      PRINTDOC ("[C] Array", parent->_name << name,
+          std::string(), type_name <T>() + "*")
+      PRINTDOC ("Ext C Function", _name << "array",
+          std::string(""), "int (*)(lua_State*)")
+      PRINTDOC ("Ext C Function", _name << "get_table",
+          std::string(""), "int (*)(lua_State*)")
+      PRINTDOC ("Ext C Function", _name << "set_table",
+          std::string(""), "int (*)(lua_State*)")
+      PRINTDOC("Member Function", _name << "sameinstance",
+          std::string("bool"), std::string("bool (*)(" + type_name <T>() + "*)"))
+      PRINTDOC("Member Function", _name << "offset",
+          std::string(type_name <T>() + "*"), std::string(type_name <T>() + "* (*)(unsigned int)"))
+
+      m_stackSize = parent->m_stackSize + 3;
+      parent->m_stackSize = 0;
+
+#if 0 // don't allow to duplicates handlers for same array-type
+      assert (lua_istable (L, -1));
+      lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+      if (lua_istable (L, -1)) {
+        lua_pushnil (L);
+        lua_pushnil (L);
+        return;
+      }
+      lua_pop (L, 1);
+#endif
+
+      assert (lua_istable (L, -1));
+      rawgetfield (L, -1, name);
+
+      if (lua_isnil (L, -1))
+      {
+        lua_pop (L, 1);
+
+        // register array access in global namespace
+        luaL_newmetatable (L, typeid(T).name());
+        lua_pushcclosure (L, CFunc::array_index<T>, 0);
+        lua_setfield(L, -2, "__index");
+        lua_pushcclosure (L, CFunc::array_newindex<T>, 0);
+        lua_setfield(L, -2, "__newindex");
+        lua_pop (L, 1);
+
+        createConstTable (name);
+        lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
+        rawsetfield (L, -2, "__gc");
+
+        createClassTable (name);
+        lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
+        rawsetfield (L, -2, "__gc");
+
+        createStaticTable (name);
+
+        // Map T back to its tables.
+        lua_pushvalue (L, -1);
+        lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
+        lua_pushvalue (L, -2);
+        lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
+        lua_pushvalue (L, -3);
+        lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
+
+        assert (lua_istable (L, -1));
+        lua_pushcclosure (L, &CFunc::getArray <T>, 0);
+        rawsetfield (L, -3, "array"); // class table
+
+        lua_pushcclosure (L, &CFunc::getTable <T>, 0);
+        rawsetfield (L, -3, "get_table"); // class table
+
+        lua_pushcclosure (L, &CFunc::setTable <T>, 0);
+        rawsetfield (L, -3, "set_table"); // class table
+
+        lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
+        rawsetfield (L, -3, "sameinstance");
+
+        lua_pushcclosure (L, &CFunc::offsetArray <T>, 0);
+        rawsetfield (L, -3, "offset"); // class table
+
+      }
+      else
+      {
+        lua_pushnil (L);
+        lua_pushnil (L);
+      }
+    }
+
+    Namespace endArray ()
+    {
+      return Namespace (this);
+    }
+  };
+
+  /** Boost Weak & Shared Pointer Class Wrapper */
+  template <class T>
+  class WSPtrClass : virtual public ClassBase
+  {
+  public:
+    WSPtrClass (char const* name, Namespace const* parent)
+      : ClassBase (parent->L)
+      , weak (name, parent)
+      , shared (name, parent)
+    {
+#ifdef LUABINDINGDOC
+      _parent = parent;
+      _name = parent->_name + name + ":";
+#endif
+      PRINTDOC ("[C] Weak/Shared Pointer Class",
+          parent->_name + name,
+          std::string(), type_name <T>())
+      m_stackSize = weak.m_stackSize;
+      parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
+      lua_pop (L, 3);
+    }
+
+    WSPtrClass (char const* name, Namespace const* parent, void const* const sharedkey, void const* const weakkey)
+      : ClassBase (parent->L)
+      , weak (name, parent, weakkey)
+      , shared (name, parent, sharedkey)
+    {
+#ifdef LUABINDINGDOC
+      _parent = parent;
+      _name = parent->_name + name + ":";
+#endif
+      m_stackSize = weak.m_stackSize;
+      parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
+      lua_pop (L, 3);
+    }
+
+    template <class MemFn>
+    WSPtrClass <T>& addFunction (char const* name, MemFn mf)
+    {
+      FUNDOC ("Weak/Shared Pointer Function", name, MemFn)
+      set_weak_class ();
+      CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
+
+      set_shared_class ();
+      CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
+      return *this;
+    }
+
+    template <class MemFn>
+    WSPtrClass <T>& addRefFunction (char const* name, MemFn mf)
+    {
+      FUNDOC ("Weak/Shared Pointer Function RefReturn", name, MemFn)
+      set_weak_class ();
+      CFunc::CallMemberRefWPtrFunctionHelper <MemFn>::add (L, name, mf);
+
+      set_shared_class ();
+      CFunc::CallMemberRefPtrFunctionHelper <MemFn>::add (L, name, mf);
+      return *this;
+    }
+
+    template <class MemFn>
+    WSPtrClass <T>& addConstructor ()
+    {
+      FUNDOC ("Weak/Shared Pointer Constructor", "", MemFn)
+      set_weak_class ();
+      lua_pushcclosure (L,
+          &weak. template ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::weak_ptr<T> >, 0);
+      rawsetfield(L, -2, "__call");
+
+      set_shared_class ();
+      lua_pushcclosure (L,
+          &shared. template ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::shared_ptr<T> >, 0);
+      rawsetfield(L, -2, "__call");
+      return *this;
+    }
+
+    WSPtrClass <T>& addVoidConstructor ()
+    {
+      return addConstructor <void (*) ()> ();
+    }
+
+    WSPtrClass <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
+    {
+      DATADOC ("Weak/Shared Ext C Function", name, fp)
+      set_weak_class ();
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, fp, 0);
+      rawsetfield (L, -3, name); // class table
+
+      set_shared_class ();
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, fp, 0);
+      rawsetfield (L, -3, name); // class table
+
+      return *this;
+    }
+
+    template <class U>
+    WSPtrClass <T>& addCast (char const* name)
+    {
+      PRINTDOC("Weak/Shared Pointer Cast", _name << name,
+          type_name< U >(),
+          type_name< U >() << " (" << type_name< T >() << "::*)()")
+
+      // TODO weak ptr
+      set_shared_class ();
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, &CFunc::CastMemberPtr <T, U>::f, 0);
+      rawsetfield (L, -3, name); // class table
+      return *this;
+    }
+
+    WSPtrClass <T>& addNullCheck ()
+    {
+      PRINTDOC("Weak/Shared Null Check", _name << "isnil", std::string("bool"), std::string("void (*)()"))
+      set_weak_class ();
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, &CFunc::WPtrNullCheck <T>::f, 0);
+      rawsetfield (L, -3, "isnil"); // class table
+
+      set_shared_class ();
+      assert (lua_istable (L, -1));
+      lua_pushcclosure (L, &CFunc::PtrNullCheck <T>::f, 0);
+      rawsetfield (L, -3, "isnil"); // class table
+
+      return *this;
+    }
+
+
+    Namespace endClass ()
+    {
+      return Namespace (this);
+    }
+
+  private:
+    void set_weak_class () {
+      lua_pop (L, 3);
+      lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::weak_ptr<T> >::getStaticKey ());
+      rawgetfield (L, -1, "__class");
+      rawgetfield (L, -1, "__const");
+      lua_insert (L, -3);
+      lua_insert (L, -2);
+    }
+    void set_shared_class () {
+      lua_pop (L, 3);
+      lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::shared_ptr<T> >::getStaticKey ());
+      rawgetfield (L, -1, "__class");
+      rawgetfield (L, -1, "__const");
+      lua_insert (L, -3);
+      lua_insert (L, -2);
+    }
+    Class<boost::weak_ptr<T> > weak;
+    Class<boost::shared_ptr<T> > shared;
   };
 
+
 private:
   //----------------------------------------------------------------------------
   /**
@@ -869,11 +1331,20 @@ private:
   explicit Namespace (lua_State* L_)
     : L (L_)
     , m_stackSize (0)
+#ifdef LUABINDINGDOC
+    , _name ("")
+    , _parent (0)
+#endif
   {
     lua_getglobal (L, "_G");
     ++m_stackSize;
   }
 
+#ifdef LUABINDINGDOC
+  std::string _name;
+  Namespace const * _parent;
+#endif
+
   //----------------------------------------------------------------------------
   /**
       Open a namespace for registrations.
@@ -884,6 +1355,10 @@ private:
   Namespace (char const* name, Namespace const* parent)
     : L (parent->L)
     , m_stackSize (0)
+#ifdef LUABINDINGDOC
+    , _name (parent->_name + name + ":")
+    , _parent (parent)
+#endif
   {
     m_stackSize = parent->m_stackSize + 1;
     parent->m_stackSize = 0;
@@ -921,6 +1396,10 @@ private:
   explicit Namespace (Namespace const* child)
     : L (child->L)
     , m_stackSize (0)
+#ifdef LUABINDINGDOC
+    , _name (child->_parent ? child->_parent->_name : "")
+    , _parent (child->_parent ? child->_parent->_parent : NULL)
+#endif
   {
     m_stackSize = child->m_stackSize - 1;
     child->m_stackSize = 1;
@@ -939,6 +1418,10 @@ private:
   explicit Namespace (ClassBase const* child)
     : L (child->L)
     , m_stackSize (0)
+#ifdef LUABINDINGDOC
+    , _name (child->_parent ? child->_parent->_name : "")
+    , _parent (child->_parent ? child->_parent->_parent : NULL)
+#endif
   {
     m_stackSize = child->m_stackSize - 3;
     child->m_stackSize = 3;
@@ -958,6 +1441,10 @@ public:
   {
     m_stackSize = other.m_stackSize;
     other.m_stackSize = 0;
+#ifdef LUABINDINGDOC
+    _name = other._name;
+    _parent = other._parent;
+#endif
   }
 
   //----------------------------------------------------------------------------
@@ -1032,6 +1519,26 @@ public:
     return *this;
   }
 
+  template <typename U>
+  Namespace& addConst (char const* name, const U val)
+  {
+    DATADOC ("Constant/Enum", name, val)
+    assert (lua_istable (L, -1));
+    rawgetfield (L, -1, "__propget");
+    new (lua_newuserdata (L, sizeof (val))) U (val);
+    lua_pushcclosure (L, &CFunc::getConst <U>, 1);
+    rawsetfield (L, -2, name);
+    lua_pop (L, 1);
+
+    rawgetfield (L, -1, "__propset");
+    assert (lua_istable (L, -1));
+    lua_pushstring (L, name);
+    lua_pushcclosure (L, &CFunc::readOnlyError, 1);
+    rawsetfield (L, -2, name);
+    lua_pop (L, 1);
+    return *this;
+  }
+
   //----------------------------------------------------------------------------
   /**
       Add or replace a property.
@@ -1077,6 +1584,7 @@ public:
   template <class FP>
   Namespace& addFunction (char const* name, FP const fp)
   {
+    FUNDOC ("Free Function", name, FP)
     assert (lua_istable (L, -1));
 
     new (lua_newuserdata (L, sizeof (fp))) FP (fp);
@@ -1086,12 +1594,38 @@ public:
     return *this;
   }
 
+  template <class FP>
+  Namespace& addRefFunction (char const* name, FP const fp)
+  {
+    FUNDOC ("Free Function RefReturn", name, FP)
+    assert (lua_istable (L, -1));
+
+    new (lua_newuserdata (L, sizeof (fp))) FP (fp);
+    lua_pushcclosure (L, &CFunc::CallRef <FP>::f, 1);
+    rawsetfield (L, -2, name);
+
+    return *this;
+  }
+
+  //----------------------------------------------------------------------------
+  /**
+      Add or replace a array type
+  */
+
+  template <typename T>
+  Namespace registerArray (char const* name)
+  {
+    return Array <T> (name, this).endArray();
+  }
+
+
   //----------------------------------------------------------------------------
   /**
       Add or replace a lua_CFunction.
   */
   Namespace& addCFunction (char const* name, int (*const fp)(lua_State*))
   {
+    DATADOC ("Free C Function", name, fp)
     lua_pushcfunction (L, fp);
     rawsetfield (L, -2, name);
 
@@ -1108,6 +1642,145 @@ public:
     return Class <T> (name, this);
   }
 
+  /** weak & shared pointer class */
+  template <class T>
+  WSPtrClass <T> beginWSPtrClass (char const* name)
+  {
+    return WSPtrClass <T> (name, this)
+      .addNullCheck();
+  }
+
+  //----------------------------------------------------------------------------
+
+  template <class K, class V>
+  Class<std::map<K, V> > beginStdMap (char const* name)
+  {
+    typedef std::map<K, V> LT;
+    typedef std::pair<const K, V> T;
+
+    typedef typename std::map<K, V>::size_type T_SIZE;
+
+    return beginClass<LT> (name)
+      .addVoidConstructor ()
+      .addFunction ("empty", &LT::empty)
+      .addFunction ("size", &LT::size)
+      .addFunction ("clear", (void (LT::*)())&LT::clear)
+      .addFunction ("count", (T_SIZE (LT::*)(const K&) const)&LT::count)
+      .addExtCFunction ("add", &CFunc::tableToMap<K, V>)
+      .addExtCFunction ("iter", &CFunc::mapIter<K, V>)
+      .addExtCFunction ("table", &CFunc::mapToTable<K, V>);
+  }
+
+  template <class T>
+  Class<std::set<T> > beginStdSet (char const* name)
+  {
+    typedef std::set<T> LT;
+    return beginClass<LT> (name)
+      .addVoidConstructor ()
+      .addFunction ("clear", (void (LT::*)())&LT::clear)
+      .addFunction ("empty", &LT::empty)
+      .addFunction ("size", &LT::size)
+      .addExtCFunction ("add", &CFunc::tableToSet<T>)
+      .addExtCFunction ("iter", &CFunc::setIter<T>)
+      .addExtCFunction ("table", &CFunc::setToTable<T>);
+  }
+
+  template <unsigned int T>
+  Class<std::bitset<T> > beginStdBitSet (char const* name)
+  {
+    typedef std::bitset<T> BS;
+    return beginClass<BS> (name)
+      .addVoidConstructor ()
+      .addFunction ("reset", (BS& (BS::*)())&BS::reset)
+      .addFunction ("set", (BS& (BS::*)(size_t, bool))&BS::set)
+      .addFunction ("count", &BS::count)
+      .addFunction ("any", &BS::any)
+      .addFunction ("none", &BS::none)
+      .addFunction ("test", &BS::test)
+      .addFunction ("size", &BS::size)
+      .addExtCFunction ("add", &CFunc::tableToBitSet<T>)
+      .addExtCFunction ("table", &CFunc::bitSetToTable<T>);
+  }
+
+  template <class T>
+  Class<std::list<T> > beginConstStdList (char const* name)
+  {
+    typedef std::list<T> LT;
+    return beginClass<LT> (name)
+      .addVoidConstructor ()
+      .addFunction ("empty", &LT::empty)
+      .addFunction ("size", &LT::size)
+      .addFunction ("reverse", &LT::reverse)
+      .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
+      .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
+  }
+
+  template <class T>
+  Class<std::list<T> > beginStdList (char const* name)
+  {
+    typedef std::list<T> LT;
+    return beginConstStdList<T> (name)
+      .addFunction ("unique", (void (LT::*)())&LT::unique)
+      .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
+      .addExtCFunction ("add", &CFunc::tableToList<T, LT>);
+  }
+
+  template <class T>
+  Class<std::vector<T> > beginStdVector (char const* name)
+  {
+    typedef std::vector<T> LT;
+    typedef typename std::vector<T>::reference T_REF;
+    typedef typename std::vector<T>::size_type T_SIZE;
+
+    return beginClass<LT> (name)
+      .addVoidConstructor ()
+      .addFunction ("empty", &LT::empty)
+      .addFunction ("size", &LT::size)
+      .addFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
+      .addFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
+      .addExtCFunction ("add", &CFunc::tableToList<T, LT>)
+      .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
+      .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
+  }
+
+  //----------------------------------------------------------------------------
+
+  template <class T>
+  Class<boost::shared_ptr<std::list<T> > > beginPtrStdList (char const* name)
+  {
+    typedef std::list<T> LT;
+
+    return beginClass<boost::shared_ptr<LT> > (name)
+      .addVoidConstructor ()
+      .addPtrFunction ("empty", &LT::empty)
+      .addPtrFunction ("size", &LT::size)
+      .addPtrFunction ("reverse", &LT::reverse)
+      .addPtrFunction ("unique", (void (LT::*)())&LT::unique)
+      .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
+      .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
+      .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
+      .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
+  }
+
+  template <class T>
+  Class<boost::shared_ptr<std::vector<T> > > beginPtrStdVector (char const* name)
+  {
+    typedef std::vector<T> LT;
+    typedef typename std::vector<T>::reference T_REF;
+    typedef typename std::vector<T>::size_type T_SIZE;
+
+    return beginClass<boost::shared_ptr<LT> > (name)
+      .addVoidConstructor ()
+      .addPtrFunction ("empty", &LT::empty)
+      .addPtrFunction ("empty", &LT::empty)
+      .addPtrFunction ("size", &LT::size)
+      .addPtrFunction ("push_back", (void (LT::*)(const T&))&LT::push_back)
+      .addPtrFunction ("at", (T_REF (LT::*)(T_SIZE))&LT::at)
+      .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
+      .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
+      .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
+  }
+
   //----------------------------------------------------------------------------
   /**
       Derive a new class for registrations.
@@ -1118,8 +1791,23 @@ public:
   template <class T, class U>
   Class <T> deriveClass (char const* name)
   {
+    CLASSDOC ("[C] Derived Class", _name << name, type_name <T>(), type_name <U>())
     return Class <T> (name, this, ClassInfo <U>::getStaticKey ());
   }
+
+  template <class T, class U>
+  WSPtrClass <T> deriveWSPtrClass (char const* name)
+  {
+
+    CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::shared_ptr<T> >(), type_name <boost::shared_ptr<U> >())
+    CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::weak_ptr<T> >(), type_name <boost::weak_ptr<U> >())
+    CLASSDOC ("[C] Derived Pointer Class", _name << name, type_name <T>(), type_name <U>())
+    return WSPtrClass <T> (name, this,
+        ClassInfo <boost::shared_ptr<U> >::getStaticKey (),
+        ClassInfo <boost::weak_ptr<U> >::getStaticKey ())
+      .addNullCheck();
+  }
+
 };
 
 //------------------------------------------------------------------------------
@@ -1134,3 +1822,13 @@ inline Namespace getGlobalNamespace (lua_State* L)
 {
   return Namespace::getGlobalNamespace (L);
 }
+
+
+#undef KEYSTA
+#undef KEYEND
+#undef CLASSDOC
+#undef PRINTDOC
+#undef FUNDOC
+#undef DATADOC
+
+/* vim: set et sw=2: */