1 module betterc.interfaces;
2 
3 template getParams (alias fn) 
4 {
5 	static if ( is(typeof(fn) params == __parameters) )
6     	alias getParams = params;
7 }
8 
9 enum isMethodImplemented(T, string member, FuncType)()
10 {
11     bool ret;
12     static foreach(overload; __traits(getVirtualMethods, T, member))
13         if(is(typeof(overload) == FuncType) && !__traits(isAbstractFunction, overload))
14             ret = true;
15     return ret;
16 }
17 
18 
19 T New(T, Args...)(Args args)
20 {
21     import core.stdc.stdlib:malloc;
22     import core.lifetime:emplace;
23     align(__traits(classInstanceAlignment, T))
24 	void[] baseMem = malloc(__traits(classInstanceSize, T))[0..__traits(classInstanceSize, T)];
25 
26     T ret = cast(T)baseMem.ptr;
27     emplace!T(ret, args);
28     return ret;
29 }
30 
31 void Destroy(T)(ref T target)
32 {
33     import core.stdc.stdlib:free;
34     destroy(target);
35     free(cast(void*)target);
36     target = null;
37 }
38 
39 
40 
41 ///Needs correct linkage for working with D custom types such as string
42 package string linkage(alias sym)()
43 { 
44     return "extern ("~__traits(getLinkage, sym)~")";
45 }
46 
47 ///Attributes such as `ref` and `const` modify the return type, so, they need to exist
48 package string attributes(alias sym)()
49 {
50     string ret = "";
51     static foreach(attr; __traits(getFunctionAttributes, sym))
52         ret~= attr~ " ";
53     return ret;
54 }
55 
56 enum GenCPPInterface(Self, itf) =  ()
57 {
58     string ret = "class _" ~ __traits(identifier, itf)~"Impl : itf {" ~ q{ extern(C++):
59             Self self;
60             this(Self self){this.self = self;}
61             };
62     
63     import std.traits;
64     static foreach(fn; __traits(allMembers, itf))
65     {{
66         string mem = "__traits(getMember, itf, \""~ fn~ "\")";
67         string retT = "ReturnType!("~mem~")";
68         string params = "getParams!("~mem~")";
69 
70         ret~= linkage!(__traits(getMember, itf, fn)) ~ " "  ~  attributes!(__traits(getMember, itf, fn)) ~" override " ~ retT ~ " " ~ fn ~ ("("~params~")") ~ "{"~
71             "return (cast(Self)self)."~fn~"(__traits(parameters));}";
72     }}
73     return ret ~ "}";
74 }();
75 
76 extern(C++) abstract class CppObject
77 {
78     this(){initialize();}
79     void initialize(){}
80 }
81 
82 extern(C++) class CppInterface(Self, Interfaces...) : CppObject
83 {
84     static foreach(itf; Interfaces)
85     {
86         mixin(q{private itf },  ("_"~__traits(identifier, itf)) ~ ";");
87     }
88         
89     override void initialize()
90     {
91         import std.traits:ReturnType;
92         static foreach(itf; Interfaces)
93         {
94             mixin(GenCPPInterface!(Self, itf));
95             mixin( ("_"~__traits(identifier, itf)) ~(" =  New!(_" ~__traits(identifier, itf) ~ "Impl)(cast(Self)this);"));
96         }
97     }
98     
99     
100     T getInterface(T)()
101     {
102         static if(__traits(hasMember, Self, "_"~T.stringof))
103             return mixin("_",T.stringof);
104         else static if(is(T == Self))
105 			return cast(Self)this;
106 		else return null;
107     }
108 
109 	~this()
110 	{
111 		import core.stdc.stdlib;
112 		static foreach(itf; Interfaces)
113 		{{
114 			alias mem = __traits(getMember, Self, "_"~itf.stringof);
115 			destroy(mem);
116 			free(cast(void*)mem);
117             mem = null;
118 		}}
119 	}
120 }
121 
122 
123 extern(C++) class CppExtend(Self, Target, Interfaces...) : CppObject
124 {
125 
126     mixin(q{private Target } ~ ("_"~__traits(identifier, Target))~";");
127     static foreach(itf; Interfaces)
128     {
129         mixin(q{private itf },  ("_"~__traits(identifier, itf)) ~ ";");
130     }
131         
132     override void initialize()
133     {
134         import std.traits:ReturnType;
135         mixin("_"~__traits(identifier, Target)) = New!Target();
136         static foreach(itf; Interfaces)
137         {
138             mixin(GenCPPInterface!(Self, itf));
139             mixin( ("_"~__traits(identifier, itf)) ~(" =  New!(_" ~__traits(identifier, itf) ~ "Impl)(cast(Self)this);"));
140         }
141     }
142     
143     
144     T getInterface(T)()
145     {
146         static if(is(T == Target))
147             return mixin("_"~__traits(identifier, Target));
148         else static if(__traits(hasMember, Self, "_"~T.stringof))
149             return mixin("_",T.stringof);
150         else static if(is(T == Self))
151 			return cast(Self)this;
152 		else return mixin("_"~__traits(identifier, Target)).getInterface!T;
153     }
154 
155     //Forward base class methods
156     import std.traits:ReturnType;
157     static foreach(mem; __traits(allMembers, Target))
158     {
159         static foreach(ov; __traits(getVirtualMethods, Target, mem))
160         {
161             static if(!__traits(hasMember, Self, mem) || !isMethodImplemented!(Self, mem, typeof(ov)))
162             {
163                 mixin(linkage!ov ~" " ~attributes!(ov)~ " ReturnType!(ov) " ~ mem ~ "(getParams!(ov))"~
164                 "{ return " ~ ("_"~__traits(identifier, Target)) ~ "." ~mem ~ "(__traits(parameters));}");
165             }
166         }
167     }
168 
169 	~this()
170 	{
171 		import core.stdc.stdlib;
172         {
173             alias mem = __traits(getMember, Self, "_"~__traits(identifier, Target));
174             destroy(mem);
175             free(cast(void*)mem);
176             mem = null;
177         }
178 		static foreach(itf; Interfaces)
179 		{{
180 			alias mem = __traits(getMember, Self, "_"~itf.stringof);
181 			destroy(mem);
182 			free(cast(void*)mem);
183             mem = null;
184 		}}
185 	}
186 }