1 module ut.refraction.vtable;
2 
3 
4 import ut;
5 import tardy.refraction;
6 import std.meta: AliasSeq;
7 static import std.traits;  // because refract uses it
8 
9 
10 struct Struct {
11     import modules.types: Point;
12 
13     int const_() const;
14     Point point() const;
15     int pure_() const pure;
16     void inc(int amount);
17     void safeInc(int amount) @safe;
18     void scopeInc(int amount) @safe scope;
19 }
20 
21 alias functions = AliasSeq!(
22     Struct.const_,
23     Struct.point,
24     Struct.pure_,
25     Struct.inc,
26     Struct.safeInc,
27     Struct.scopeInc,
28 );
29 
30 //pragma(msg, "");
31 static foreach(F; functions) {
32     // pragma(msg, "F: ", std.traits.fullyQualifiedName!F, "\t\t", vtableEntryRecipe!F);
33     mixin(vtableEntryRecipe!F, " ", vtableEntryId!F, ";");
34     // pragma(msg, "");
35 }
36 // pragma(msg, "");
37 
38 
39 @("return")
40 @safe pure unittest {
41     static foreach(F; functions) {
42         shouldMatchReturnType!F;
43     }
44 }
45 
46 private void shouldMatchReturnType(alias F)() {
47     import std.traits: ReturnType;
48     import std.conv: text;
49     enum vtableEntry = vtableEntryId!F;
50     static assert(is(ReturnType!F == ReturnType!(mixin(vtableEntry))),
51                   text("Wrong return type for " ~ __traits(identifier, F),
52                        ": expected ", ReturnType!F.stringof, " but got ", ReturnType!(mixin(vtableEntry)).stringof));
53 }
54 
55 
56 @("self.mutable")
57 @safe pure unittest {
58     shouldMatchSelf!(Struct.inc, void*);
59 }
60 
61 
62 @("self.const")
63 @safe pure unittest {
64     shouldMatchSelf!(Struct.const_, const(void)*);
65 }
66 
67 
68 private void shouldMatchSelf(alias F, T)() {
69     import std.conv: text;
70     import std.traits: Parameters;
71 
72     enum vtableEntry = vtableEntryId!F;
73     alias params = Parameters!(mixin(vtableEntry));
74 
75     static assert(is(params[0] == T),
76                   text("Wrong self type for ", __traits(identifier, F),
77                        ": expected ", T.stringof, " but got ", params[0].stringof));
78 }
79 
80 
81 @("type.struct.inc")
82 @safe pure unittest {
83     static assert(is(typeof(mixin(vtableEntryId!(Struct.inc))) == void function(void*, int) @system));
84 }
85 
86 
87 @("type.struct.safeInc")
88 @safe pure unittest {
89     alias T = typeof(mixin(vtableEntryId!(Struct.safeInc)));
90     static assert(is(T == void function(void*, int) @safe));
91 }
92 
93 
94 // FIXME: dmd bug
95 @("type.struct.scopeInc")
96 @safe pure unittest {
97     alias T = typeof(mixin(vtableEntryId!(Struct.scopeInc)));
98     //static assert(is(T == void function(scope void*, int) @safe));
99 }
100 
101 
102 private string vtableEntryId(alias F)()
103     in(__ctfe)
104     do
105 {
106     return "asvtable_" ~ __traits(identifier, F);
107 }