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"));
}


Reply via email to