Skip to content

Commit

Permalink
Added bridge methods to functional members
Browse files Browse the repository at this point in the history
  • Loading branch information
stanhebben committed Nov 1, 2024
1 parent d84c9a8 commit 9219731
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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() + ";");
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public JavaExpansionMemberVisitor(JavaBytecodeContext context, JavaCompilingClas
javaModule = context.getJavaModule(definition.module);

JavaNativeMethod clinit = new JavaNativeMethod(context.getJavaClass(definition), JavaNativeMethod.Kind.STATICINIT, "<clinit>", 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();
Expand Down
Loading

0 comments on commit 9219731

Please sign in to comment.