diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeContext.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeContext.java index f8037560..1c80d348 100644 --- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeContext.java +++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeContext.java @@ -106,7 +106,7 @@ private void createRangeClass(JavaSynthesizedRange range) { new FunctionParameter(range.baseType, "to") ); JavaNativeMethod method = JavaNativeMethod.getConstructor(range.cls, getMethodDescriptor(ctorHeader), Opcodes.ACC_PUBLIC); - JavaCompilingMethod compilingMethod = new JavaCompilingMethod(range.compiling.compiled, method, getMethodSignature(ctorHeader)); + JavaCompilingMethod compilingMethod = new JavaCompilingMethod(method, getMethodSignature(ctorHeader)); JavaWriter constructorWriter = new JavaWriter(logger, CodePosition.GENERATED, rangeWriter, compilingMethod, null); constructorWriter.loadObject(0); diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeRunUnit.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeRunUnit.java index 461050f5..4f1e3c80 100644 --- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeRunUnit.java +++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeRunUnit.java @@ -10,9 +10,7 @@ import org.objectweb.asm.Type; import org.openzen.zencode.shared.CodePosition; import org.openzen.zencode.shared.logging.IZSLogger; -import org.openzen.zenscript.codemodel.FunctionHeader; import org.openzen.zenscript.codemodel.FunctionParameter; -import org.openzen.zenscript.codemodel.type.BasicTypeID; import org.openzen.zenscript.javabytecode.compiler.JavaClassWriter; import org.openzen.zenscript.javabytecode.compiler.JavaWriter; import org.openzen.zenscript.javashared.JavaClass; @@ -157,7 +155,6 @@ private void writeScripts() { return; JavaClassWriter scriptsClassWriter = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES); - JavaClass scriptsClass = JavaClass.fromInternalName("Scripts", JavaClass.Kind.CLASS); scriptsClassWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Scripts", null, "java/lang/Object", null); StringBuilder headerBuilder = new StringBuilder(); @@ -168,7 +165,7 @@ private void writeScripts() { headerBuilder.append(")V"); JavaNativeMethod runMethod = JavaNativeMethod.getStatic(new JavaClass("script", "Scripts", JavaClass.Kind.CLASS), "run", headerBuilder.toString(), Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC); - JavaCompilingMethod runMethodCompiling = new JavaCompilingMethod(scriptsClass, runMethod, headerBuilder.toString()); + JavaCompilingMethod runMethodCompiling = new JavaCompilingMethod(runMethod, headerBuilder.toString()); final JavaWriter runWriter = new JavaWriter(logger, CodePosition.GENERATED, scriptsClassWriter, runMethodCompiling, null); runWriter.start(); for (JavaScriptMethod method : scripts) { diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaCompiler.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaCompiler.java index 61b3f6be..bd53f701 100644 --- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaCompiler.java +++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaCompiler.java @@ -119,7 +119,7 @@ public JavaBytecodeModule compile(String packageName, SemanticModule module, Jav final JavaClassWriter visitor = scriptFile.classWriter; JavaClass scriptsClass = new JavaClass(context.getPackageName(script.pkg), className, JavaClass.Kind.CLASS); JavaNativeMethod method = JavaNativeMethod.getStatic(scriptsClass, methodName, scriptDescriptor, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC); - JavaCompilingMethod compilingMethod = new JavaCompilingMethod(scriptsClass, method, scriptDescriptor); + JavaCompilingMethod compilingMethod = new JavaCompilingMethod(method, scriptDescriptor); scriptFile.scriptMethods.add(new JavaScriptMethod(method, module.parameters, javaScriptParameters)); final JavaWriter writer = new JavaWriter(logger, CodePosition.UNKNOWN, visitor, compilingMethod, null); diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java index b379312c..2dfb89bb 100644 --- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java +++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java @@ -6,7 +6,6 @@ import org.objectweb.asm.Type; import org.openzen.zencode.shared.CodePosition; import org.openzen.zenscript.codemodel.CompareType; -import org.openzen.zenscript.codemodel.FunctionParameter; import org.openzen.zenscript.codemodel.OperatorType; import org.openzen.zenscript.codemodel.definition.ExpansionDefinition; import org.openzen.zenscript.codemodel.expression.captured.CapturedExpression; @@ -24,6 +23,7 @@ import org.openzen.zenscript.javabytecode.JavaMangler; import org.openzen.zenscript.javabytecode.compiler.JavaModificationExpressionVisitor.PushOption; import org.openzen.zenscript.javabytecode.compiler.capturing.*; +import org.openzen.zenscript.javabytecode.compiler.definitions.JavaMemberVisitor; import org.openzen.zenscript.javashared.*; import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod; import org.openzen.zenscript.javashared.expressions.JavaFunctionInterfaceCastExpression; @@ -473,79 +473,41 @@ public Void visitFunction(FunctionExpression expression) { return null; }*/ - final String signature; final String[] interfaces; - final String descriptor; - - {//Fill the info above - if (expression.type instanceof JavaFunctionalInterfaceTypeID) { - //Let's implement the functional Interface instead - JavaFunctionalInterfaceTypeID type = (JavaFunctionalInterfaceTypeID) expression.type; - final Method functionalInterfaceMethod = type.functionalInterfaceMethod; - - //Should be the same, should it not? - signature = context.getMethodSignature(expression.header, true); - descriptor = context.getMethodDescriptor(expression.header); - interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())}; - } else { - //Normal way, no casting to functional interface - signature = context.getMethodSignature(expression.header, true); - descriptor = context.getMethodDescriptor(expression.header); - interfaces = new String[]{context.getInternalName(new FunctionTypeID(expression.header))}; - } + + if (expression.type instanceof JavaFunctionalInterfaceTypeID) { + //Let's implement the functional Interface instead + JavaFunctionalInterfaceTypeID type = (JavaFunctionalInterfaceTypeID) expression.type; + final Method functionalInterfaceMethod = type.functionalInterfaceMethod; + + //Should be the same, should it not? + interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())}; + } else { + //Normal way, no casting to functional interface + interfaces = new String[]{context.getInternalName(new FunctionTypeID(expression.header))}; } final JavaNativeMethod methodInfo; final String className = this.javaMangler.mangleGeneratedLambdaName(interfaces[0]); { final JavaNativeMethod m = context.getFunctionalInterface(expression.type); - methodInfo = new JavaNativeMethod(m.cls, m.kind, m.name, m.compile, m.descriptor, m.modifiers & ~JavaModifiers.ABSTRACT, m.genericResult, m.typeParameterArguments); + methodInfo = m.withModifiers(m.modifiers & ~JavaModifiers.ABSTRACT); } final ClassWriter lambdaCW = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES); JavaClass lambdaClass = JavaClass.fromInternalName(className, JavaClass.Kind.CLASS); lambdaCW.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", interfaces); final JavaWriter functionWriter; - //Bridge method!!! - if (!Objects.equals(methodInfo.descriptor, descriptor)) { - final JavaNativeMethod bridgeMethodInfo = new JavaNativeMethod(methodInfo.cls, methodInfo.kind, methodInfo.name, methodInfo.compile, methodInfo.descriptor, methodInfo.modifiers | JavaModifiers.BRIDGE | JavaModifiers.SYNTHETIC, methodInfo.genericResult, methodInfo.typeParameterArguments); - JavaCompilingMethod compilingBridgeMethod = new JavaCompilingMethod(javaWriter.method.class_, bridgeMethodInfo, signature); - final JavaWriter bridgeWriter = new JavaWriter(context.logger, expression.position, lambdaCW, compilingBridgeMethod, null); - bridgeWriter.start(); - - //This.name(parameters, casted) - bridgeWriter.loadObject(0); - - for (int i = 0; i < expression.header.parameters.length; i++) { - final FunctionParameter functionParameter = expression.header.parameters[i]; - final Type type = context.getType(functionParameter.type); - bridgeWriter.load(type, i + 1); - if (!CompilerUtils.isPrimitive(functionParameter.type)) { - bridgeWriter.checkCast(type); - } - } - - bridgeWriter.invokeVirtual(new JavaNativeMethod(JavaClass.fromInternalName(className, JavaClass.Kind.CLASS), JavaNativeMethod.Kind.INSTANCE, methodInfo.name, methodInfo.compile, descriptor, methodInfo.modifiers, methodInfo.genericResult)); - final TypeID returnType = expression.header.getReturnType(); - if (returnType != BasicTypeID.VOID) { - final Type returnTypeASM = context.getType(returnType); - if (!CompilerUtils.isPrimitive(returnType)) { - bridgeWriter.checkCast(returnTypeASM); - } - bridgeWriter.returnType(returnTypeASM); - } - - bridgeWriter.ret(); - bridgeWriter.end(); - - JavaNativeMethod actualMethod = methodInfo.createBridge(context.getMethodDescriptor(expression.header)); - JavaCompilingMethod actualCompiling = new JavaCompilingMethod(lambdaClass, actualMethod, signature); - //No @Override - functionWriter = new JavaWriter(context.logger, expression.position, lambdaCW, actualCompiling, null); - } else { - JavaCompilingMethod actualCompiling = new JavaCompilingMethod(lambdaClass, methodInfo, signature); - functionWriter = new JavaWriter(context.logger, expression.position, lambdaCW, actualCompiling, null); - } + JavaCompilingMethod actualCompiling = JavaMemberVisitor.compileBridgeableMethod( + context, + expression.position, + lambdaCW, + lambdaClass, + methodInfo, + expression.header, + null + ); + functionWriter = new JavaWriter(context.logger, expression.position, lambdaCW, actualCompiling, null); functionWriter.clazzVisitor.visitSource(expression.position.getFilename(), null); javaWriter.newObject(className); javaWriter.dup(); @@ -554,7 +516,7 @@ public Void visitFunction(FunctionExpression expression) { // To check: write a test where the ctor desc and signature would differ and make sure the program compiles/executes final String constructorDescriptorAndSignature = calcFunctionDescriptor(expression.closure); JavaNativeMethod constructor = JavaNativeMethod.getConstructor(lambdaClass, constructorDescriptorAndSignature, Opcodes.ACC_PUBLIC); - JavaCompilingMethod constructorCompiling = new JavaCompilingMethod(lambdaClass, constructor, constructorDescriptorAndSignature); + JavaCompilingMethod constructorCompiling = new JavaCompilingMethod(constructor, constructorDescriptorAndSignature); final JavaWriter constructorWriter = new JavaWriter(context.logger, expression.position, lambdaCW, constructorCompiling, null); constructorWriter.start(); constructorWriter.loadObject(0); @@ -1193,7 +1155,7 @@ private FunctionCastWrapperClass generateFunctionCastWrapperClass(CodePosition p //Constructor { JavaNativeMethod constructor = JavaNativeMethod.getConstructor(classInfo, constructorDescriptor, Opcodes.ACC_PUBLIC); - JavaCompilingMethod compiling = new JavaCompilingMethod(classInfo, constructor, constructorSignature); + JavaCompilingMethod compiling = new JavaCompilingMethod(constructor, constructorSignature); final JavaWriter constructorWriter = new JavaWriter(context.logger, position, lambdaCW, compiling, null); constructorWriter.start(); constructorWriter.loadObject(0); @@ -1209,7 +1171,7 @@ private FunctionCastWrapperClass generateFunctionCastWrapperClass(CodePosition p //The actual method { - JavaCompilingMethod compiling = new JavaCompilingMethod(classInfo, implementationMethod, methodSignature); + JavaCompilingMethod compiling = new JavaCompilingMethod(implementationMethod, methodSignature); final JavaWriter functionWriter = new JavaWriter(context.logger, position, lambdaCW, compiling, null); functionWriter.start(); diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaDefinitionVisitor.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaDefinitionVisitor.java index 5f52578c..9f5d54c9 100644 --- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaDefinitionVisitor.java +++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaDefinitionVisitor.java @@ -148,7 +148,7 @@ public byte[] visitEnum(EnumDefinition definition) { // TODO - expose an additional set of members including these generated ones if (definition.members.stream().noneMatch(it -> it instanceof ConstructorMember)) { final ConstructorMember autoConstructor = new ConstructorMember(CodePosition.BUILTIN, definition, Modifiers.NONE, new FunctionHeader(BasicTypeID.VOID)); - final JavaCompilingMethod compiling = new JavaCompilingMethod(class_.compiled, JavaNativeMethod.getConstructor(class_.compiled, "(Ljava/lang/String;I)V", 0), "(Ljava/lang/String;I)V"); + final JavaCompilingMethod compiling = new JavaCompilingMethod(JavaNativeMethod.getConstructor(class_.compiled, "(Ljava/lang/String;I)V", 0), "(Ljava/lang/String;I)V"); // This is used in the accept call below class_.addMethod(autoConstructor, compiling); @@ -164,7 +164,7 @@ public byte[] visitEnum(EnumDefinition definition) { // Enums aren't generic, so the descriptor and signature will always be the same String valuesMethodDescriptorAndAlsoSignature = "()[L" + class_.getInternalName() + ";"; JavaNativeMethod valuesMethod = JavaNativeMethod.getStatic(class_.compiled, "values", valuesMethodDescriptorAndAlsoSignature, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC); - JavaCompilingMethod valuesMethodCompiling = new JavaCompilingMethod(class_.compiled, valuesMethod, valuesMethodDescriptorAndAlsoSignature); + JavaCompilingMethod valuesMethodCompiling = new JavaCompilingMethod(valuesMethod, valuesMethodDescriptorAndAlsoSignature); JavaWriter valuesWriter = new JavaWriter(context.logger, CodePosition.BUILTIN, writer, valuesMethodCompiling, definition); valuesWriter.start(); valuesWriter.getStaticField(class_.getInternalName(), "$VALUES", "[L" + class_.getInternalName() + ";"); @@ -182,7 +182,7 @@ public byte[] visitEnum(EnumDefinition definition) { // Enums aren't generic, so the descriptor and signature will always be the same String valueOfMethodDescriptorAndAlsoSignature = "(Ljava/lang/String;)L" + class_.getInternalName() + ";"; JavaNativeMethod valueOfMethod = JavaNativeMethod.getStatic(class_.compiled, "valueOf", valueOfMethodDescriptorAndAlsoSignature, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC); - final JavaCompilingMethod javaCompilingMethod = new JavaCompilingMethod(class_.compiled, valueOfMethod, valueOfMethodDescriptorAndAlsoSignature); + final JavaCompilingMethod javaCompilingMethod = new JavaCompilingMethod(valueOfMethod, valueOfMethodDescriptorAndAlsoSignature); JavaWriter valueOfWriter = new JavaWriter(context.logger, CodePosition.BUILTIN, writer, javaCompilingMethod, definition); valueOfWriter.start(); valueOfWriter.constant(class_.compiled); @@ -326,7 +326,7 @@ public byte[] visitVariant(VariantDefinition variant) { optionInitSignatureBuilder.append(")V"); JavaNativeMethod constructorMethod = JavaNativeMethod.getConstructor(optionTag.variantOptionClass, optionInitDescBuilder.toString(), JavaModifiers.PUBLIC); - final JavaCompilingMethod constructorMethodCompiling = new JavaCompilingMethod(class_.compiled, constructorMethod, signature); + final JavaCompilingMethod constructorMethodCompiling = new JavaCompilingMethod(constructorMethod, signature); final JavaWriter initWriter = new JavaWriter(context.logger, option.position, optionWriter, constructorMethodCompiling, variant); initWriter.start(); initWriter.loadObject(0); @@ -345,7 +345,7 @@ public byte[] visitVariant(VariantDefinition variant) { //Denominator for switch-cases JavaNativeMethod denominator = JavaNativeMethod.getVirtual(optionTag.variantOptionClass, "getDenominator", "()I", JavaModifiers.PUBLIC); - final JavaCompilingMethod denominatorMethodCompiling = new JavaCompilingMethod(class_.compiled, denominator, signature); + final JavaCompilingMethod denominatorMethodCompiling = new JavaCompilingMethod(denominator, signature); final JavaWriter getDenominator = new JavaWriter(context.logger, option.position, optionWriter, denominatorMethodCompiling, variant); getDenominator.start(); getDenominator.constant(option.ordinal); @@ -363,7 +363,7 @@ public byte[] visitVariant(VariantDefinition variant) { } final JavaNativeMethod superInitMethod = JavaNativeMethod.getConstructor(class_.compiled, "()V", Opcodes.ACC_PUBLIC); - final JavaCompilingMethod superInitMethodCompiling = new JavaCompilingMethod(class_.compiled, superInitMethod, "()V"); + final JavaCompilingMethod superInitMethodCompiling = new JavaCompilingMethod(superInitMethod, "()V"); final JavaWriter superInitWriter = new JavaWriter(context.logger, variant.position, writer, superInitMethodCompiling, variant); superInitWriter.start(); superInitWriter.loadObject(0); diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaExpansionMemberVisitor.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaExpansionMemberVisitor.java index 90db87a3..88c3b806 100644 --- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaExpansionMemberVisitor.java +++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaExpansionMemberVisitor.java @@ -44,7 +44,7 @@ public JavaExpansionMemberVisitor(JavaBytecodeContext context, JavaCompilingClas javaModule = context.getJavaModule(definition.module); JavaNativeMethod clinit = new JavaNativeMethod(context.getJavaClass(definition), JavaNativeMethod.Kind.STATICINIT, "", true, "()V", Opcodes.ACC_STATIC, false); - JavaCompilingMethod clinitCompiling = new JavaCompilingMethod(class_.compiled, clinit, "()V"); + JavaCompilingMethod clinitCompiling = new JavaCompilingMethod(clinit, "()V"); final JavaWriter javaWriter = new JavaWriter(context.logger, definition.position, writer, clinitCompiling, definition); this.clinitStatementVisitor = new JavaStatementVisitor(context, javaModule, javaWriter, mangler); this.clinitStatementVisitor.start(); diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java index f2ed2498..59f4e4e4 100644 --- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java +++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java @@ -4,6 +4,8 @@ import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; +import org.openzen.zencode.shared.CodePosition; +import org.openzen.zenscript.codemodel.FunctionHeader; import org.openzen.zenscript.codemodel.FunctionParameter; import org.openzen.zenscript.codemodel.HighLevelDefinition; import org.openzen.zenscript.codemodel.OperatorType; @@ -11,9 +13,13 @@ import org.openzen.zenscript.codemodel.definition.EnumDefinition; import org.openzen.zenscript.codemodel.expression.Expression; import org.openzen.zenscript.codemodel.generic.TypeParameter; +import org.openzen.zenscript.codemodel.identifiers.MethodSymbol; import org.openzen.zenscript.codemodel.identifiers.TypeSymbol; +import org.openzen.zenscript.codemodel.identifiers.instances.MethodInstance; import org.openzen.zenscript.codemodel.member.*; +import org.openzen.zenscript.codemodel.type.BasicTypeID; import org.openzen.zenscript.codemodel.type.DefinitionTypeID; +import org.openzen.zenscript.codemodel.type.TypeID; import org.openzen.zenscript.javabytecode.JavaBytecodeContext; import org.openzen.zenscript.javabytecode.JavaMangler; import org.openzen.zenscript.javabytecode.compiler.*; @@ -48,7 +54,7 @@ public JavaMemberVisitor( javaModule = context.getJavaModule(definition.module); JavaNativeMethod clinitMethod = new JavaNativeMethod(class_.compiled, JavaNativeMethod.Kind.STATICINIT, "", true, "()V", Opcodes.ACC_STATIC, false); - final JavaCompilingMethod clinitMethodCompiling = new JavaCompilingMethod(class_.compiled, clinitMethod, "()V"); + final JavaCompilingMethod clinitMethodCompiling = new JavaCompilingMethod(clinitMethod, "()V"); final JavaWriter javaWriter = new JavaWriter(context.logger, definition.position, writer, clinitMethodCompiling, definition); this.clinitStatementVisitor = new JavaStatementVisitor(context, javaModule, javaWriter, mangler); this.clinitStatementVisitor.start(); @@ -201,6 +207,24 @@ private void visitFunction(FunctionalMember member) { final boolean isAbstract = member.body == null || member.getEffectiveModifiers().isAbstract(); final JavaCompilingMethod method = class_.getMethod(member); + Optional overrides = member.getOverrides(); + if (overrides.isPresent()) { + JavaClass overriddenClass = context.getJavaClass(overrides.get().method.getDefiningType()); + String overriddenMethodSignature = context.getMethodSignature(overrides.get().method.getHeader(), true); + JavaCompilingMethod overriddenMethodInfo = context.getJavaMethod(overrides.get().method) + .asCompilingMethod(overriddenClass, overriddenMethodSignature); + + JavaMemberVisitor.compileBridgeableMethod( + context, + member.position, + writer, + class_.compiled, + overriddenMethodInfo.compiled, + member.header, + overriddenMethodSignature + ); + } + final JavaWriter methodWriter = new JavaWriter(context.logger, member.position, writer, method, definition); if (!isAbstract) { @@ -250,9 +274,6 @@ public Void visitSetter(SetterMember member) { final JavaWriter methodWriter = new JavaWriter(context.logger, member.position, writer, javaMethod, member.definition); methodWriter.label(methodStart); - //ToDo: - // in scripts, you use $ but the parameter is named "value", which to choose? - //final String name = member.parameter.name; final String name = "$"; final int localIndex = member.isStatic() ? 0 : 1; methodWriter.nameVariable(localIndex, name, methodStart, methodEnd, context.getType(member.type)); @@ -276,7 +297,7 @@ public Void visitOperator(OperatorMember member) { if (member.body == null) modifiers |= Opcodes.ACC_ABSTRACT; - final JavaCompilingMethod method = new JavaCompilingMethod(class_.compiled, JavaNativeMethod.getVirtual(class_.compiled, "close", "()V", modifiers), "()V"); + final JavaCompilingMethod method = new JavaCompilingMethod(JavaNativeMethod.getVirtual(class_.compiled, "close", "()V", modifiers), "()V"); if (member.body == null) return null; @@ -410,4 +431,57 @@ public void end() { clinitStatementVisitor.end(); } + + public static JavaCompilingMethod compileBridgeableMethod( + JavaBytecodeContext context, + CodePosition position, + ClassWriter classWriter, + JavaClass localClass, + JavaNativeMethod overriddenMethodInfo, + FunctionHeader implementationHeader, + String overriddenMethodSignature + ) { + final String implementationSignature = context.getMethodSignature(implementationHeader, true); + final String implementationDescriptor = context.getMethodDescriptor(implementationHeader); + + if (!Objects.equals(overriddenMethodInfo.descriptor, implementationDescriptor)) { + final JavaNativeMethod bridgeMethodInfo = overriddenMethodInfo + .withModifiers((overriddenMethodInfo.modifiers | JavaModifiers.BRIDGE | JavaModifiers.SYNTHETIC) & ~JavaModifiers.ABSTRACT); + JavaCompilingMethod compilingBridgeMethod = new JavaCompilingMethod( + bridgeMethodInfo, + overriddenMethodSignature == null ? implementationSignature : overriddenMethodSignature); + final JavaWriter bridgeWriter = new JavaWriter(context.logger, position, classWriter, compilingBridgeMethod, null); + bridgeWriter.start(); + + //This.name(parameters, casted) + bridgeWriter.loadObject(0); + + for (int i = 0; i < implementationHeader.parameters.length; i++) { + final FunctionParameter functionParameter = implementationHeader.parameters[i]; + final Type type = context.getType(functionParameter.type); + bridgeWriter.load(type, i + 1); + if (!CompilerUtils.isPrimitive(functionParameter.type)) { + bridgeWriter.checkCast(type); + } + } + + bridgeWriter.invokeVirtual(new JavaNativeMethod(localClass, JavaNativeMethod.Kind.INSTANCE, overriddenMethodInfo.name, overriddenMethodInfo.compile, implementationDescriptor, overriddenMethodInfo.modifiers, overriddenMethodInfo.genericResult)); + final TypeID returnType = implementationHeader.getReturnType(); + if (returnType != BasicTypeID.VOID) { + final Type returnTypeASM = context.getType(returnType); + if (!CompilerUtils.isPrimitive(returnType)) { + bridgeWriter.checkCast(returnTypeASM); + } + bridgeWriter.returnType(returnTypeASM); + } + + bridgeWriter.ret(); + bridgeWriter.end(); + + JavaNativeMethod actualMethod = overriddenMethodInfo.createBridge(context.getMethodDescriptor(implementationHeader)); + return new JavaCompilingMethod(actualMethod, implementationSignature); + } else { + return new JavaCompilingMethod(overriddenMethodInfo, implementationSignature); + } + } } diff --git a/JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaNativeMethod.java b/JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaNativeMethod.java index 92eb0397..aadf9870 100644 --- a/JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaNativeMethod.java +++ b/JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaNativeMethod.java @@ -112,7 +112,7 @@ public String getMapping(JavaClass definition) { @Override public JavaCompilingMethod asCompilingMethod(JavaClass compiled, String signature) { - return new JavaCompilingMethod(compiled, this, signature, compile); + return new JavaCompilingMethod(this, signature, compile); } public boolean isAbstract() { @@ -123,6 +123,18 @@ public JavaNativeMethod createBridge(String descriptor) { return new JavaNativeMethod(cls, kind, name, compile, descriptor, modifiers, genericResult, typeParameterArguments); } + public JavaNativeMethod withModifiers(int modifiers) { + return new JavaNativeMethod( + cls, + kind, + name, + compile, + descriptor, + modifiers, + genericResult, + typeParameterArguments); + } + @Override public T compileConstructor(JavaMethodCompiler compiler, TypeID type, CallArguments arguments) { if(this.kind == Kind.STATIC) { diff --git a/JavaShared/src/main/java/org/openzen/zenscript/javashared/compiling/JavaCompilingClass.java b/JavaShared/src/main/java/org/openzen/zenscript/javashared/compiling/JavaCompilingClass.java index ca6a4f7b..cb9ee1da 100644 --- a/JavaShared/src/main/java/org/openzen/zenscript/javashared/compiling/JavaCompilingClass.java +++ b/JavaShared/src/main/java/org/openzen/zenscript/javashared/compiling/JavaCompilingClass.java @@ -7,7 +7,6 @@ import org.openzen.zenscript.codemodel.identifiers.FieldSymbol; import org.openzen.zenscript.codemodel.identifiers.MethodID; import org.openzen.zenscript.codemodel.identifiers.MethodSymbol; -import org.openzen.zenscript.codemodel.type.GenericTypeID; import org.openzen.zenscript.codemodel.type.TypeID; import org.openzen.zenscript.javashared.*; @@ -115,7 +114,7 @@ public JavaCompilingMethod addConstructor(MethodSymbol method, NativeTag native_ ); } - JavaCompilingMethod compiling = new JavaCompilingMethod(compiled, javaMethod, getContext().getMethodSignatureConstructor(method)); + JavaCompilingMethod compiling = new JavaCompilingMethod(javaMethod, getContext().getMethodSignatureConstructor(method)); addMethod(method, compiling); return compiling; } @@ -151,7 +150,7 @@ public void addMethod(MethodSymbol method, NativeTag native_) { JavaModifiers.getJavaModifiers(method.getModifiers()), getContext().isGenericReturn(method.getHeader().getReturnType()), method.getHeader().useTypeParameters()); - addMethod(method, new JavaCompilingMethod(compiled, javaMethod, signature)); + addMethod(method, new JavaCompilingMethod(javaMethod, signature)); } public void addDependency(DefinitionSymbol symbol) { diff --git a/JavaShared/src/main/java/org/openzen/zenscript/javashared/compiling/JavaCompilingMethod.java b/JavaShared/src/main/java/org/openzen/zenscript/javashared/compiling/JavaCompilingMethod.java index 7092b5df..7962b41f 100644 --- a/JavaShared/src/main/java/org/openzen/zenscript/javashared/compiling/JavaCompilingMethod.java +++ b/JavaShared/src/main/java/org/openzen/zenscript/javashared/compiling/JavaCompilingMethod.java @@ -9,15 +9,15 @@ public class JavaCompilingMethod { public boolean compile; public final String signature; - public JavaCompilingMethod(JavaClass class_, JavaNativeMethod compiled, String signature) { - this.class_ = class_; + public JavaCompilingMethod(JavaNativeMethod compiled, String signature) { + this.class_ = compiled.cls; this.compiled = compiled; this.signature = signature; this.compile = true; } - public JavaCompilingMethod(JavaClass class_, JavaNativeMethod compiled, String signature, boolean compile) { - this.class_ = class_; + public JavaCompilingMethod(JavaNativeMethod compiled, String signature, boolean compile) { + this.class_ = compiled.cls; this.compiled = compiled; this.signature = signature; this.compile = compile; diff --git a/JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareClassMethodVisitor.java b/JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareClassMethodVisitor.java index 76bba6e7..507c0b32 100644 --- a/JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareClassMethodVisitor.java +++ b/JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareClassMethodVisitor.java @@ -10,7 +10,6 @@ import org.openzen.zenscript.codemodel.FunctionParameter; import org.openzen.zenscript.codemodel.OperatorType; import org.openzen.zenscript.codemodel.annotations.NativeTag; -import org.openzen.zenscript.codemodel.identifiers.instances.MethodInstance; import org.openzen.zenscript.codemodel.member.*; import org.openzen.zenscript.codemodel.type.BasicTypeID; import org.openzen.zenscript.javashared.*; @@ -18,8 +17,6 @@ import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod; import org.openzen.zenscript.javashared.compiling.JavaCompilingModule; -import java.util.Optional; - /** * @author Hoofdgebruiker */ @@ -248,7 +245,7 @@ private void visitFunctional(FunctionalMember member, FunctionHeader header, Str JavaCompilingMethod method = null; if (nativeTag != null && class_.nativeClass != null) { final String signature = context.getMethodSignature(header); - method = new JavaCompilingMethod(class_.compiled, (JavaNativeMethod) class_.nativeClass.getMethod(nativeTag.value), signature); + method = new JavaCompilingMethod((JavaNativeMethod) class_.nativeClass.getMethod(nativeTag.value), signature); } for (FunctionParameter parameter : header.parameters) { @@ -261,7 +258,7 @@ private void visitFunctional(FunctionalMember member, FunctionHeader header, Str if (member instanceof ConstructorMember) { if(member.isImplicit()) { final String signature = context.getMethodSignature(header, true); - method = new JavaCompilingMethod(class_.compiled, new JavaNativeMethod( + method = new JavaCompilingMethod(new JavaNativeMethod( class_.compiled, getKind(member), "implicit-constructor", @@ -273,7 +270,7 @@ private void visitFunctional(FunctionalMember member, FunctionHeader header, Str signature); } else { final String signature = context.getMethodSignatureConstructor(member); - method = new JavaCompilingMethod(class_.compiled, new JavaNativeMethod( + method = new JavaCompilingMethod(new JavaNativeMethod( class_.compiled, getKind(member), name, @@ -288,7 +285,7 @@ private void visitFunctional(FunctionalMember member, FunctionHeader header, Str } else { final String signature = context.getMethodSignature(header); - method = new JavaCompilingMethod(class_.compiled, new JavaNativeMethod( + method = new JavaCompilingMethod(new JavaNativeMethod( class_.compiled, getKind(member), name, diff --git a/JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareDefinitionMemberVisitor.java b/JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareDefinitionMemberVisitor.java index 183c8cf0..30157fe0 100644 --- a/JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareDefinitionMemberVisitor.java +++ b/JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareDefinitionMemberVisitor.java @@ -7,7 +7,6 @@ import org.openzen.zenscript.codemodel.HighLevelDefinition; import org.openzen.zenscript.codemodel.definition.*; -import org.openzen.zenscript.codemodel.generic.TypeParameter; import org.openzen.zenscript.codemodel.member.IDefinitionMember; import org.openzen.zenscript.javashared.*; import org.openzen.zenscript.javashared.compiling.JavaCompilingClass; @@ -66,7 +65,7 @@ public Void visitFunction(FunctionDefinition definition) { descriptor, JavaModifiers.getJavaModifiers(definition.modifiers), definition.header.getReturnType().isGeneric()); - class_.addMethod(definition.caller, new JavaCompilingMethod(class_.compiled, method, signature)); + class_.addMethod(definition.caller, new JavaCompilingMethod(method, signature)); return null; }