Skip to content

Instantly share code, notes, and snippets.

@PetarKirov
Last active December 4, 2020 08:46
Show Gist options
  • Save PetarKirov/ae6fcf53908232d15b357bb79c2be5b0 to your computer and use it in GitHub Desktop.
Save PetarKirov/ae6fcf53908232d15b357bb79c2be5b0 to your computer and use it in GitHub Desktop.
Implementing run-time dispatch in D
import std.conv : to;
import std.meta : ApplyLeft, Filter;
import std.stdio : writef, writefln, writeln;
import std.variant : Variant;
void main()
{
auto c = new MyClass();
c.call("v0", [ ]);
c.call("v1", [ Variant(42), Variant("test") ]);
c.call("v2", [ Variant(42), Variant("test"), Variant(["test1", "test2"]) ]);
c.call("s0", [ ]).writeln;
c.call("s1", [ Variant(21) ]).writeln;
c.call("s2", [ Variant("hello "), Variant("world!") ]).writeln;
c.call("d3", [ Variant(0), Variant(3), Variant(4) ]).writeln;
}
class MyClass
{
void v0() { writeln("f0()"); }
void v1(int x, string y) { writefln("f1(%s, %s)", x, y); }
void v2(int x, string y, string[] z) { writefln("f2(%s, %s, %s)", x, y, z); }
string s0() { writef("s0() returns: "); return "some string"; }
string s1(int x) { writef("s1(%s) returns: ", x); return (x * 2).to!string; }
string s2(string x, string y) { writef("s2(%s, %s) returns: ", x, y); return x ~ y; }
double d3(double x, double y, double z) { writef("d3(%s, %s, %s) returns: ", x, y, z); return (x*x + y*y + z*z) ^^ 0.5; }
}
Variant call(T)(T self, string methodName, Variant[] args)
{
import std.traits : ReturnType, Parameters;
switch (methodName)
{
default:
throw new Exception("Unknown method: " ~ methodName);
static foreach (name; AllMemberFunctions!MyClass)
{
case name:
{
Parameters!(mixin("self." ~ name)) tuple;
static foreach (i; 0 .. tuple.length)
tuple[i] = args[i].get!(typeof(tuple[i]));
static if (is(ReturnType!(mixin("self." ~ name)) == void))
{
mixin("self." ~ name ~ "(tuple);");
return Variant();
}
else
return Variant(mixin("self." ~ name ~ "(tuple)"));
}
}
}
}
enum isMethod(T, string name) =
__traits(isVirtualFunction, mixin("T.init." ~ name));
alias AllMemberFunctions(T) = Filter!(
ApplyLeft!(isMethod, T), // filtering condition: each string must be the name of member function of T
__traits(allMembers, T) // sequence to filter: the names of all members of T
);
@PetarKirov
Copy link
Author

PetarKirov commented Sep 7, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment