Browse Source

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 5 years ago
parent
commit
9494ef212e
No known key found for this signature in database

+ 1
- 1
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaBytecodeContext.java View File

86
         ifaceWriter
86
         ifaceWriter
87
 				.visitMethod(
87
 				.visitMethod(
88
 					Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
88
 					Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
89
-					"accept",
89
+					function.method,
90
 					getMethodDescriptor(function.header),
90
 					getMethodDescriptor(function.header),
91
 					getMethodSignature(function.header),
91
 					getMethodSignature(function.header),
92
 					null)
92
 					null)

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

1127
 				break;
1127
 				break;
1128
 			}
1128
 			}
1129
 			case FUNCTION_CALL:
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
 				break;
1131
 				break;
1136
 			case AUTOOP_NOTEQUALS:
1132
 			case AUTOOP_NOTEQUALS:
1137
 				throw new UnsupportedOperationException("Not yet supported!");
1133
 				throw new UnsupportedOperationException("Not yet supported!");
1870
             return null;
1866
             return null;
1871
         }*/
1867
         }*/
1872
 
1868
 
1873
-		final String descriptor;
1874
 		final String signature;
1869
 		final String signature;
1875
 		final String[] interfaces;
1870
 		final String[] interfaces;
1876
-		final String methodName;
1877
 		final String className = context.getLambdaCounter();
1871
 		final String className = context.getLambdaCounter();
1878
 		
1872
 		
1879
 		{//Fill the info above
1873
 		{//Fill the info above
1882
 				//Let's implement the functional Interface instead
1876
 				//Let's implement the functional Interface instead
1883
 				final Method functionalInterfaceMethod = ((JavaFunctionalInterfaceStorageTag) actualStorage).functionalInterfaceMethod;
1877
 				final Method functionalInterfaceMethod = ((JavaFunctionalInterfaceStorageTag) actualStorage).functionalInterfaceMethod;
1884
 				
1878
 				
1885
-				descriptor = Type.getMethodDescriptor(functionalInterfaceMethod);
1886
 				//Should be the same, should it not?
1879
 				//Should be the same, should it not?
1887
 				signature = context.getMethodSignature(expression.header);
1880
 				signature = context.getMethodSignature(expression.header);
1888
 				interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
1881
 				interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
1889
-				methodName = functionalInterfaceMethod.getName();
1890
 			} else {
1882
 			} else {
1891
 				//Normal way, no casting to functional interface
1883
 				//Normal way, no casting to functional interface
1892
-				descriptor = context.getMethodDescriptor(expression.header);
1893
 				signature = context.getMethodSignature(expression.header);
1884
 				signature = context.getMethodSignature(expression.header);
1894
 				interfaces = new String[]{context.getInternalName(new FunctionTypeID(null, expression.header).stored(UniqueStorageTag.INSTANCE))};
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
 		final ClassWriter lambdaCW = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
1895
 		final ClassWriter lambdaCW = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
1902
 		lambdaCW.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", interfaces);
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
 		javaWriter.newObject(className);
1932
 		javaWriter.newObject(className);
1906
 		javaWriter.dup();
1933
 		javaWriter.dup();
3930
 		final String constructorDesc = "(" + wrappedSignature + ")V";
3957
 		final String constructorDesc = "(" + wrappedSignature + ")V";
3931
 		
3958
 		
3932
 		final String className = context.getLambdaCounter();
3959
 		final String className = context.getLambdaCounter();
3933
-		final String methodName = functionalInterfaceMethod.getName();
3934
 		final String methodDescriptor = Type.getMethodDescriptor(functionalInterfaceMethod);
3960
 		final String methodDescriptor = Type.getMethodDescriptor(functionalInterfaceMethod);
3935
 		final String[] interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
3961
 		final String[] interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
3936
 
3962
 
3959
 
3985
 
3960
 		//The actual method
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
 			functionWriter.start();
3990
 			functionWriter.start();
3964
 
3991
 
3965
 			//this.wrapped
3992
 			//this.wrapped

+ 1
- 1
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java View File

418
         if (debug)
418
         if (debug)
419
             System.out.println("checkCast " + type.getDescriptor());
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
     public void iNeg() {
424
     public void iNeg() {

+ 1
- 1
JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaContext.java View File

115
 					function.getMethod(),
115
 					function.getMethod(),
116
 					false,
116
 					false,
117
 					getMethodDescriptor(function.getHeader()),
117
 					getMethodDescriptor(function.getHeader()),
118
-					Modifiers.PUBLIC | Modifiers.ABSTRACT,
118
+					JavaModifiers.PUBLIC | JavaModifiers.ABSTRACT,
119
 					function.getHeader().getReturnType().isGeneric());
119
 					function.getHeader().getReturnType().isGeneric());
120
 		}
120
 		}
121
 	}
121
 	}

+ 11
- 0
ScriptingExample/scripts/functionalInterfaces.zs View File

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));

Loading…
Cancel
Save