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...
int loadFrom(T, Range)(ref T t, auto ref Range r, bool assumeBigEndian = false) {
int bytesConsumed;
string currentItem;
import std.conv;
scope(failure)
throw new Exception(T.stringof ~ "." ~ currentItem ~ " trouble " ~ to!string(t));
ubyte next() {
if(r.empty)
throw new Exception(T.stringof ~ "." ~ currentItem ~ " trouble " ~ to!string(t));
auto bfr = r.front;
r.popFront;
bytesConsumed++;
@ -78,6 +86,7 @@ int loadFrom(T, Range)(ref T t, auto ref Range r, bool assumeBigEndian = false)
bool endianness = bigEndian!T(assumeBigEndian);
static foreach(memberName; __traits(allMembers, T)) {{
currentItem = memberName;
static if(is(typeof(__traits(getMember, T, memberName)))) {
alias f = __traits(getMember, T, memberName);
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);
// find the child of the union matching the tag...
bool found = false;
static foreach(um; __traits(allMembers, ty)) {
if(tag == getTag!(__traits(getMember, ty, um))) {
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)) {
static foreach(attr; __traits(getAttributes, f)) {
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;
string mainThing;
string helperThing;
//string helperThing;
// so overriding Java classes from D is iffy and with separate implementation
// non final leads to linker errors anyway...
//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...
if(jtc.inlineImplementations) {
auto scn = cf.superclassName;
if(scn.length) {
mainThing ~= "\t\t\"" ~ scn ~ "\",\n";
}
/+
//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) {
@ -458,6 +467,7 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
mainThing ~= ", ";
}
//}
+/
}
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
//if(name !in allClasses)
//continue;
mainThing ~= javaObjectToDTypeString(name, javaPackages, javaPackagesReturn, importPrefix);
mainThing ~= ", ";
//mainThing ~= javaObjectToDTypeString(name, javaPackages, javaPackagesReturn, importPrefix);
//mainThing ~= ", ";
mainThing ~= "\t\t\"" ~ name ~ "\",\n";
}
mainThing ~= "arsd.jni.IJavaObject";
mainThing ~= "\t];\n";
mainThing ~= " {\n";
//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;
//helperThing ~= "interface " ~ lastClassName ~ "_d_methods : ";
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;
if(jtc.nativesAreImports) {
native = false; // kinda hacky but meh
@ -545,32 +507,27 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
}
auto port = native ? "@Export" : "@Import";
if(method.flags & 1) { // public
bool addToMixinTemplate;
bool wasStatic;
if(!isTopLevel && method.name == "<init>")
continue;
bool maybeOverride = false;// !isInterface;
if(method.flags & 0x0008) {
port ~= " static";
maybeOverride = false;
wasStatic = true;
}
if(method.flags & method_info.ACC_ABSTRACT) {
maybeOverride = false;
//if(!isInterface)
port ~= " abstract";
//port ~= " abstract";
} else {
// this represents a default implementation in a Java interface
// D cannot express this... so I need to add it to the mixin template
// associated with this interface as well.
if(isInterface && (!(method.flags & 0x0008))) {
addToMixinTemplate = true;
}
//if(isInterface && (!(method.flags & 0x0008))) {
//addToMixinTemplate = true;
//}
}
if(maybeOverride && method.isOverride(allClasses))
port ~= " override";
//if(maybeOverride && method.isOverride(allClasses))
//port ~= " override";
auto name = method.name;
@ -585,10 +542,6 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
name = name.replace("$", "_");
bool ctor = name == "<init>";
if(ctor && isInterface) {
ctor = false;
name = "CONSTRUCTOR";
}
auto sig = method.signature;
@ -596,11 +549,10 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
assert(lidx != -1);
auto retJava = sig[lidx + 1 .. $];
auto argsJava = sig[1 .. lidx];
auto retJava2 = retJava;
auto argsJava2 = argsJava;
string ret = ctor ? "" : javaSignatureToDTypeString(retJava, javaPackages, javaPackagesReturn, importPrefix);
string args = javaSignatureToDTypeString(argsJava, javaPackages, javaPackagesArguments, importPrefix);
auto oargs = args;
if(!jtc.inlineImplementations) {
if(ctor && args.length == 0)
@ -613,52 +565,32 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
mentioned[men] = men;
string proto = cast(string) ("\t"~port~" " ~ ret ~ (ret.length ? " " : "") ~ (ctor ? "this" : name) ~ "("~args~")"~(native ? " { assert(0); }" : ";")~"\n");
if(wasStatic || ctor)
mainThing ~= proto;
else
helperThing ~= proto;
mainThing ~= proto;
if(addToMixinTemplate) {
string pfx = "tmimport";
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(oargs.length == 0 && name == "toString_" && !(method.flags & 0x0008))
mainThing ~= "\toverride string toString() { return toString_(); }\n";
}
}
if(!isInterface) {
mainThing ~= "\tmixin IJavaObjectImplementation!(false);\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";
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 ~= "\tpublic static immutable string _javaParameterString = \"L" ~ cn ~ ";\";\n";
mainThing ~= "}\n\n";
helperThing ~= "}\n\n";
dc ~= mainThing;
dc ~= "\n\n";
dc ~= helperThing;
foreach(pkg, prefix; javaPackages) {
auto m = (dPackagePrefix.length ? (dPackagePrefix ~ ".") : "") ~ pkg;
@ -674,10 +606,6 @@ void rawClassStructToD()(ref ClassFile cf, string dPackagePrefix, string outputD
dco ~= "\n";
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) {
dco ~= "\nmixin ImportExportImpl!"~lastClassName~";\n";
std.file.write(filename, dco);