Quellcode durchsuchen

Functional Wrappers, Bridge Methods, Type descriptor fix

Functional interface wrappers should work now
Implementing a method with a signature differing from the actual one (e.g. when dealing with generics) now creates a proper bridge method
The Java Bytecde compiler used an incorrect method in checkCast
We now no longer use hardcoded 'accept's as method names but whatever the context tells us to.
kindlich vor 5 Jahren
Ursprung
Commit
9494ef212e
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden

+ 1
- 1
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeContext.java Datei anzeigen

@@ -86,7 +86,7 @@ public class JavaBytecodeContext extends JavaContext {
86 86
         ifaceWriter
87 87
 				.visitMethod(
88 88
 					Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
89
-					"accept",
89
+					function.method,
90 90
 					getMethodDescriptor(function.header),
91 91
 					getMethodSignature(function.header),
92 92
 					null)

+ 42
- 15
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java Datei anzeigen

@@ -1127,11 +1127,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
1127 1127
 				break;
1128 1128
 			}
1129 1129
 			case FUNCTION_CALL:
1130
-				javaWriter.invokeInterface(
1131
-						JavaMethod.getNativeVirtual(
1132
-								JavaClass.fromInternalName(context.getInternalName(expression.target.type), JavaClass.Kind.INTERFACE),
1133
-								"accept",
1134
-								context.getMethodDescriptor(expression.instancedHeader)));
1130
+				javaWriter.invokeInterface(context.getFunctionalInterface(expression.target.type));
1135 1131
 				break;
1136 1132
 			case AUTOOP_NOTEQUALS:
1137 1133
 				throw new UnsupportedOperationException("Not yet supported!");
@@ -1870,10 +1866,8 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
1870 1866
             return null;
1871 1867
         }*/
1872 1868
 
1873
-		final String descriptor;
1874 1869
 		final String signature;
1875 1870
 		final String[] interfaces;
1876
-		final String methodName;
1877 1871
 		final String className = context.getLambdaCounter();
1878 1872
 		
1879 1873
 		{//Fill the info above
@@ -1882,25 +1876,58 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
1882 1876
 				//Let's implement the functional Interface instead
1883 1877
 				final Method functionalInterfaceMethod = ((JavaFunctionalInterfaceStorageTag) actualStorage).functionalInterfaceMethod;
1884 1878
 				
1885
-				descriptor = Type.getMethodDescriptor(functionalInterfaceMethod);
1886 1879
 				//Should be the same, should it not?
1887 1880
 				signature = context.getMethodSignature(expression.header);
1888 1881
 				interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
1889
-				methodName = functionalInterfaceMethod.getName();
1890 1882
 			} else {
1891 1883
 				//Normal way, no casting to functional interface
1892
-				descriptor = context.getMethodDescriptor(expression.header);
1893 1884
 				signature = context.getMethodSignature(expression.header);
1894 1885
 				interfaces = new String[]{context.getInternalName(new FunctionTypeID(null, expression.header).stored(UniqueStorageTag.INSTANCE))};
1895
-				methodName = "accept";
1896 1886
 			}
1897 1887
 		}
1898 1888
 		
1899 1889
 		
1900
-		final JavaMethod methodInfo = JavaMethod.getNativeVirtual(javaWriter.method.cls, methodName, descriptor);
1890
+		final JavaMethod methodInfo;
1891
+		{
1892
+			final JavaMethod m = context.getFunctionalInterface(expression.type);
1893
+			methodInfo = new JavaMethod(m.cls, m.kind, m.name, m.compile, m.descriptor, m.modifiers & ~JavaModifiers.ABSTRACT, m.genericResult, m.typeParameterArguments);
1894
+		}
1901 1895
 		final ClassWriter lambdaCW = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
1902 1896
 		lambdaCW.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", interfaces);
