Bill Baxter <wbax...@gmail.com> wrote: > On Mon, Nov 9, 2009 at 4:09 PM, Walter Bright > <newshou...@digitalmars.com> wrote: >> Looks like Bill Baxter is giving a presentation on D Nov. 18! >> >> http://www.nwcpp.org/ > > Yep, that's right, and I'd be quite grateful to you smart folks here > if you could share your meta-programming favorites with me! If > you've got a real-world example of meta-programming in D that you > think is particularly handy, then please send it my way > > I'm looking for small-but-useful things that are easy to explain, and > make something easier than it would be otherwise. Things like places > where static if can save your butt, or loop unrolling, and passing > code snippets to functions like in std.algorithm. > > Things like a compile-time raytracer or regexp parser (though quite > cool!) are not what I'm after. Too involved for a short talk. > > --bb >
I've use the code below to generate wrappers for my hessian serialization implementation. its not all absolutely necessary but is only 130 lines. import std.stdio; import std.typetuple; import std.traits; import std.metastrings; 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\t//serialize!(string)(\""~splitFuncs(methodstr)[i]~"\"); /+ the method name +/\n"; // send args ret ~= "\t\t//serialize!("~ ParameterTypeTuple!(t)[0].stringof~") (arg); /+ the first argument +/\n"; foreach (j, t1; ParameterTypeTuple!(t)[1..$]) { ret ~= "\t\t//serialize!("~ t1.stringof ~")(arg"~ToString!(j)~"); / + argument "~ToString!(j)~" +/\n"; } // receive return type static if (!is(ReturnType!(t) == void)) { pragma(msg, "WARNING: this will always result in Range violation due to no real data. THIS IS JUST A DEMO"); pragma(msg, "\t\t need to implement the actual send/receive"); ret ~= "\t\t//return deserialize!("~ ReturnType!(t).stringof ~") (buffer);\n"; // this is just here to make it still compile even though I've commented out the real deserialize return above static if (is(ReturnType!(t) == int)) { ret ~= "\t\treturn 0;\n"; } else { ret ~= "\t\treturn \"\";\n"; } } ret ~= "\t}\n"; } return ret; } string ProxyClass_mixin(alias C, string methodstr)() { string ret = "new class { ubyte[] buffer;\n"; ret ~= ProxyMethods_mixin!(C, methodstr)(); ret ~= "}\n"; pragma(msg, MethodTypeTuple_mixin!(C)(splitFuncs(methodstr))); return ret; } class ProxyClass(alias C, string methodstr) { ubyte[] buffer; this() { } mixin(ProxyMethods_mixin!(C,methodstr)()); } /+ void serialize(T)(T value) { writefln("serialize"); } T deserialize(T)() { writefln("deserialize"); static if (is(T==int)) { return 1; } else return "asdf"; } +/ void main() { pragma(msg, ProxyClass_mixin!(A,cast(string)"getInt setInt")()); writefln(ProxyClass_mixin!(A,cast(string)"getInt setInt")()); auto c = mixin(ProxyClass_mixin!(A,cast(string)"getInt setInt getString") ()); //pragma(msg, typeof(c).stringof); writefln("c.getInt(\"adsf\"): "~ c.getString("asdf")); auto pc = new ProxyClass!(A, cast(string)"getInt setInt getString"); writefln("ProxyClass: "~ pc.getString("asdf")); }