Skip to content

Instantly share code, notes, and snippets.

@aliyome
Last active July 22, 2018 07:27
Show Gist options
  • Save aliyome/e17e707c5c82f24329b2a99ead86fe00 to your computer and use it in GitHub Desktop.
Save aliyome/e17e707c5c82f24329b2a99ead86fe00 to your computer and use it in GitHub Desktop.
黒魔術系
import std.stdio;
import std.traits;
import std.range;
import std.array;
import std.algorithm;
import core.sync.mutex;
class A {
private int private_field;
public string public_field;
private int private_method() { return 10; }
public int public_method(ref int a, in int b, out int c) { return 20; }
static public void static_method() {}
public this() {
}
}
//template GenerateCInterface(T) if (is(T == class)) {
// // T* T_storage;
// mixin(T.stringof ~ "* " ~ T.stringof ~ "_storage;");
// //pragma(msg, allMembers!T);
//}
//string[] allMembers(T)() if (is(T == class)) {
// return [__traits(allMembers, T)];
//}
////string[] privateFields(T)() {
//void privateFields(T)() {
// foreach (member_name; [__traits(allMembers, T)]) {
// mixin("alias member = " ~ T.stringof ~ "." ~ member_name ~ ";");
// //pragma(msg, __traits(getProtection, __traits(getMember, T.stringof ~ "." ~ member_name)));
// }
//}
enum BuiltInFunctions = ["toString", "toHash", "opCmp", "opEquals", "factory"];
struct MethodInfo {
string name;
ArgInfo[] args;
string return_type;
string protection;
bool is_static;
}
struct ArgInfo {
string name;
uint storage_class; // ParameterStorageClassTuple.ref_とか
string type;
}
private template GetAllMethodsTrait(T) if (is(T == class)) {
private MethodInfo[] _getMethods() {
MethodInfo[] result;
foreach (member_string; __traits(allMembers, T)) {
mixin("alias member = " ~ T.stringof ~ "." ~ member_string ~ ";");
static if (is(typeof(member) == function)) {
MethodInfo m = MethodInfo();
m.name = __traits(identifier, member);
m.return_type = ReturnType!member.stringof;
m.protection = __traits(getProtection, member);
m.is_static = __traits(isStaticFunction, member);
foreach (i, n; ParameterIdentifierTuple!member) {
ArgInfo a = ArgInfo();
a.name = n;
m.args ~= a;
}
foreach (i, n; ParameterStorageClassTuple!member) {
m.args[i].storage_class = n;
}
foreach (i, n; Parameters!member) {
m.args[i].type = n.stringof;
}
result ~= m;
}
}
return result;
}
enum GetAllMethodsTrait = _getMethods();
}
uint GetGuid() {
static guid = 0;
static Mutex mutex;
if (mutex is null) mutex = new Mutex;
synchronized (mutex) {
++guid;
}
return guid;
}
string buildBindingMixinString(T)() {
string result;
result ~= T.stringof ~ "[] _" ~ T.stringof ~ ";\n";
foreach (m; GetAllMethodsTrait!T.filter!(x => x.protection == "public")) {
bool is_new = false;
if (m.name == "__ctor") {
result ~= "uint " ~ T.stringof ~ "_new(";
is_new = true;
}
else {
result ~= m.return_type ~ " " ~ T.stringof ~ "_" ~ m.name ~ "(";
if (!m.is_static) {
result ~= "uint guid";
}
}
foreach (i, a; m.args) {
if (!m.is_static && !is_new) result ~= ", ";
if (a.storage_class & ParameterStorageClass.scope_) result ~= "scope ";
if (a.storage_class & ParameterStorageClass.out_) result ~= "out ";
if (a.storage_class & ParameterStorageClass.ref_) result ~= "ref ";
if (a.storage_class & ParameterStorageClass.lazy_) result ~= "lazy ";
if (a.storage_class & ParameterStorageClass.return_) result ~= "return ";
result ~= a.type ~ " " ~ a.name;
}
result ~= ")";
if (is_new) {
result ~= "{ _" ~ T.stringof ~ " ~= new " ~ T.stringof ~ "(";
}
else {
result ~= "{ ";
if (m.return_type != "void") {
result ~= "return ";
}
if (m.is_static) {
result ~= T.stringof ~ "." ~ m.name ~ "(";
}
else {
result ~= "_" ~ T.stringof ~ "[guid]." ~ m.name ~ "(";
}
}
foreach (i, a; m.args) {
if (i != 0) result ~= ", ";
result ~= a.name;
}
result ~= ");";
if (is_new) {
result ~= " return GetGuid();";
}
result ~= "}";
result ~= "\n";
}
return result;
}
//private template AllMethods(T) if (is(T == class)) {
// private string[] getMethods() {
// string[] result;
// foreach (member_string; __traits(allMembers, T)) {
// mixin("alias member = " ~ T.stringof ~ "." ~ member_string ~ ";");
// static if (is(typeof(member) == function)) {
// result ~= __traits(identifier, member);
// }
// }
// return result;
// }
// enum AllMethods = getMethods().join("\n");
//}
//private template PrivateMethods(T) if (is(T == class)) {
// private string[] getPrivateMethods() {
// string[] result;
// foreach (member_string; __traits(allMembers, T)) {
// mixin("alias member = " ~ T.stringof ~ "." ~ member_string ~ ";");
// static if (is(typeof(member) == function)) {
// static if (__traits(getProtection, member) == "private") {
// result ~= __traits(identifier, member);
// }
// }
// }
// return result;
// }
// enum PrivateMethods = getPrivateMethods().join("\n");
//}
//private template PublicMethods(T) if (is(T == class)) {
// private string[] getPublicMethods() {
// string[] result;
// foreach (member_string; __traits(allMembers, T)) {
// mixin("alias member = " ~ T.stringof ~ "." ~ member_string ~ ";");
// static if (is(typeof(member) == function)) {
// static if (__traits(getProtection, member) == "public") {
// result ~= __traits(identifier, member);
// }
// }
// }
// return result;
// }
// enum PublicMethods = getPublicMethods();
//}
//auto publicMethodInterface(T)() {
// foreach (m; PublicMethods!T) {
// static if (true) {
// __traits(getMember, T, m);
// }
// }
//}
mixin(buildBindingMixinString!A());
version(unittest) void main() {}
unittest {
//pragma(msg, AllMethods!A);
//pragma(msg, PrivateMethods!A);
//pragma(msg, PublicMethods!A);
//pragma(msg, GetAllMethodsTrait!A);
pragma(msg, buildBindingMixinString!A());
uint id = A_new();
int a, c;
writeln(id, ",", _A[a].public_method(a, 2, c));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment