Chances of D getting proper runtime reflection?

Martin Nowak dawg at dawgfoto.de
Wed Aug 24 20:31:04 PDT 2011


On Wed, 24 Aug 2011 08:49:19 +0200, Jacob Carlborg <doob at me.com> wrote:

> On 2011-08-24 01:34, Martin Nowak wrote:
>> On Tue, 23 Aug 2011 17:03:12 +0200, Jacob Carlborg <doob at me.com> wrote:
>>
>>> On 2011-08-23 16:38, Andrei Alexandrescu wrote:
>>>> On 8/23/11 12:55 AM, Jacob Carlborg wrote:
>>>>> On 2011-08-23 08:52, Andrei Alexandrescu wrote:
>>>>>> On 8/22/11 11:30 PM, Jacob Carlborg wrote:
>>>>>>> Ok, then I just change "register" to a static method.
>>>>>>
>>>>>> A static method of whom?
>>>>>>
>>>>>> Andrei
>>>>>
>>>>> Well, "register" currently an instance method of Serializer so I  
>>>>> would
>>>>> change it to be a static method of Serializer.
>>>>
>>>> I think the ability of a class to be serialized would be independent  
>>>> of
>>>> the notion of a serializer. To me, "this class is serializable" really
>>>> means "this class has metadata associated with it that allows  
>>>> interested
>>>> parties to serialize it". But perhaps this is splitting hairs.
>>>>
>>>> Andrei
>>>
>>> You don't want to have it in the class and don't want it in the
>>> serializer. I mean, it needs to be stored somewhere and I thought that
>>> a static method in Serializer would better than a completely global
>>> function.
>>>
>>> Are you thinking about having another serialization library that can
>>> use this information as well? I'm not sure if that's good idea,
>>> different serialization implementations might need to do very
>>> different things with the information.
>>>
>>
>> I think the idea is to register something that provides the needed
>> information at runtime and separate that from the serializer because
>> it's useful on it's own.
>>
>> Could be as simple as:
>>
>> interface Serializable {
>> string[] allMembers();
>> Member getMember(string name);
>> }
>>
>> interface Member {
>> final void set(T)(T t) {
>> setRaw(typeid(t), cast(void*)&t);
>> }
>> void setRaw(TypeInfo ti, void* p);
>>
>> final T get(T)() {
>> return *cast(T*)enforce(getRaw(typeid(T)));
>> }
>> void* getRaw();
>> }
>>
>> It's clearly interesting to make this available if you implement
>> something along that line.
>> But I would not overstress it for there are dozen of different
>> requirements profiles (performance, versioning, pre/post-serialize  
>> hooks).
>> So even if I am interested to use something similar for undo/redo or
>> delta creation, I'm not sure one can find a one-for-all solution here
>> (i.e. the above approach seems way to dynamic for my needs).
>> Maybe Variant could help in setting/getting values.
>>
>> martin
>
> As soon as "setRaw" is called all static information is gone. I need to  
> be able to iterate over T.tupleof.
>

Not sure, I get what you mean.
Let me try to clarify this:

static Serializeable[TypeInfo] infos;

void register(T)() {
	infos[typeid(T)] = new SerializableImpl!T();
}

// Serializable binds static reflection to dynamic interface
class SerializeableImpl!T : Serializable {
	string[] allMembers() { array(__traits(allMembers, T)); }
	Member getMember(string name) {
	  if (mi = findMemberInfo(name)) {
             auto res = mi.clone(); // found immutable info, now create  
wrapper
	    res.address = this + mi.offset; // tell the clone where to find
	    return res;
	  }
	  return null;
	}
}

// Member binds purely static info to dynamic interface and an actual  
address
class MemberInfo!T : Member {
   override void setRaw(TypeInfo ti, void* p) {
     if (ti is typeid(T))
       *address = *cast(T*)p;
   }

   override void* getRaw(TypeInfo ti) {
     if (ti is typeid(T))
       return address;
   }

   T* address;
}

In object.d there is a lot of this partly implemented. Have a closer look  
at OffsetTypeInfo and MemberInfo_field.
You can definitely get all the information the compiler could provide for  
RTTI at compile time. If you try hard
enough you may even be able to store them at compile time. The only  
difference remaining is that you could not
access it through instance.classinfo but have to use a table lookup.

It would be great if there was a way to append data to classinfo at  
compile time. Like an extra pointer or an array of ubyte that can be set.
martin


More information about the Digitalmars-d mailing list