On Wed, 12 Aug 2009 17:03:17 -0700, Bill Baxter wrote: > On Wed, Aug 12, 2009 at 4:52 PM, Rory McGuire<rjmcgu...@gmail.com> > wrote: >> Here is some code I wrote which enables wrapping a proxy around an >> object. I am using it for my serialization library. It works in >> D1(1.046) and D2 (2.031) >> >> Posting it here for reference by all before I add to much of the stuff >> specific to my use, should make it easier to follow. >> >> usage: new ProxyClass!(A, cast(string)"getInt setInt getString"); would >> implement the methods getInt setInt and getString from A in the new >> class. >> >> the code below will fail to compile but not before printing the >> generated code to stdout. >> >> Shin Fujishiro has made some new templates for D2 which will make it so >> I can get rid of the "setInt getInt getString" part which would make >> the usage for D2: new ProxyClass!A; >> which would be great! >> >> -Rory >> >> ============================================ // author: Rory McGuire, >> rjmcgu...@gmail.com import std.stdio; >> import std.typetuple; >> import std.traits; >> import std.metastrings; >> >> //import serializer; >> >> // this CTF from somewhere on news.digitalmars.com string[] >> splitFuncs(string str) { >> string[] res; >> while (str.length > 0) { >> while (str.length > 0 && (' ' == str[0] || ',' == str[0])) { >> str = str[1..$]; >> } >> int to = 0; >> for (; to < str.length && str[to] != ' ' && str[to] != ','; >> ++to) >> {} >> if (to > 0) { >> res ~= str[0..to]; >> str = str[to..$]; >> } >> } >> return res; >> } >> >> string MethodTypeTuple_mixin(alias a)(string[] methods) { >> string ret = "TypeTuple!("~ >> "typeof(&C.init."~methods[0]~")"; foreach (method; >> methods[1..$]) { >> ret ~= ",typeof(&C.init."~method~")"; >> } >> ret ~= ")"; >> return ret; >> } >> >> >> >> // test case >> >> class A { >> int a; >> this(int a) { >> this.a = a; >> } >> int getInt(string intname) { >> return a; >> } >> >> void setInt(int i) { >> a = i; >> } >> string getString(string s) { >> return s ~"1234"; >> } >> } >> >> >> string ProxyMethods_mixin(alias C, string methodstr)() { >> string ret; >> foreach(i, t; mixin(MethodTypeTuple_mixin!(C)(splitFuncs >> (methodstr)))) { >> // output function header >> ret ~= "\t"~ReturnType!(t).stringof ~" "~ >> splitFuncs >> (methodstr)[i]~"("; >> // output first arg >> ret ~= ParameterTypeTuple!(t)[0].stringof~" >> arg"; // output remainder of args >> foreach (j, t1; ParameterTypeTuple!(t)[1..$]) { >> ret ~= ","~t1.stringof~" >> arg"~std.metastrings.ToString!(j); >> } >> // output body >> ret ~= ") {\n"; >> // output serialization code >> // send method name >> ret ~= "\t\twritefln(\"serialize docall id\"); >> // the >> method call byte id\n"; >> ret ~= "\t\tbuffer ~= >> serialize!(string)(\""~splitFuncs >> (methodstr)[i]~"\", s_state); /+ the method name +/\n"; >> // send args >> ret ~= "\t\tbuffer ~= serialize!("~ >> ParameterTypeTuple!(t) >> [0].stringof~")(arg, s_state); /+ the first argument +/\n"; >> foreach (j, t1; ParameterTypeTuple!(t)[1..$]) { >> ret ~= "\t\tbuffer ~= serialize!("~ >> t1.stringof >> ~")(arg"~ToString!(j)~", s_state); /+ argument "~ToString!(j)~" +/\n"; >> } >> // receive return type >> static if (!is(ReturnType!(t) == void)) { >> ret ~= "\t\treturn deserialize!("~ >> ReturnType! >> (t).stringof ~")(buffer, des_state);\n"; >> } >> ret ~= "\t}\n"; >> } >> return ret; >> } >> >> >> class ProxyClass(alias C, string methodstr) { >> ubyte[] buffer; >> mixin(ProxyMethods_mixin!(C,methodstr)()); >> pragma(msg, "class ProxyClass!("~C.stringof~", >> \""~ >> methodstr ~"\") {\n\tubyte[] buffer;\n SerializerState s_state;\n >> DeserializerState des_state;\n this() {s_state = new >> SerializerState(); des_state = new DeserializerState(); }\n\n"~ >> ProxyMethods_mixin! (C,methodstr)() ~"\n}\n"); >> >> } >> >> void main() { >> auto pc = new ProxyClass!(A, cast(string)"getInt setInt >> getString"); >> writefln("ProxyClass: "~ pc.getString("asdf")); >> } >> >> > That code is screaming for some macros. Or variable interpolation at > least. > > --bb
Where would you propose that one would use 'macro'?