Runtime reflection idea
Adam D. Ruppe
destructionator at gmail.com
Sun Jun 2 08:10:09 PDT 2013
On Sunday, 2 June 2013 at 13:28:28 UTC, Rainer Schuetze wrote:
> and TypeInfo.rtInfo() would then return a pointer to RTInfoData
> instead of void*. This doesn't make it modifiable from outside
> object.di, but I have no idea how that could be possible to
> begin with (without recompiling the runtime library).
I think I have something figured out:
use side:
// i'll use this as a UDA
struct InfoStruct {
string info;
}
// and this as the template extension
struct MoreRtInfo {
string amazing;
}
@CustomInfo!(InfoStruct("info struct data")) // UDA style, goes
into an array
class RTTest {
// template style, goes in a special member
static template userRtInfo(This) {
static __gshared i = MoreRtInfo("amazingness");
enum userRtInfo = &i;
}
}
Retrieve:
auto info = typeid(RTTest).rtInfo();
if(info is null)
throw new Exception("wtf");
auto urtInfo = info.userRtInfo; // this is from the
template..
if(urtInfo is null)
write("urtInfo == null\n");
else {
// it comes out as a void*, so we have to cast it
back.
auto urt = cast(immutable(MoreRtInfo)*) urtInfo;
write("cool ",urt.amazing,"\n");
}
// and this is fetching the CustomInfo UDA
auto cd = info.getCustomInfo!InfoStruct;
if(cd is null) // it returns a InfoStruct*, like AA's in
operator
write("InfoStruct is null\n");
else
write(cd.info, "\n");
And the implementation side in object.d:
struct MoreTypeInfo {
// other stuff druntime is free to declare
hash_t hash;
string stringOf;
// holder for the template thing
immutable(void)* userRtInfo;
// holder for the UDA thing
immutable(CustomTypeInfoExtension)[] customInfo;
// helper for the UDA get
immutable(T)* getCustomInfo(T)() immutable {
auto hash = typeid(T); // typehash!T;
foreach(ci; customInfo) {
if(ci.typeOfData == hash)
return
cast(immutable(T)*) ci.data();
}
return null;
}
}
// instantiates the T.userRtInfo, if possible
template urtInfo(T) {
static if (__traits(compiles, { auto a =
cast(immutable(void)*) T.userRtInfo!T; }))
enum urtInfo = cast(immutable(void)*)
T.userRtInfo!T;
else
enum urtInfo = null;
}
template RTInfo(T) {
__gshared static immutable minfo = MoreTypeInfo(
// stuff druntime is free to add
typehash!T, T.stringof,
// the user defined template
urtInfo!T,
// getting the UDA stuff
getCustomInfoInternal!T);
enum RTInfo = &minfo;
}
// finally, helpers in getting the UDAs, I posted this
before too
struct CustomTypeInfoExtension {
TypeInfo typeOfData;
// ctfe complained when I tried to just do
&static_data
// so instead this little function helper does it
for us
void* function() data;
}
immutable(CustomTypeInfoExtension)[]
getCustomInfoInternal(T)() {
if(__ctfe) {
//bool[hash_t] seen;
immutable(CustomTypeInfoExtension)[] ext;
foreach(attr; __traits(getAttributes, T))
static if(is(typeof(attr) ==
CustomTypeInfoExtension)) {
//auto hash =
attr.typeOfData.rtInfo.hash;
//if(hash in seen)
//assert(0,
"repeated data");
//seen[hash] = true;
ext ~= cast(immutable)
attr;
}
return ext;
} else return null;
}
// this is the user uses: @CustomInfo!(something)
template CustomInfo(alias T) {
__gshared static data = T;
void* getRaw() { return cast(void*) &data; }
enum CustomInfo = CustomTypeInfoExtension(
typeid(typeof(data))/*typehash!(typeof(data))*/, &getRaw);
}
> Unfortunately the compiler sometimes doesn't force the
> generation of RTInfo, but sets the m_rtInfo to 0 or 1 depending
> on whether the Type contains pointers or not. I always wanted
> to figure out why that happens...
weird
More information about the Digitalmars-d
mailing list