Newer
Older
Import / applications / Framework / reflection.txt


Idea
----


Make 'Objects' which have 'Properties' cleanly, and exposed to
scripting (python) and can be serialised and de-serialised.

The serialisation can work from a root object and serialise down
in to all the hierachy. And when de-serialising, it can work in
reverse to construct again the same object hierachy.
(use of classes and inheritance should still be possible)

Within C++ this requires using a sub-set of functionality and some
manual exposing of the meta-data for the reflection. Ideally
the pimpl pattern can still be used and the implementation be
hidden inside the cpp files, whist exposing a clean header file
for use of the same objects from C++.


Objectives
----------

1) Objects
2) Tree of Objects
3) Classes
4) Tree of Classes
3) Scriptable
4) Serializable (generic tree walking)
5) Cold de-serializable (object re-creation)
6) Native performance of algorithms
7) Pimpl implementation hiding and fast compiling
8) Shared pimpl pointers?


Example:


-- exampleObject.h --


class ExampleObject
{
public:
   void setName(std::string a_name);
   std::string name();

   void setHeight(int a_height);
   int height();

private:
   struct pImpl;
   std::unique_ptr<pImpl> m_pImpl;
};



-- exampleObject.cpp --


struct ExampleObject::pImpl
{
   std::string m_name;
   int         m_height;
};


META_DEFINE_CLASS( ExampleObject )
{
   ADD_MEMBER( m_name );
   ADD_MEMBER( m_height );
}


-------------

Observations:
	Duplicated redundant typing:
		The name and height are written 3 times to describe the property
	We want two things, properties and methods

------------


DEFINE_CLASS( ExampleObject )
{
   ADD_PROPERTY( std::string,  name   );
   ADD_PROPERTY( int,          height );
   ADD_PROPERTY_READONLY( int, blah   );

   ADD_METHOD( int doSomething() };
   ADD_METHOD( void execute(int) };
}

-----
The above should be enough to create the object definition, pimpl etc
-----

class BaseClass
{
private:
   void* pimpl;
};

class Obj : public BaseClass
{
private:
  // doesn't need a pimpl pointer, uses base class one
};


trick is, how to only allocate it once??
problem is allocation happens from inner class to outer
Not a problem if we can work out the derived class's pimpl size


class BaseClass
{
public:
   BaseClass(size_t a_derivedPimplSize = 0) : pimpl(new char[a_derivedPimplSize]) {}
protected:
   void* pimpl;
};


class Obj : public BaseClass
{
public:
   Obj(size_t a_derivedPimplSize = 0) : BaseClass(sizeof(Obj::pimpl) + a_derivedPimplSize) {}

   // doesn't need a pimpl pointer, uses base class's one
};


class Derived : public Obj
{
public:
   Derived(size_t a_derivedPimplSize = 0) : Obj(sizeof(Obj::pimpl) + a_derivedPimplSize) {}

   // doesn't need a pimpl pointer, uses base class's one
};


however now the trick is knowing the offset in to the base class's pimpl
this will be static though, it doesn't need to be stored inside each object.
I'm assuming multiple inheritance isn't allowed and any complication from this
can be ignored. Instead of multiple inheritance, use object composition


For the object tree, we need to store parent pointers. Every object will need
an owner or parent. If none given, it will belong to the root node.


So at first a root node object is created


class BaseClass
{
public:
   BaseClass(BaseClass* a_parent = 0, size_t a_derivedPimplSize = 0) : pimpl(new char[a_derivedPimplSize])
   {
      setParent((a_parent) ? a_parent : rootObject);
   }
   ~BaseClass()
   {
      delete pimpl;
   }

   ADD_PROPERTY(parent);
protected:
   void* pimpl;
};


class BaseObject
{
public:
	BaseObject(BaseObject* a_parent = 0, 
};