Skip to content

Commit 46658d9

Browse files
committed
Move lambda compilation into a separate file
Signed-off-by: TheSilkMiner <thesilkminer@outlook.com>
1 parent 154590a commit 46658d9

9 files changed

Lines changed: 250 additions & 273 deletions

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

Lines changed: 10 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
1212
import org.openzen.zenscript.codemodel.expression.captured.CapturedExpression;
1313
import org.openzen.zenscript.codemodel.expression.captured.CapturedExpressionVisitor;
14-
import org.openzen.zenscript.codemodel.expression.captured.CapturedThisExpression;
1514
import org.openzen.zenscript.codemodel.expression.modifiable.ModifiableExpression;
1615
import org.openzen.zenscript.codemodel.identifiers.MethodID;
1716
import org.openzen.zenscript.codemodel.identifiers.ModuleSymbol;
@@ -23,8 +22,8 @@
2322
import org.openzen.zenscript.javabytecode.JavaLocalVariableInfo;
2423
import org.openzen.zenscript.javabytecode.JavaMangler;
2524
import org.openzen.zenscript.javabytecode.compiler.JavaModificationExpressionVisitor.PushOption;
26-
import org.openzen.zenscript.javabytecode.compiler.capturing.*;
27-
import org.openzen.zenscript.javabytecode.compiler.definitions.JavaMemberVisitor;
25+
import org.openzen.zenscript.javabytecode.compiler.lambda.LambdaIndyCompiler;
26+
import org.openzen.zenscript.javabytecode.compiler.lambda.capturing.JavaInvalidCapturedExpressionVisitor;
2827
import org.openzen.zenscript.javashared.*;
2928
import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod;
3029
import org.openzen.zenscript.javashared.expressions.JavaFunctionInterfaceCastExpression;
@@ -474,135 +473,27 @@ public Void visitFunction(FunctionExpression expression) {
474473
return null;
475474
}*/
476475

477-
final String[] interfaces;
478-
FunctionHeader header = expression.original == null ? expression.header : expression.original;
479-
476+
final String interfaceName;
480477
if (expression.type instanceof JavaFunctionalInterfaceTypeID) {
481478
//Let's implement the functional Interface instead
482479
JavaFunctionalInterfaceTypeID type = (JavaFunctionalInterfaceTypeID) expression.type;
483-
final Method functionalInterfaceMethod = type.functionalInterfaceMethod;
484-
485480
//Should be the same, should it not?
486-
interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
481+
interfaceName = Type.getInternalName(type.functionalInterfaceMethod.getDeclaringClass());
487482
} else {
488483
//Normal way, no casting to functional interface
489-
interfaces = new String[]{context.getInternalName(new FunctionTypeID(header))};
490-
}
491-
492-
final JavaNativeMethod methodInfo;
493-
{
494-
final JavaNativeMethod m = context.getFunctionalInterface(expression.original == null ? expression.type : new FunctionTypeID(expression.original));
495-
methodInfo = m.withModifiers(m.modifiers & ~JavaModifiers.ABSTRACT);
496-
}
497-
498-
final JavaClass thisClass = javaWriter.method.class_;
499-
final String lambdaName = this.javaMangler.mangleLambdaMethod(javaWriter.method.compiled.name, interfaces[0]);
500-
final LambdaClosureInfo closureInfo = LambdaClosureInfo.from(context, expression.closure, thisClass);
501-
final String lambdaDescriptor = calcFunctionDescriptor(closureInfo, expression.header);
502-
final JavaNativeMethod lambdaMethod = JavaNativeMethod.getStatic(thisClass, lambdaName, lambdaDescriptor, Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
503-
final JavaCompilingMethod lambdaMethodCompiling = JavaMemberVisitor.compileBridgeableMethodNoSideEffect(lambdaMethod, lambdaDescriptor); // TODO("Restore signatures")
504-
final JavaWriter lambdaWriter = new JavaWriter(context.logger, expression.position, javaWriter.clazzVisitor, lambdaMethodCompiling, null);
505-
final CapturedExpressionVisitor<Void> lambdaCapturesVisitor = new JavaCapturedExpressionVisitorLocalRedirectionVisitor(lambdaWriter, expression, closureInfo);
506-
final JavaExpressionVisitor lambdaExpressionVisitor = new JavaExpressionVisitor(context, module, lambdaWriter, javaMangler, lambdaCapturesVisitor);
507-
final JavaStatementVisitor lambdaStatementVisitor = new JavaStatementVisitor(context, lambdaExpressionVisitor, javaMangler);
508-
509-
lambdaWriter.start();
510-
expression.body.accept(lambdaStatementVisitor);
511-
lambdaWriter.ret();
512-
lambdaWriter.end();
513-
514-
final JavaLoadThisOnIndyCapturedExpressionVisitor thisVisitor = new JavaLoadThisOnIndyCapturedExpressionVisitor(this);
515-
final JavaLoadCapturesOnIndyCapturedExpressionVisitor othersVisitor = new JavaLoadCapturesOnIndyCapturedExpressionVisitor(this);
516-
517-
boolean hasLoadedThis = false;
518-
for (final CapturedExpression capture : expression.closure.captures) {
519-
// Note: we want this to be |= to ensure NO short-circuiting behavior
520-
hasLoadedThis |= capture.accept(thisVisitor);
484+
FunctionHeader header = expression.original == null ? expression.header : expression.original;
485+
interfaceName = context.getInternalName(new FunctionTypeID(header));
521486
}
522487

523-
// If no this was loaded, then we don't care about its value; just load null
524-
if (!hasLoadedThis) {
525-
javaWriter.aConstNull();
526-
}
488+
final JavaNativeMethod functionalMethod = context.getFunctionalInterface(expression.original == null ? expression.type : new FunctionTypeID(expression.original));
489+
final JavaNativeMethod methodInfo = functionalMethod.withModifiers(functionalMethod.modifiers & ~JavaModifiers.ABSTRACT);
527490

528-
for (final CapturedExpression capture : expression.closure.captures) {
529-
capture.accept(othersVisitor);
530-
}
531-
532-
// TODO("Have this in JavaWriter")
533-
javaWriter.getVisitor().visitInvokeDynamicInsn(
534-
methodInfo.name,
535-
calcIndyDescriptor(closureInfo, interfaces[0]),
536-
new org.objectweb.asm.Handle(
537-
Opcodes.H_INVOKESTATIC,
538-
Type.getInternalName(org.openzen.zenscript.javart.factory.LambdaFactory.class),
539-
"buildLambda",
540-
Type.getMethodDescriptor(
541-
Type.getType(java.lang.invoke.CallSite.class),
542-
Type.getType(java.lang.invoke.MethodHandles.Lookup.class),
543-
Type.getType(String.class),
544-
Type.getType(java.lang.invoke.MethodType.class),
545-
Type.getType(java.lang.invoke.MethodHandle.class),
546-
Type.getType(java.lang.invoke.MethodType.class),
547-
Type.INT_TYPE,
548-
Type.getType(java.lang.invoke.MethodType.class)
549-
),
550-
false
551-
),
552-
new org.objectweb.asm.Handle(
553-
Opcodes.H_INVOKESTATIC,
554-
thisClass.internalName,
555-
lambdaName,
556-
lambdaDescriptor,
557-
false
558-
),
559-
Type.getMethodType(JavaMemberVisitor.compileBridgeableMethodNoSideEffect(methodInfo, context.getMethodDescriptor(expression.header)).compiled.descriptor),
560-
org.openzen.zenscript.javart.factory.LambdaFactory.FLAG_GENERATE_BRIDGE,
561-
Type.getMethodType(methodInfo.descriptor)
562-
);
491+
final LambdaIndyCompiler lambdaCompiler = LambdaIndyCompiler.of(this.javaWriter, this.javaMangler, this.context, this.module, this);
492+
lambdaCompiler.compileFunctionExpressionViaIndy(expression, interfaceName, methodInfo);
563493

564494
return null;
565495
}
566496