1903
-		final JavaWriter functionWriter = new JavaWriter(expression.position, lambdaCW, methodInfo, null, signature, null, "java/lang/Override");
1897
+		final JavaWriter functionWriter;
1898
+		
1899
+		//Bridge method!!!
1900
+		if(!Objects.equals(methodInfo.descriptor, signature)) {
1901
+			final JavaMethod bridgeMethodInfo = new JavaMethod(methodInfo.cls, methodInfo.kind, methodInfo.name, methodInfo.compile, methodInfo.descriptor, methodInfo.modifiers | JavaModifiers.BRIDGE | JavaModifiers.SYNTHETIC, methodInfo.genericResult, methodInfo.typeParameterArguments);
1902
+			final JavaWriter bridgeWriter = new JavaWriter(expression.position, lambdaCW, bridgeMethodInfo, null, methodInfo.descriptor, null, "java/lang/Override");
1903
+			bridgeWriter.start();
1904
+			
1905
+			//This.name(parameters, casted)
1906
+			bridgeWriter.loadObject(0);
1907
+			
1908
+			for (int i = 0; i < expression.header.parameters.length; i++) {
1909
+				final FunctionParameter functionParameter = expression.header.parameters[i];
1910
+				final Type type = context.getType(functionParameter.type);
1911
+				bridgeWriter.load(type, i + 1);
1912
+				bridgeWriter.checkCast(type);
1913
+			}
1914
+			
1915
+			bridgeWriter.invokeVirtual(methodInfo);
1916
+			if(expression.header.getReturnType().type != BasicTypeID.VOID) {
1917
+				bridgeWriter.returnType(context.getType(expression.header.getReturnType()));
1918
+			}
1919
+			
1920
+			bridgeWriter.ret();
1921
+			bridgeWriter.end();
1922
+			
1923
+			
1924
+			
1925
+			final JavaMethod actualMethod = new JavaMethod(methodInfo.cls, methodInfo.kind, methodInfo.name, methodInfo.compile, signature, methodInfo.modifiers, methodInfo.genericResult, methodInfo.typeParameterArguments);
1926
+			//No @Override
1927
+			functionWriter = new JavaWriter(expression.position, lambdaCW, actualMethod, null, signature, null);
1928
+		} else {
1929
+			functionWriter = new JavaWriter(expression.position, lambdaCW, methodInfo, null, signature, null, "java/lang/Override");
1930
+		}
1904 1931
 
1905 1932
 		javaWriter.newObject(className);
1906 1933
 		javaWriter.dup();
@@ -3930,7 +3957,6 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
3930 3957
 		final String constructorDesc = "(" + wrappedSignature + ")V";
3931 3958
 		
3932 3959
 		final String className = context.getLambdaCounter();
3933
-		final String methodName = functionalInterfaceMethod.getName();
3934 3960
 		final String methodDescriptor = Type.getMethodDescriptor(functionalInterfaceMethod);
3935 3961
 		final String[] interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
3936 3962
 
@@ -3959,7 +3985,8 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
3959 3985
 
3960 3986
 		//The actual method
3961 3987
 		{
3962
-			final JavaWriter functionWriter = new JavaWriter(expression.position, lambdaCW, tag.method, null, methodDescriptor, null, "java/lang/Override");
3988
+			final JavaMethod actualMethod = new JavaMethod(tag.method.cls, tag.method.kind, tag.method.name, tag.method.compile, tag.method.descriptor, tag.method.modifiers & ~JavaModifiers.ABSTRACT, tag.method.genericResult, tag.method.typeParameterArguments);
3989
+			final JavaWriter functionWriter = new JavaWriter(expression.position, lambdaCW, actualMethod, null, methodDescriptor, null, "java/lang/Override");
3963 3990
 			functionWriter.start();
3964 3991
 
3965 3992
 			//this.wrapped

+ 1
- 1
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java Datei anzeigen

@@ -418,7 +418,7 @@ public class JavaWriter {
418 418
         if (debug)
419 419
             System.out.println("checkCast " + type.getDescriptor());
420 420
 
421
-        visitor.visitTypeInsn(CHECKCAST, type.getDescriptor());
421
+        visitor.visitTypeInsn(CHECKCAST, type.getInternalName());
422 422
     }
423 423
 
424 424
     public void iNeg() {

+ 1
- 1
JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaContext.java Datei anzeigen

@@ -115,7 +115,7 @@ public abstract class JavaContext {
115 115
 					function.getMethod(),
116 116
 					false,
117 117
 					getMethodDescriptor(function.getHeader()),
118
-					Modifiers.PUBLIC | Modifiers.ABSTRACT,
118
+					JavaModifiers.PUBLIC | JavaModifiers.ABSTRACT,
119 119
 					function.getHeader().getReturnType().isGeneric());
120 120
 		}
121 121
 	}

+ 11
- 0
ScriptingExample/scripts/functionalInterfaces.zs Datei anzeigen

@@ -0,0 +1,11 @@
1
+//val x = ((a as string) => "hello" + a) as function`auto(a as string) as string`auto;
2
+//invokeFunctional(x);
3
+
4
+val y = (a as int, b as int) => a + b;
5
+
6
+
7
+//invokeFunctionalInt((a, b) => a + b);
8
+invokeFunctionalInt(y);
9
+
10
+
11
+println(((x as int) => x)(10));

Laden…
Abbrechen
Speichern