I just made something I thought I'd share.

It's great for those times when the compiler decides to randomly put a closure on the heap.

The usage is pretty simple:

    int x = 5;
    auto adder5 = mixin(closure!x(q{(int a) { return a + x; }}));
    assert(adder5(10) == 15);

It returns a callable struct whose body is the given string; the template parameters are the variables under closure (in this case, x).

The generated code looks like (minus a little beautification on my part):

    (delegate(ref int x) {
        static struct State {
            int* px;
            @property ref int x() { return *this.px; }
            auto opCall(int a) { return a + x; }
        }
        State tmp;
        tmp.px = &x;
        return tmp;
    })(x)

So when you assign it to something, that something becomes a struct with opCall overloaded. You can then take the address of opCall on the struct, and you get a delegate.

Thoughts?

----------------------------------------------
 // Code:

string closure(States...)(string argsAndBody)
{
string stateArgs = null, stateVars = null, stateProps = null, setStateVars = null;
    alias staticMap!(StringOf, States) VarNames;
    string varPtrs;
    alias staticMap!(TypeStringOf, States) TypeNames;
    foreach (i, varName; VarNames)
    {
        if (varPtrs != null) { varPtrs ~= ", "; }
        if (stateArgs != null) { stateArgs ~= ", "; }
        varPtrs ~= varName;
        stateArgs ~= "ref " ~ TypeNames[i] ~ " " ~ varName;
        stateVars ~= TypeNames[i] ~ "* ___p_" ~ varName ~ "; ";
stateProps ~= "@property ref " ~ TypeNames[i] ~ " " ~ varName ~ "() { return *this.___p_" ~ varName ~ "; } ";
        setStateVars ~= "___tmp.___p_" ~ varName ~ " = &" ~ varName ~ "; ";
    }
    return "("
        ~ "delegate(" ~ stateArgs ~ ") { "
            ~ "static struct State { "
                ~ stateVars ~ ""
                ~ stateProps ~ ""
                ~ "auto opCall" ~ argsAndBody
                ~ ""
            ~ "} "
            ~ "State ___tmp; "
            ~ setStateVars
            ~ "return ___tmp; "
        ~"})(" ~ varPtrs ~ ")";
}

Reply via email to