567-
private String calcFunctionDescriptor(final LambdaClosureInfo closureInfo, final FunctionHeader header) {
568-
final StringJoiner joiner = new StringJoiner("");
569-
for (final CapturedExpression capture : closureInfo.closure().captures) {
570-
if (!(capture instanceof CapturedThisExpression)) {
571-
final String descriptor = context.getDescriptor(capture.type);
572-
joiner.add(descriptor);
573-
}
574-
}
575-
576-
// TODO("Remove null check: the method should always return non-null")
577-
final String thisType = closureInfo.thisType() == null? "Ljava/lang/Void;" : context.getDescriptor(closureInfo.thisType());
578-
final StringBuilder builder = new StringBuilder(context.getMethodDescriptor(header));
579-
builder.insert(builder.indexOf("(") + 1, thisType);
580-
builder.insert(builder.lastIndexOf(")"), joiner);
581-
return builder.toString();
582-
}
583-
584-
private String calcIndyDescriptor(final LambdaClosureInfo closureInfo, final String targetInterface) {
585-
final StringBuilder builder = new StringBuilder("(");
586-
587-
// TODO("Remove null check as this method should never return null")
588-
if (closureInfo.thisType() == null) {
589-
builder.append("Ljava/lang/Void;");
590-
} else {
591-
builder.append(context.getDescriptor(closureInfo.thisType()));
592-
}
593-
594-
final StringJoiner joiner = new StringJoiner("");
595-
for (final CapturedExpression capture : closureInfo.closure().captures) {
596-
if (!(capture instanceof CapturedThisExpression)) {
597-
final String descriptor = context.getDescriptor(capture.type);
598-
joiner.add(descriptor);
599-
}
600-
}
601-
602-
builder.append(joiner).append(")L").append(targetInterface).append(';');
603-
return builder.toString();
604-
}
605-
606497
@Override
607498
public Void visitGetField(GetFieldExpression expression) {
608499
JavaField field = context.getJavaField(expression.field);

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/capturing/JavaCapturedExpressionVisitorToAccessCapturesInsideTheLambda.java

Lines changed: 0 additions & 102 deletions
This file was deleted.

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/capturing/JavaCapturedExpressionVisitorToPutCapturesOnTheStackBeforeCallingTheCtor.java

Lines changed: 0 additions & 40 deletions
This file was deleted.

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/LambdaClosureInfo.java renamed to JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/lambda/LambdaClosureInfo.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
package org.openzen.zenscript.javabytecode.compiler;
1+
package org.openzen.zenscript.javabytecode.compiler.lambda;
22

33
import org.openzen.zenscript.codemodel.expression.LambdaClosure;
44
import org.openzen.zenscript.codemodel.expression.captured.CapturedExpression;
55
import org.openzen.zenscript.codemodel.expression.captured.CapturedThisExpression;
6-
import org.openzen.zenscript.codemodel.type.BasicTypeID;
7-
import org.openzen.zenscript.codemodel.type.OptionalTypeID;
86
import org.openzen.zenscript.codemodel.type.TypeID;
97
import org.openzen.zenscript.javabytecode.JavaBytecodeContext;
108
import org.openzen.zenscript.javashared.JavaClass;

0 commit comments

Comments
 (0)