Skip to content

Commit ee69630

Browse files
committed
Move FunctionalInterface conversion to Indy too
Signed-off-by: TheSilkMiner <thesilkminer@outlook.com>
1 parent b276a68 commit ee69630

3 files changed

Lines changed: 67 additions & 216 deletions

File tree

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaMangler.java

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -153,42 +153,6 @@ public int hashCode() {
153153
return "$lambda$" + sanitizedMethodName + '$' + canonicalInterfaceTarget + '$' + this.mangleCounters.get(id);
154154
}
155155

156-
public String mangleGeneratedLambdaName(final String interfaceName) {
157-
final class LambdaId {
158-
final String target;
159-
160-
LambdaId(final String target) {
161-
this.target = target;
162-
}
163-
164-
@Override
165-
public boolean equals(final Object o) {
166-
return this == o || o instanceof LambdaId && this.target.equals(((LambdaId) o).target);
167-
}
168-
169-
@Override
170-
public int hashCode() {
171-
return 17 * this.target.hashCode();
172-
}
173-
}
174-
175-
final String interfaceTarget = interfaceName.replace('/', '_').replace('.', '_');
176-
// TODO("Rework package structure")
177-
return "zsynthetic/$Lambda$" + interfaceTarget + '$' + this.mangleCounters.get(new LambdaId(interfaceTarget));
178-
}
179-
180-
public String mangleGeneratedLambdaName(final FunctionHeader header) {
181-
return this.mangleGeneratedLambdaName("$Generated" + EXP_TAR_MANGLE_FUNCTION_ID + this.encodeLengthNameFormat(this.mangleFunctionHeader(header)));
182-
}
183-
184-
public String mangleCapturedParameter(final int parameterId, final boolean isThis) {
185-
if (isThis) {
186-
return "$this";
187-
} else {
188-
return "$" + parameterId;
189-
}
190-
}
191-
192156
private String mangleScriptName(final String rawName) {
193157
if (rawName == null) {
194158
class GeneratedBlock {}

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java

Lines changed: 18 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package org.openzen.zenscript.javabytecode.compiler;
22

3-
import org.objectweb.asm.ClassWriter;
43
import org.objectweb.asm.Label;
5-
import org.objectweb.asm.Opcodes;
64
import org.objectweb.asm.Type;
7-
import org.openzen.zencode.shared.CodePosition;
85
import org.openzen.zenscript.codemodel.CompareType;
96
import org.openzen.zenscript.codemodel.FunctionHeader;
107
import org.openzen.zenscript.codemodel.OperatorType;
@@ -25,12 +22,9 @@
2522
import org.openzen.zenscript.javabytecode.compiler.lambda.LambdaIndyCompiler;
2623
import org.openzen.zenscript.javabytecode.compiler.lambda.capturing.JavaInvalidCapturedExpressionVisitor;
2724
import org.openzen.zenscript.javashared.*;
28-
import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod;
2925
import org.openzen.zenscript.javashared.expressions.JavaFunctionInterfaceCastExpression;
3026
import org.openzen.zenscript.javashared.types.JavaFunctionalInterfaceTypeID;
3127

32-
import java.lang.reflect.Method;
33-
import java.lang.reflect.Modifier;
3428
import java.util.*;
3529

3630
import static org.openzen.zenscript.javabytecode.compiler.JavaMethodBytecodeCompiler.OBJECT_HASHCODE;
@@ -50,6 +44,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
5044
private final JavaUnboxingTypeVisitor optionalUnwrappingTypeVisitor;
5145
private final JavaFieldBytecodeCompiler fieldCompiler;
5246
public final JavaMethodBytecodeCompiler methodCompiler;
47+
private final LambdaIndyCompiler lambdaIndyCompiler;
5348
private final CapturedExpressionVisitor<Void> capturedExpressionVisitor;
5449

5550
public JavaExpressionVisitor(JavaBytecodeContext context, JavaCompiledModule module, JavaWriter javaWriter, JavaMangler javaMangler) {
@@ -67,6 +62,7 @@ public JavaExpressionVisitor(JavaBytecodeContext context, JavaCompiledModule mod
6762
optionalUnwrappingTypeVisitor = JavaUnboxingTypeVisitor.forOptionalUnwrapping(javaWriter);
6863
fieldCompiler = new JavaFieldBytecodeCompiler(javaWriter, this, true);
6964
methodCompiler = new JavaMethodBytecodeCompiler(javaWriter, this, context, module);
65+
this.lambdaIndyCompiler = LambdaIndyCompiler.of(this.javaWriter, this.javaMangler, this.context, this.module, this);
7066
this.capturedExpressionVisitor = capturedExpressionVisitor;
7167
}
7268

@@ -488,8 +484,7 @@ public Void visitFunction(FunctionExpression expression) {
488484
final JavaNativeMethod functionalMethod = context.getFunctionalInterface(expression.original == null ? expression.type : new FunctionTypeID(expression.original));
489485
final JavaNativeMethod methodInfo = functionalMethod.withModifiers(functionalMethod.modifiers & ~JavaModifiers.ABSTRACT);
490486

491-
final LambdaIndyCompiler lambdaCompiler = LambdaIndyCompiler.of(this.javaWriter, this.javaMangler, this.context, this.module, this);
492-
lambdaCompiler.compileFunctionExpressionViaIndy(expression, interfaceName, methodInfo);
487+
this.lambdaIndyCompiler.compileFunctionExpressionViaIndy(expression, interfaceName, methodInfo);
493488

494489
return null;
495490
}
@@ -869,16 +864,17 @@ private void modify(ModifiableExpression source, Runnable modification, PushOpti
869864

870865
@Override
871866
public Void visitPlatformSpecific(Expression expression) {
872-
if (expression instanceof JavaFunctionInterfaceCastExpression) {
873-
JavaFunctionInterfaceCastExpression jficExpression = (JavaFunctionInterfaceCastExpression) expression;
874-
if (jficExpression.value.type instanceof JavaFunctionalInterfaceTypeID) {
875-
jficExpression.value.accept(this);
876-
} else {
877-
visitFunctionalInterfaceWrapping(jficExpression);
878-
}
879-
} else {
880-
throw new AssertionError("Unrecognized platform expression: " + expression);
867+
if (!(expression instanceof JavaFunctionInterfaceCastExpression)) {
868+
throw new AssertionError("Unrecognized platform expression " + expression.getClass().getName() + ": " + expression);
869+
}
870+
871+
final JavaFunctionInterfaceCastExpression jficExpression = (JavaFunctionInterfaceCastExpression) expression;
872+
873+
if (jficExpression.value.type instanceof JavaFunctionalInterfaceTypeID) {
874+
return jficExpression.value.accept(this);
881875
}
876+
877+
this.lambdaIndyCompiler.convertTypeOfFunctionExpressionViaIndy(jficExpression);
882878
return null;
883879
}
884880

@@ -906,9 +902,11 @@ public void modify(ModificationExpression expression, PushOption pushOption) {
906902
BuiltinMethodSymbol builtin = (BuiltinMethodSymbol) expression.method.method;
907903
modify(expression.target, builtin, pushOption);
908904
} else {
909-
modify(expression.target, () -> {
910-
context.getJavaMethod(expression.method).compileVirtualWithTargetOnTopOfStack(methodCompiler, expression.type, CallArguments.EMPTY);
911-
}, pushOption);
905+
modify(
906+
expression.target,
907+
() -> context.getJavaMethod(expression.method).compileVirtualWithTargetOnTopOfStack(methodCompiler, expression.type, CallArguments.EMPTY),
908+
pushOption
909+
);
912910
}
913911
}
914912

@@ -981,148 +979,6 @@ public Void visitSetStaticField(SetStaticFieldExpression expression) {
981979
return null;
982980
}
983981

984-
private void visitFunctionalInterfaceWrapping(JavaFunctionInterfaceCastExpression expression) {
985-
// TODO("Move to LambdaFactory")
986-
// To do the above, we simply need to be able to "extract" this into a lambda form.
987-
// In other words, if we have to convert (OurThing -> Function), as of now:
988-
// 1. Generate a lambda method with the signature (ThisClass, ..., OurThing)
989-
// 2. Fill the lambda method with simply $capture.invoke(...)
990-
// 3. Invoke LambdaFactory passing the current OurThing instance as a capture; ThisClass can be simply always loaded as null as we always ignore it
991-
// In the above, ... denotes parameters, **never** captures
992-
final FunctionCastWrapperClass wrapper = generateFunctionCastWrapperClass(
993-
expression.position,
994-
(FunctionTypeID) expression.value.type,
995-
expression.functionType);
996-
997-
expression.value.accept(this);
998-
javaWriter.newObject(wrapper.className);
999-
javaWriter.dupX1();
1000-
javaWriter.swap();
1001-
javaWriter.invokeSpecial(wrapper.className, "<init>", wrapper.constructorDesc);
1002-
}
1003-
1004-
private FunctionCastWrapperClass generateFunctionCastWrapperClass(CodePosition position, FunctionTypeID fromType, FunctionTypeID toType) {
1005-
final String className = this.javaMangler.mangleGeneratedLambdaName(fromType.header);
1006-
final JavaClass classInfo = JavaClass.fromInternalName(className, JavaClass.Kind.CLASS);
1007-
1008-
String[] interfaces;
1009-
String wrappedFromSignature = context.getDescriptor(fromType);
1010-
String methodDescriptor;
1011-
String methodSignature;
1012-
Type[] methodParameterTypes;
1013-
JavaNativeMethod implementationMethod;
1014-
if (toType instanceof JavaFunctionalInterfaceTypeID) {
1015-
JavaNativeMethod javaMethod = ((JavaFunctionalInterfaceTypeID) toType).method;
1016-
implementationMethod = new JavaNativeMethod(
1017-
classInfo,
1018-
JavaNativeMethod.Kind.COMPILED,
1019-
javaMethod.name,
1020-
true,
1021-
javaMethod.descriptor,
1022-
javaMethod.modifiers & ~JavaModifiers.ABSTRACT,
1023-
javaMethod.genericResult,
1024-
javaMethod.typeParameterArguments);
1025-
1026-
final Method functionalInterfaceMethod = ((JavaFunctionalInterfaceTypeID) toType).functionalInterfaceMethod;
1027-
1028-
methodDescriptor = Type.getMethodDescriptor(functionalInterfaceMethod);
1029-
// ToDo: Is signature===descriptor fine here or do we need the actual signature here?
1030-
methodSignature = methodDescriptor;
1031-
interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
1032-
1033-
final Class<?>[] methodParameterClasses = functionalInterfaceMethod.getParameterTypes();
1034-
methodParameterTypes = new Type[methodParameterClasses.length];
1035-
for (int i = 0; i < methodParameterClasses.length; i++) {
1036-
final Class<?> methodParameterType = methodParameterClasses[i];
1037-
methodParameterTypes[i] = Type.getType(methodParameterType);
1038-
}
1039-
} else {
1040-
wrappedFromSignature = context.getMethodSignature(toType.header, true);
1041-
methodDescriptor = context.getMethodDescriptor(toType.header);
1042-
methodSignature = context.getMethodSignature(toType.header);
1043-
interfaces = new String[]{context.getInternalName(toType)};
1044-
1045-
JavaSynthesizedFunctionInstance function = context.getFunction(toType);
1046-
1047-
implementationMethod = new JavaNativeMethod(
1048-
classInfo,
1049-
JavaNativeMethod.Kind.COMPILED,
1050-
function.getMethod(),
1051-
true,
1052-
methodDescriptor,
1053-
JavaModifiers.PUBLIC,
1054-
false // TODO: generic result or not
1055-
);
1056-
1057-
methodParameterTypes = new Type[toType.header.parameters.length];
1058-
for (int i = 0; i < methodParameterTypes.length; i++) {
1059-
methodParameterTypes[i] = context.getType(toType.header.parameters[i].type);
1060-
}
1061-
}
1062-
1063-
final JavaNativeMethod wrappedMethod = context.getFunctionalInterface(fromType);
1064-
final String constructorDescriptor = "(" + wrappedFromSignature + ")V";
1065-
// ToDo: Is signature===descriptor fine here or do we need the actual signature here?
1066-
final String constructorSignature = "(" + wrappedFromSignature + ")V";
1067-
1068-
final ClassWriter lambdaCW = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
1069-
lambdaCW.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", interfaces);
1070-
1071-
//The field storing the wrapped object
1072-
{
1073-
lambdaCW.visitField(Modifier.PRIVATE | Modifier.FINAL, "wrapped", wrappedFromSignature, null, null).visitEnd();
1074-
}
1075-
1076-
//Constructor
1077-
{
1078-
JavaNativeMethod constructor = JavaNativeMethod.getConstructor(classInfo, constructorDescriptor, Opcodes.ACC_PUBLIC);
1079-
JavaCompilingMethod compiling = new JavaCompilingMethod(constructor, constructorSignature);
1080-
final JavaWriter constructorWriter = new JavaWriter(context.logger, position, lambdaCW, compiling, null);
1081-
constructorWriter.start();
1082-
constructorWriter.loadObject(0);
1083-
constructorWriter.dup();
1084-
constructorWriter.invokeSpecial(Object.class, "<init>", "()V");
1085-
1086-
constructorWriter.loadObject(1);
1087-
constructorWriter.putField(className, "wrapped", wrappedFromSignature);
1088-
1089-
constructorWriter.ret();
1090-
constructorWriter.end();
1091-
}
1092-
1093-
//The actual method
1094-
{
1095-
JavaCompilingMethod compiling = new JavaCompilingMethod(implementationMethod, methodSignature);
1096-
final JavaWriter functionWriter = new JavaWriter(context.logger, position, lambdaCW, compiling, null);
1097-
functionWriter.start();
1098-
1099-
//this.wrapped
1100-
functionWriter.loadObject(0);
1101-
functionWriter.getField(className, "wrapped", wrappedFromSignature);
1102-
1103-
//Load all function parameters
1104-
for (int i = 0, currentLocalPosition = 1; i < methodParameterTypes.length; i++) {
1105-
functionWriter.load(methodParameterTypes[i], currentLocalPosition);
1106-
currentLocalPosition += methodParameterTypes[i].getSize();
1107-
}
1108-
1109-
//Invokes the wrapped interface's method and returns the result
1110-
functionWriter.invokeInterface(wrappedMethod);
1111-
final TypeID returnType = fromType.header.getReturnType();
1112-
final Type rtype = context.getType(returnType);
1113-
if (!CompilerUtils.isPrimitive(returnType)) {
1114-
functionWriter.checkCast(rtype);
1115-
}
1116-
functionWriter.returnType(rtype);
1117-
functionWriter.end();
1118-
}
1119-
1120-
lambdaCW.visitEnd();
1121-
context.register(className, lambdaCW.toByteArray());
1122-
1123-
return new FunctionCastWrapperClass(className, constructorDescriptor);
1124-
}
1125-
1126982
@Override
1127983
public Void visitSupertypeCast(SupertypeCastExpression expression) {
1128984
expression.value.accept(this);
@@ -1261,14 +1117,4 @@ private Void tagVariableAndUpdateLastUsage(VariableID id) {
12611117
public JavaWriter getJavaWriter() {
12621118
return javaWriter;
12631119
}
1264-
1265-
private static class FunctionCastWrapperClass {
1266-
final String className;
1267-
final String constructorDesc;
1268-
1269-
FunctionCastWrapperClass(String className, String constructorDesc) {
1270-
this.className = className;
1271-
this.constructorDesc = constructorDesc;
1272-
}
1273-
}
12741120
}

0 commit comments

Comments
 (0)