|
11 | 11 | import org.openzen.zenscript.codemodel.definition.ExpansionDefinition; |
12 | 12 | import org.openzen.zenscript.codemodel.expression.captured.CapturedExpression; |
13 | 13 | import org.openzen.zenscript.codemodel.expression.captured.CapturedExpressionVisitor; |
14 | | -import org.openzen.zenscript.codemodel.expression.captured.CapturedThisExpression; |
15 | 14 | import org.openzen.zenscript.codemodel.expression.modifiable.ModifiableExpression; |
16 | 15 | import org.openzen.zenscript.codemodel.identifiers.MethodID; |
17 | 16 | import org.openzen.zenscript.codemodel.identifiers.ModuleSymbol; |
|
23 | 22 | import org.openzen.zenscript.javabytecode.JavaLocalVariableInfo; |
24 | 23 | import org.openzen.zenscript.javabytecode.JavaMangler; |
25 | 24 | 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; |
28 | 27 | import org.openzen.zenscript.javashared.*; |
29 | 28 | import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod; |
30 | 29 | import org.openzen.zenscript.javashared.expressions.JavaFunctionInterfaceCastExpression; |
@@ -474,135 +473,27 @@ public Void visitFunction(FunctionExpression expression) { |
474 | 473 | return null; |
475 | 474 | }*/ |
476 | 475 |
|
477 | | - final String[] interfaces; |
478 | | - FunctionHeader header = expression.original == null ? expression.header : expression.original; |
479 | | - |
| 476 | + final String interfaceName; |
480 | 477 | if (expression.type instanceof JavaFunctionalInterfaceTypeID) { |
481 | 478 | //Let's implement the functional Interface instead |
482 | 479 | JavaFunctionalInterfaceTypeID type = (JavaFunctionalInterfaceTypeID) expression.type; |
483 | | - final Method functionalInterfaceMethod = type.functionalInterfaceMethod; |
484 | | - |
485 | 480 | //Should be the same, should it not? |
486 | | - interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())}; |
| 481 | + interfaceName = Type.getInternalName(type.functionalInterfaceMethod.getDeclaringClass()); |
487 | 482 | } else { |
488 | 483 | //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)); |
521 | 486 | } |
522 | 487 |
|
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); |
527 | 490 |
|
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); |
563 | 493 |
|
564 | 494 | return null; |
565 | 495 | } |
566 | 496 |
|
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 | | - |
606 | 497 | @Override |
607 | 498 | public Void visitGetField(GetFieldExpression expression) { |
608 | 499 | JavaField field = context.getJavaField(expression.field); |
|
0 commit comments