Browse Source

WIP Functional Wrapper

Currently only supports 'accepts' methods, until we can get a way to get the actual method signature/name from the class
kindlich 5 years ago
parent
commit
da4c6eb005
No known key found for this signature in database

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

@@ -5,8 +5,10 @@ import org.objectweb.asm.Label;
5 5
 import org.objectweb.asm.Opcodes;
6 6
 import org.objectweb.asm.Type;
7 7
 import org.openzen.zenscript.codemodel.CompareType;
8
+import org.openzen.zenscript.codemodel.FunctionParameter;
8 9
 import org.openzen.zenscript.codemodel.expression.*;
9 10
 import org.openzen.zenscript.codemodel.expression.switchvalue.VariantOptionSwitchValue;
11
+import org.openzen.zenscript.codemodel.generic.TypeParameter;
10 12
 import org.openzen.zenscript.codemodel.member.ref.DefinitionMemberRef;
11 13
 import org.openzen.zenscript.codemodel.member.ref.FieldMemberRef;
12 14
 import org.openzen.zenscript.codemodel.statement.ReturnStatement;
@@ -3893,6 +3895,13 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
3893 3895
 	@Override
3894 3896
 	public Void visitStorageCast(StorageCastExpression expression) {
3895 3897
 		expression.value.accept(this);
3898
+		
3899
+		{
3900
+			final StorageTag specifiedStorage = expression.type.getSpecifiedStorage();
3901
+			if(specifiedStorage instanceof JavaFunctionalInterfaceStorageTag) {
3902
+				visitFunctionalInterfaceWrapping(expression, (JavaFunctionalInterfaceStorageTag) specifiedStorage);
3903
+			}
3904
+		}
3896 3905
 
3897 3906
 		if (expression.type.isDestructible()) { // only destructible types matter here; nondestructible types never need conversion
3898 3907
 			StorageTag fromTag = expression.value.type.getActualStorage();
@@ -3910,6 +3919,77 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
3910 3919
 
3911 3920
 		return null;
3912 3921
 	}
3922
+	
3923
+	private void visitFunctionalInterfaceWrapping(StorageCastExpression expression, JavaFunctionalInterfaceStorageTag tag) {
3924
+		final Method functionalInterfaceMethod = tag.functionalInterfaceMethod;
3925
+		
3926
+		final String wrappedSignature = context.getDescriptor(expression.type);
3927
+		final String wrappedMethodName = "accept";
3928
+		final String constructorDesc = "(" + wrappedSignature + ")V";
3929
+		
3930
+		final String className = context.getLambdaCounter();
3931
+		final String descriptor = Type.getMethodDescriptor(functionalInterfaceMethod);
3932
+		//ddd
3933
+		final String methodName = functionalInterfaceMethod.getName();
3934
+		final String[] interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
3935
+		
3936
+		final FunctionParameter[] functionParameters = ((FunctionTypeID) expression.value.type.type).header.parameters;
3937
+		final String wrappedMethodSig = context.getMethodDescriptor(((FunctionTypeID) expression.value.type.type).header);
3938
+		
3939
+		
3940
+		javaWriter.newObject(className);
3941
+		javaWriter.dupX1();
3942
+		javaWriter.swap();
3943
+		javaWriter.invokeSpecial(className, "<init>", constructorDesc);
3944
+		
3945
+		
3946
+		final JavaMethod methodInfo = JavaMethod.getNativeVirtual(javaWriter.method.cls, methodName, descriptor);
3947
+		final ClassWriter lambdaCW = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
3948
+		lambdaCW.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", interfaces);
3949
+		
3950
+		
3951
+		lambdaCW.visitField(Modifier.PRIVATE | Modifier.FINAL, "wrapped", wrappedSignature, null, null).visitEnd();
3952
+		
3953
+		final JavaWriter constructorWriter = new JavaWriter(expression.position, lambdaCW, JavaMethod.getConstructor(javaWriter.method.cls, constructorDesc, Opcodes.ACC_PUBLIC), null, null, null);
3954
+		constructorWriter.start();
3955
+		constructorWriter.loadObject(0);
3956
+		constructorWriter.dup();
3957
+		constructorWriter.invokeSpecial(Object.class, "<init>", "()V");
3958
+		
3959
+		constructorWriter.loadObject(1);
3960
+		constructorWriter.putField(className, "wrapped", wrappedSignature);
3961
+		
3962
+		constructorWriter.ret();
3963
+		constructorWriter.end();
3964
+		
3965
+		
3966
+		final JavaWriter functionWriter = new JavaWriter(expression.position, lambdaCW, methodInfo, null, descriptor, null, "java/lang/Override");
3967
+		functionWriter.start();
3968
+		
3969
+		//this.wrapped
3970
+		functionWriter.loadObject(0);
3971
+		functionWriter.getField(className, "wrapped", wrappedSignature);
3972
+		for (int i = 0; i < functionParameters.length; i++) {
3973
+			final FunctionParameter functionParameter = functionParameters[i];
3974
+			functionWriter.load(context.getType(functionParameter.type), i + 1);
3975
+		}
3976
+		
3977
+		functionWriter.invokeInterface(JavaMethod.getVirtual(JavaClass.fromInternalName(context.getInternalName(expression.type.type), JavaClass.Kind.INTERFACE), wrappedMethodName, wrappedMethodSig, 0));
3978
+		
3979
+		functionWriter.returnType(context.getType(((FunctionTypeID) expression.value.type.type).header.getReturnType()));
3980
+		
3981
+		functionWriter.ret();
3982
+		functionWriter.end();
3983
+		lambdaCW.visitEnd();
3984
+		
3985
+		context.register(className, lambdaCW.toByteArray());
3986
+		
3987
+		try (FileOutputStream out = new FileOutputStream(className + ".class")) {
3988
+			out.write(lambdaCW.toByteArray());
3989
+		} catch (IOException e) {
3990
+			e.printStackTrace();
3991
+		}
3992
+	}
3913 3993
 
3914 3994
 	@Override
3915 3995
 	public Void visitSupertypeCast(SupertypeCastExpression expression) {

+ 10
- 0
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/Globals.java View File

@@ -52,6 +52,11 @@ public class Globals implements ZenCodeGlobals {
52 52
 		System.out.println("doSomething: " + greeter.doSomething("world"));
53 53
 	}
54 54
 	
55
+	@Global
56
+	public static void invokeFunctionalInt(MyFunctionalInterfaceInt calculator){
57
+		System.out.println("FunctionalInt: " + calculator.doSomething(7, 13));
58
+	}
59
+	
55 60
 	public static TestClass bracket(String value) {
56 61
 		return new TestClass(value);
57 62
 	}
@@ -60,4 +65,9 @@ public class Globals implements ZenCodeGlobals {
60 65
 	public static interface MyFunctionalInterface {
61 66
 		String doSomething(String value);
62 67
 	}
68
+	
69
+	@FunctionalInterface
70
+	public static interface MyFunctionalInterfaceInt {
71
+		int doSomething(int valueA, int valueB);
72
+	}
63 73
 }

Loading…
Cancel
Save