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