11package org .openzen .zenscript .javabytecode .compiler ;
22
3- import org .objectweb .asm .ClassWriter ;
43import org .objectweb .asm .Label ;
5- import org .objectweb .asm .Opcodes ;
64import org .objectweb .asm .Type ;
7- import org .openzen .zencode .shared .CodePosition ;
85import org .openzen .zenscript .codemodel .CompareType ;
96import org .openzen .zenscript .codemodel .FunctionHeader ;
107import org .openzen .zenscript .codemodel .OperatorType ;
2522import org .openzen .zenscript .javabytecode .compiler .lambda .LambdaIndyCompiler ;
2623import org .openzen .zenscript .javabytecode .compiler .lambda .capturing .JavaInvalidCapturedExpressionVisitor ;
2724import org .openzen .zenscript .javashared .*;
28- import org .openzen .zenscript .javashared .compiling .JavaCompilingMethod ;
2925import org .openzen .zenscript .javashared .expressions .JavaFunctionInterfaceCastExpression ;
3026import org .openzen .zenscript .javashared .types .JavaFunctionalInterfaceTypeID ;
3127
32- import java .lang .reflect .Method ;
33- import java .lang .reflect .Modifier ;
3428import java .util .*;
3529
3630import 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