cool stuff

This commit is contained in:
Adam D. Ruppe 2020-01-09 19:46:30 -05:00
parent 07f73fec97
commit 09a6e315b1
2 changed files with 63 additions and 120 deletions

View File

@ -69,7 +69,15 @@ union N(ty) {
/// input range of ubytes... /// input range of ubytes...
int loadFrom(T, Range)(ref T t, auto ref Range r, bool assumeBigEndian = false) { int loadFrom(T, Range)(ref T t, auto ref Range r, bool assumeBigEndian = false) {
int bytesConsumed; int bytesConsumed;
string currentItem;
import std.conv;
scope(failure)
throw new Exception(T.stringof ~ "." ~ currentItem ~ " trouble " ~ to!string(t));
ubyte next() { ubyte next() {
if(r.empty)
throw new Exception(T.stringof ~ "." ~ currentItem ~ " trouble " ~ to!string(t));
auto bfr = r.front; auto bfr = r.front;
r.popFront; r.popFront;
bytesConsumed++; bytesConsumed++;
@ -78,6 +86,7 @@ int loadFrom(T, Range)(ref T t, auto ref Range r, bool assumeBigEndian = false)
bool endianness = bigEndian!T(assumeBigEndian); bool endianness = bigEndian!T(assumeBigEndian);
static foreach(memberName; __traits(allMembers, T)) {{ static foreach(memberName; __traits(allMembers, T)) {{
currentItem = memberName;
static if(is(typeof(__traits(getMember, T, memberName)))) { static if(is(typeof(__traits(getMember, T, memberName)))) {
alias f = __traits(getMember, T, memberName); alias f = __traits(getMember, T, memberName);
alias ty = typeof(f); alias ty = typeof(f);
@ -115,11 +124,17 @@ int loadFrom(T, Range)(ref T t, auto ref Range r, bool assumeBigEndian = false)
auto tag = __traits(getMember, t, tagField); auto tag = __traits(getMember, t, tagField);
// find the child of the union matching the tag... // find the child of the union matching the tag...
bool found = false;
static foreach(um; __traits(allMembers, ty)) { static foreach(um; __traits(allMembers, ty)) {
if(tag == getTag!(__traits(getMember, ty, um))) { if(tag == getTag!(__traits(getMember, ty, um))) {
bytesConsumed += loadFrom(__traits(getMember, __traits(getMember, t, memberName), um), r, endianness); bytesConsumed += loadFrom(__traits(getMember, __traits(getMember, t, memberName), um), r, endianness);
found = true;
} }
} }
if(!found) {
import std.format;
throw new Exception(format("found unknown union tag %s at %s", tag, t));
}
} else static if(is(ty == E[], E)) { } else static if(is(ty == E[], E)) {
static foreach(attr; __traits(getAttributes, f)) { static foreach(attr; __traits(getAttributes, f)) {
static if(is(attr == NumBytes!Field, alias Field)) static if(is(attr == NumBytes!Field, alias Field))

168
jni.d
View File

@ -442,15 +442,24 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
bool outputMixinTemplate = false; bool outputMixinTemplate = false;
string mainThing; string mainThing;
string helperThing; //string helperThing;
// so overriding Java classes from D is iffy and with separate implementation // so overriding Java classes from D is iffy and with separate implementation
// non final leads to linker errors anyway... // non final leads to linker errors anyway...
//mainThing ~= (isInterface ? "interface " : (jtc.inlineImplementations ? "class " : isAbstract ? "abstract class " : "final class ")) ~ lastClassName ~ " : "; //mainThing ~= (isInterface ? "interface " : (jtc.inlineImplementations ? "class " : isAbstract ? "abstract class " : "final class ")) ~ lastClassName ~ " : ";
mainThing ~= "final class " ~ lastClassName ~ " : IJavaObject {\n";
mainThing ~= "\tstatic immutable string[] _d_canCastTo = [\n";
// not putting super class on inline implementations since that forces vtable... // not putting super class on inline implementations since that forces vtable...
if(jtc.inlineImplementations) { if(jtc.inlineImplementations) {
auto scn = cf.superclassName; auto scn = cf.superclassName;
if(scn.length) {
mainThing ~= "\t\t\"" ~ scn ~ "\",\n";
}
/+
//if(!scn.startsWith("java/")) { //if(!scn.startsWith("java/")) {
// superclasses need the implementation too so putting it in the return list lol // superclasses need the implementation too so putting it in the return list lol
if(scn.length && scn != "java/lang/Object") { // && scn in allClasses) { if(scn.length && scn != "java/lang/Object") { // && scn in allClasses) {
@ -458,6 +467,7 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
mainThing ~= ", "; mainThing ~= ", ";
} }
//} //}
+/
} }
foreach(name; cf.interfacesNames) { foreach(name; cf.interfacesNames) {
@ -465,73 +475,25 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
//continue; // these probably aren't important to D and can really complicate version management //continue; // these probably aren't important to D and can really complicate version management
//if(name !in allClasses) //if(name !in allClasses)
//continue; //continue;
mainThing ~= javaObjectToDTypeString(name, javaPackages, javaPackagesReturn, importPrefix); //mainThing ~= javaObjectToDTypeString(name, javaPackages, javaPackagesReturn, importPrefix);
mainThing ~= ", "; //mainThing ~= ", ";
mainThing ~= "\t\t\"" ~ name ~ "\",\n";
} }
mainThing ~= "arsd.jni.IJavaObject"; mainThing ~= "\t];\n";
mainThing ~= " {\n"; //helperThing ~= "interface " ~ lastClassName ~ "_d_methods : ";
//mainThing ~= "\talias _d_helper this;\n";
mainThing ~= "\tfinal auto opDispatch(string name, Args...)(Args args) if(name != \"opCall\") { auto local = _d_helper(); return __traits(getMember, local, name)(args); }\n";
if(isInterface)
mainThing ~= "\tfinal auto _d_helper()() { return getDProxy(); }\n";
else {
mainThing ~= "\t" ~ lastClassName ~ "_d_methods _d_proxy_;\n";
mainThing ~= "\tfinal auto _d_helper()() {\n";
mainThing ~= "\t\tif(getDProxy() is null) _d_proxy_ = arsd.jni.createDProxy!("~lastClassName~"_d_methods)(this);\n";
mainThing ~= "\t\treturn getDProxy();\n";
mainThing ~= "\t}\n";
mainThing ~= "\toverride " ~ lastClassName ~ "_d_methods getDProxy() { return _d_proxy_; }\n";
}
helperThing ~= "interface " ~ lastClassName ~ "_d_methods : ";
// not putting super class on inline implementations since that forces vtable...
if(jtc.inlineImplementations) {
auto scn = cf.superclassName;
//if(!scn.startsWith("java/")) {
// superclasses need the implementation too so putting it in the return list lol
if(scn.length && scn != "java/lang/Object") { // && scn in allClasses) {
helperThing ~= javaObjectToDTypeString(scn, javaPackages, javaPackagesReturn, importPrefix);
helperThing ~= "_d_methods, ";
}
//}
}
foreach(name; cf.interfacesNames) {
//if(name.startsWith("java/"))
//continue; // these probably aren't important to D and can really complicate version management
//if(name !in allClasses)
//continue;
helperThing ~= javaObjectToDTypeString(name, javaPackages, javaPackagesReturn, importPrefix);
helperThing ~= "_d_methods, ";
}
helperThing ~= "IJavaObject";
helperThing ~= " {\n";
helperThing ~= "\tmixin JavaInterfaceMembers!(\"L" ~ cn ~ ";\");\n";
string tm;
string[string] tmpackages;
string[string] tmpackagesr;
string[string] tmpackagesa;
string[string] mentioned; string[string] mentioned;
foreach(method; cf.methodsListing) {
string[string] processed;
void addMethods(ClassFile* current, bool isTopLevel) {
if(current is null) return;
if(current.className in processed) return;
foreach(method; current.methodsListing) {
bool native = (method.flags & 0x0100) ? true : false; bool native = (method.flags & 0x0100) ? true : false;
if(jtc.nativesAreImports) { if(jtc.nativesAreImports) {
native = false; // kinda hacky but meh native = false; // kinda hacky but meh
@ -545,32 +507,27 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
} }
auto port = native ? "@Export" : "@Import"; auto port = native ? "@Export" : "@Import";
if(method.flags & 1) { // public if(method.flags & 1) { // public
if(!isTopLevel && method.name == "<init>")
bool addToMixinTemplate; continue;
bool wasStatic;
bool maybeOverride = false;// !isInterface; bool maybeOverride = false;// !isInterface;
if(method.flags & 0x0008) { if(method.flags & 0x0008) {
port ~= " static"; port ~= " static";
maybeOverride = false;
wasStatic = true;
} }
if(method.flags & method_info.ACC_ABSTRACT) { if(method.flags & method_info.ACC_ABSTRACT) {
maybeOverride = false;
//if(!isInterface) //if(!isInterface)
port ~= " abstract"; //port ~= " abstract";
} else { } else {
// this represents a default implementation in a Java interface // this represents a default implementation in a Java interface
// D cannot express this... so I need to add it to the mixin template // D cannot express this... so I need to add it to the mixin template
// associated with this interface as well. // associated with this interface as well.
if(isInterface && (!(method.flags & 0x0008))) { //if(isInterface && (!(method.flags & 0x0008))) {
addToMixinTemplate = true; //addToMixinTemplate = true;
} //}
} }
if(maybeOverride && method.isOverride(allClasses)) //if(maybeOverride && method.isOverride(allClasses))
port ~= " override"; //port ~= " override";
auto name = method.name; auto name = method.name;
@ -585,10 +542,6 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
name = name.replace("$", "_"); name = name.replace("$", "_");
bool ctor = name == "<init>"; bool ctor = name == "<init>";
if(ctor && isInterface) {
ctor = false;
name = "CONSTRUCTOR";
}
auto sig = method.signature; auto sig = method.signature;
@ -596,11 +549,10 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
assert(lidx != -1); assert(lidx != -1);
auto retJava = sig[lidx + 1 .. $]; auto retJava = sig[lidx + 1 .. $];
auto argsJava = sig[1 .. lidx]; auto argsJava = sig[1 .. lidx];
auto retJava2 = retJava;
auto argsJava2 = argsJava;
string ret = ctor ? "" : javaSignatureToDTypeString(retJava, javaPackages, javaPackagesReturn, importPrefix); string ret = ctor ? "" : javaSignatureToDTypeString(retJava, javaPackages, javaPackagesReturn, importPrefix);
string args = javaSignatureToDTypeString(argsJava, javaPackages, javaPackagesArguments, importPrefix); string args = javaSignatureToDTypeString(argsJava, javaPackages, javaPackagesArguments, importPrefix);
auto oargs = args;
if(!jtc.inlineImplementations) { if(!jtc.inlineImplementations) {
if(ctor && args.length == 0) if(ctor && args.length == 0)
@ -613,52 +565,32 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
mentioned[men] = men; mentioned[men] = men;
string proto = cast(string) ("\t"~port~" " ~ ret ~ (ret.length ? " " : "") ~ (ctor ? "this" : name) ~ "("~args~")"~(native ? " { assert(0); }" : ";")~"\n"); string proto = cast(string) ("\t"~port~" " ~ ret ~ (ret.length ? " " : "") ~ (ctor ? "this" : name) ~ "("~args~")"~(native ? " { assert(0); }" : ";")~"\n");
if(wasStatic || ctor)
mainThing ~= proto; mainThing ~= proto;
else
helperThing ~= proto;
if(addToMixinTemplate) { if(oargs.length == 0 && name == "toString_" && !(method.flags & 0x0008))
string pfx = "tmimport"; mainThing ~= "\toverride string toString() { return toString_(); }\n";
string ret1 = ctor ? "" : javaSignatureToDTypeString(retJava2, tmpackages, tmpackagesr, pfx);
string args1 = javaSignatureToDTypeString(argsJava2, tmpackages, tmpackagesa, pfx);
tm ~= "\t\t"~port~" " ~ ret1 ~ (ret1.length ? " " : "") ~ (ctor ? "this" : name) ~ "("~args1~"){ assert(0); }\n";
}
} }
} }
if(!isInterface) { processed[current.className.idup] = "done";
if(current.superclassName.length) {
auto c = current.superclassName in allClasses;
addMethods(c, false);
}
foreach(iface; current.interfacesNames) {
auto c = iface in allClasses;
addMethods(c, false);
}
}
addMethods(&cf, true);
mainThing ~= "\tmixin IJavaObjectImplementation!(false);\n"; mainThing ~= "\tmixin IJavaObjectImplementation!(false);\n";
mainThing ~= "\tpublic static immutable string _javaParameterString = \"L" ~ cn ~ ";\";\n"; mainThing ~= "\tpublic static immutable string _javaParameterString = \"L" ~ cn ~ ";\";\n";
} else {
mainThing ~= "\tmixin JavaInterfaceMembers!(\"L" ~ cn ~ ";\");\n";
if(outputMixinTemplate && tm.length) {
mainThing ~= "\tmixin template JavaDefaultImplementations() {\n";
foreach(pkg, prefix; tmpackages) {
auto m = (dPackagePrefix.length ? (dPackagePrefix ~ ".") : "") ~ pkg;
if(jtc.inlineImplementations)
tm ~= "\t\timport " ~ prefix ~ " = " ~ m ~ ";\n";
else
tm ~= "\t\timport " ~ prefix ~ " = " ~ m ~ "_d_interface;\n";
}
if(!jtc.inlineImplementations)
foreach(pkg, prefix; tmpackagesr) {
auto m = (dPackagePrefix.length ? (dPackagePrefix ~ ".") : "") ~ pkg;
tm ~= "\t\timport impl_" ~ prefix ~ " = " ~ m ~ ";\n";
}
mainThing ~= tm;
mainThing ~= "\t}\n";
}
}
mainThing ~= "}\n\n"; mainThing ~= "}\n\n";
helperThing ~= "}\n\n";
dc ~= mainThing; dc ~= mainThing;
dc ~= "\n\n"; dc ~= "\n\n";
dc ~= helperThing;
foreach(pkg, prefix; javaPackages) { foreach(pkg, prefix; javaPackages) {
auto m = (dPackagePrefix.length ? (dPackagePrefix ~ ".") : "") ~ pkg; auto m = (dPackagePrefix.length ? (dPackagePrefix ~ ".") : "") ~ pkg;
@ -674,10 +606,6 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
dco ~= "\n"; dco ~= "\n";
dco ~= dc; dco ~= dc;
//dco ~= "\tmixin JavaPackageId!(\""~originalJavaPackage.replace("/", ".")~"\", \""~originalClassName~"\");\n";
// the following saves some compile time of the bindings; might as well do some calculations ahead of time
//dco ~= "\tpublic static immutable string _javaParameterString = \"L" ~ cn ~ ";\";\n";
if(jtc.inlineImplementations) { if(jtc.inlineImplementations) {
dco ~= "\nmixin ImportExportImpl!"~lastClassName~";\n"; dco ~= "\nmixin ImportExportImpl!"~lastClassName~";\n";
std.file.write(filename, dco); std.file.write(filename, dco);