diff --git a/declarativeloader.d b/declarativeloader.d index 139b806..28299c2 100644 --- a/declarativeloader.d +++ b/declarativeloader.d @@ -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)) diff --git a/jni.d b/jni.d index 6bc457c..6da2309 100644 --- a/jni.d +++ b/jni.d @@ -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 == "") + 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 == ""; - 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);