Skip to content

Instantly share code, notes, and snippets.

@UplinkCoder
Created August 14, 2021 11:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save UplinkCoder/e60584a2c8f46ae4a490117b878ecec1 to your computer and use it in GitHub Desktop.
Save UplinkCoder/e60584a2c8f46ae4a490117b878ecec1 to your computer and use it in GitHub Desktop.
import ctx_ = ctx;
import std.meta;
import std.traits;
template isStruct(alias S)
{
enum isStruct = (is(S == struct));
}
template isFunction(alias F)
{
enum isFunction = (is(typeof(F) == function));
}
template MemberOf(alias M)
{
template MemberOfInner(string memberName)
{
static if (is(mixin("M." ~ memberName)) || is(typeof(mixin("M." ~ memberName))))
{
alias MemberOfInner = mixin("M." ~ memberName);
}
}
alias MemberOf = MemberOfInner;
}
template MembersOf(alias M)
{
template MembersOfInner(memberStrings...)
{
alias MembersOfInner = staticMap!(MemberOf!M, memberStrings);
}
alias MembersOf = MembersOfInner;
}
template StructCollector(alias M)
{
alias StructCollector
= Filter!(isStruct, staticMap!(MembersOf!M, __traits(allMembers, M)));
}
template FunctionCollector(alias M)
{
alias FunctionCollector
= Filter!(isFunction, staticMap!(MembersOf!M, __traits(allMembers, M)));
}
template Params(alias F)
{
static if (is(F == function))
{
static if (is(F P == __parameters))
{
alias Params = P;
}
}
else static if (is(typeof(F) P == __parameters))
{
alias Params = P;
}
else
{
static assert(0, F.stringof ~ " is not a function");
}
}
template isSame(alias A)
{
template isSameInner(alias B)
{
enum isSameInner = is(A == B);
}
alias isSame = isSameInner;
}
template isSame(alias A, alias B)
{
enum isSame = is(A == B);
}
template FunctionHasParamType(alias F, alias P)
{
alias FParams = Params!F;
// Unqual doesn't get rid of the const in our params :(
// so we have to run 2 filters
alias Fil1 = Filter!(isTOrConstT!P, FParams);
enum FunctionHasParamType = (Fil1.length != 0);
}
template isTOrConstT(alias T, alias A)
{
alias ConstT = const(T);
enum isTOrConstT = isSame!(T, A) || isSame!(ConstT, A);
}
template isTOrConstT(alias T)
{
template isTOrConstTInner(alias A)
{
alias ConstT = const(T);
enum isTOrConstTInner = isSame!(T, A) || isSame!(ConstT, A);
}
alias isTOrConstT = isTOrConstTInner;
}
template FunctionHasContextType(alias F)
{
enum FunctionHasContextType = FunctionHasParamType!(F, Structs[0]*);
}
alias Funcs = FunctionCollector!ctx_;
alias Structs = StructCollector!ctx_;
alias FilteredFuncs = Filter!(FunctionHasContextType, Funcs);
alias WrapperStrings = staticMap!(WrapperStringMap!(Structs[0]*), FilteredFuncs);
template WrapperStringMap(alias Ctx)
{
template WrapperStringInner(alias F)
{
enum WrapperStringInner = WrapperString!(Ctx, F);
}
alias WrapperStringMap = WrapperStringInner;
}
template WrapperString(alias Ctx, alias F)
{
enum WrapperString = () {
alias RetType = ReturnType!F;
alias FParams = Params!(F);
string FName = __traits(identifier, F);
string result = RetType.stringof ~ " " ~ FName ~ " (";
alias PIdents = ParameterIdentifierTuple!F;
bool wasCtx;
foreach(i, P;FParams)
{
wasCtx = false;
static if (isTOrConstT!(Ctx, P))
{
wasCtx = true;
}
else
{
result ~= P.stringof ~ " " ~ PIdents[i] ~ ", ";
}
}
if (!wasCtx) result = result[0 .. $-2];
result ~= ")\n";
result ~= " ";
result ~= FName ~ " (";
foreach(i, P;FParams)
{
static if (isTOrConstT!(Ctx*, P))
{
result ~= "ctx, ";
}
else
{
result ~= PIdents[i] ~ ", ";
}
}
result = result[0 .. $-2] ~ ");\n";
result ~= "}\n";
return result;
} ();
}
// lets be generous and not count the cost of joining
// import std.array : join;
// pragma(msg, [WrapperStrings].join("\n"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment