The OpenD Programming Language

1 /++
2 $(H1 Type Information)
3 
4 Type Information implementation compatible with BetterC mode.
5 
6 Copyright: 2020 Ilia Ki, Kaleidic Associates Advisory Limited, Symmetry Investments
7 Authors: Ilia Ki
8 
9 Macros:
10 NDSLICE = $(REF_ALTTEXT $(TT $2), $2, mir, ndslice, $1)$(NBSP)
11 T2=$(TR $(TDNW $(LREF $1)) $(TD $+))
12 +/
13 module mir.type_info;
14 
15 /++
16 +/
17 struct mir_type_info
18 {
19     ///
20     extern(C)
21     void function(void*) @safe pure nothrow @nogc destructor;
22     /++
23     Note: Negative values are used for classes to indicate that 
24     +/
25     int size;
26 }
27 
28 /++
29 +/
30 ref immutable(mir_type_info) mir_get_type_info(T)() @trusted
31 {
32     import std.traits: Unqual, hasElaborateDestructor;
33 
34     static if (is(T == class))
35         enum sizeof = __traits(classInstanceSize, T);
36     else
37         enum sizeof = T.sizeof;
38 
39     static if (!is(T == Unqual!T))
40     {
41         return mir_get_type_info!(Unqual!T);
42     }
43     else
44     static if (hasElaborateDestructor!T)
45     {
46         import std.traits: SetFunctionAttributes, functionAttributes;
47         alias fun = void function(void*) @safe pure nothrow @nogc;
48         extern(C)
49         static void destroy_impl(void* ptr) nothrow
50         {
51             static if (is(T == class))
52                 T inst() return @trusted
53                 {
54                     return cast(T)ptr;
55                 }
56             else
57                 ref T inst() return @trusted
58                 {
59                     return *cast(T*)ptr;
60                 }
61             version(assert)
62                 destroy!true(inst());
63             else
64                 destroy!false(inst());
65         }
66 
67         static immutable ti = mir_type_info(cast(SetFunctionAttributes!(fun, "C", functionAttributes!fun))&destroy_impl, sizeof);
68         return ti;
69     }
70     else
71     {
72         return .mir_get_type_info!sizeof;
73     }
74 }
75 
76 /++
77 +/
78 ref immutable(mir_type_info) mir_get_type_info(uint sizeof)()
79 {
80     static immutable ti = mir_type_info(null, sizeof);
81     return ti;
82 }
83 
84 package template hasDestructor(T)
85 {
86     import std.traits: Unqual;
87 
88     static if (is(T == struct))
89     {
90         static if (__traits(hasMember, Unqual!T, "__xdtor"))
91             enum hasDestructor = __traits(isSame, Unqual!T, __traits(parent, T.init.__xdtor));
92         else
93             enum hasDestructor = false;
94     }
95     else
96     static if (is(T == class))
97     {
98         enum hasDestructor = __traits(hasMember, Unqual!T, "__xdtor");
99     }
100     else
101     {
102         enum hasDestructor = false;
103     }
104 }
105 
106 package const(void)* mir_get_payload_ptr(T)()
107 {
108     import std.traits: Unqual;
109 
110     static if (!is(T == Unqual!T))
111     {
112         return mir_get_payload_ptr!(Unqual!T);
113     }
114     else
115     static if (is(T == class))
116     {
117         return typeid(T).initializer.ptr;
118     }
119     else
120     static if (__traits(isZeroInit, T) || __traits(isFloating, T))
121     {
122         return null;
123     }
124     else
125     {
126         static immutable payload = T.init;
127         return &payload;
128     }
129 }