Last active
December 4, 2020 08:46
-
-
Save PetarKirov/ae6fcf53908232d15b357bb79c2be5b0 to your computer and use it in GitHub Desktop.
Implementing run-time dispatch in D
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Try online at: https://run.dlang.io/gist/PetarKirov/ae6fcf53908232d15b357bb79c2be5b0?compiler=dmd