internal virtual LambdaForm CollectArgumentsForm(int pos, MethodType collectorType) { int collectorArity = collectorType.ParameterCount(); bool dropResult = (collectorType.ReturnType() == typeof(void)); if (collectorArity == 1 && !dropResult) { return(FilterArgumentForm(pos, basicType(collectorType.ParameterType(0)))); } BasicType[] newTypes = BasicType.basicTypes(collectorType.ParameterList()); Transform.Kind kind = (dropResult ? Transform.Kind.COLLECT_ARGS_TO_VOID : Transform.Kind.COLLECT_ARGS); if (dropResult && collectorArity == 0) // pure side effect { pos = 1; } Transform key = Transform.Of(kind, pos, collectorArity, BasicType.basicTypesOrd(newTypes)); LambdaForm form = GetInCache(key); if (form != null) { assert(form.Arity_Renamed == LambdaForm.Arity_Renamed - (dropResult ? 0 : 1) + collectorArity); return(form); } form = MakeArgumentCombinationForm(pos, collectorType, false, dropResult); return(PutInCache(key, form)); }
private readonly String LambdaClassName; // Generated name for the generated class "X$$Lambda$1" /// <summary> /// General meta-factory constructor, supporting both standard cases and /// allowing for uncommon options such as serialization or bridging. /// </summary> /// <param name="caller"> Stacked automatically by VM; represents a lookup context /// with the accessibility privileges of the caller. </param> /// <param name="invokedType"> Stacked automatically by VM; the signature of the /// invoked method, which includes the expected static /// type of the returned lambda object, and the static /// types of the captured arguments for the lambda. In /// the event that the implementation method is an /// instance method, the first argument in the invocation /// signature will correspond to the receiver. </param> /// <param name="samMethodName"> Name of the method in the functional interface to /// which the lambda or method reference is being /// converted, represented as a String. </param> /// <param name="samMethodType"> Type of the method in the functional interface to /// which the lambda or method reference is being /// converted, represented as a MethodType. </param> /// <param name="implMethod"> The implementation method which should be called (with /// suitable adaptation of argument types, return types, /// and adjustment for captured arguments) when methods of /// the resulting functional interface instance are invoked. </param> /// <param name="instantiatedMethodType"> The signature of the primary functional /// interface method after type variables are /// substituted with their instantiation from /// the capture site </param> /// <param name="isSerializable"> Should the lambda be made serializable? If set, /// either the target type or one of the additional SAM /// types must extend {@code Serializable}. </param> /// <param name="markerInterfaces"> Additional interfaces which the lambda object /// should implement. </param> /// <param name="additionalBridges"> Method types for additional signatures to be /// bridged to the implementation method </param> /// <exception cref="LambdaConversionException"> If any of the meta-factory protocol /// invariants are violated </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, MethodType invokedType, String samMethodName, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType, boolean isSerializable, Class[] markerInterfaces, MethodType[] additionalBridges) throws LambdaConversionException public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, MethodType invokedType, String samMethodName, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType, bool isSerializable, Class[] markerInterfaces, MethodType[] additionalBridges) : base(caller, invokedType, samMethodName, samMethodType, implMethod, instantiatedMethodType, isSerializable, markerInterfaces, additionalBridges) { ImplMethodClassName = ImplDefiningClass.Name.Replace('.', '/'); ImplMethodName = ImplInfo.Name; ImplMethodDesc = ImplMethodType.ToMethodDescriptorString(); ImplMethodReturnClass = (ImplKind == MethodHandleInfo.REF_newInvokeSpecial) ? ImplDefiningClass : ImplMethodType.ReturnType(); ConstructorType = invokedType.ChangeReturnType(Void.TYPE); LambdaClassName = TargetClass.Name.Replace('.', '/') + "$$Lambda$" + Counter.IncrementAndGet(); Cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); int parameterCount = invokedType.ParameterCount(); if (parameterCount > 0) { ArgNames = new String[parameterCount]; ArgDescs = new String[parameterCount]; for (int i = 0; i < parameterCount; i++) { ArgNames[i] = "arg$" + (i + 1); ArgDescs[i] = BytecodeDescriptor.unparse(invokedType.ParameterType(i)); } } else { ArgNames = ArgDescs = EMPTY_STRING_ARRAY; } }
private static MethodHandle BindCaller(MethodHandle target, Class hostClass) { MethodHandle cbmh = MethodHandleImpl.BindCaller(target, hostClass); if (target.VarargsCollector) { MethodType type = cbmh.Type(); int arity = type.ParameterCount(); return(cbmh.AsVarargsCollector(type.ParameterType(arity - 1))); } return(cbmh); }
/// <summary> /// Check the meta-factory arguments for errors </summary> /// <exception cref="LambdaConversionException"> if there are improper conversions </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: void validateMetafactoryArgs() throws LambdaConversionException internal virtual void ValidateMetafactoryArgs() { switch (ImplKind) { case MethodHandleInfo.REF_invokeInterface: case MethodHandleInfo.REF_invokeVirtual: case MethodHandleInfo.REF_invokeStatic: case MethodHandleInfo.REF_newInvokeSpecial: case MethodHandleInfo.REF_invokeSpecial: break; default: throw new LambdaConversionException(string.Format("Unsupported MethodHandle kind: {0}", ImplInfo)); } // Check arity: optional-receiver + captured + SAM == impl //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int implArity = implMethodType.parameterCount(); int implArity = ImplMethodType.ParameterCount(); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int receiverArity = implIsInstanceMethod ? 1 : 0; int receiverArity = ImplIsInstanceMethod ? 1 : 0; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int capturedArity = invokedType.parameterCount(); int capturedArity = InvokedType.ParameterCount(); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int samArity = samMethodType.parameterCount(); int samArity = SamMethodType.ParameterCount(); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int instantiatedArity = instantiatedMethodType.parameterCount(); int instantiatedArity = InstantiatedMethodType.ParameterCount(); if (implArity + receiverArity != capturedArity + samArity) { throw new LambdaConversionException(string.Format("Incorrect number of parameters for {0} method {1}; {2:D} captured parameters, {3:D} functional interface method parameters, {4:D} implementation parameters", ImplIsInstanceMethod ? "instance" : "static", ImplInfo, capturedArity, samArity, implArity)); } if (instantiatedArity != samArity) { throw new LambdaConversionException(string.Format("Incorrect number of parameters for {0} method {1}; {2:D} instantiated parameters, {3:D} functional interface method parameters", ImplIsInstanceMethod ? "instance" : "static", ImplInfo, instantiatedArity, samArity)); } foreach (MethodType bridgeMT in AdditionalBridges) { if (bridgeMT.ParameterCount() != samArity) { throw new LambdaConversionException(string.Format("Incorrect number of parameters for bridge signature {0}; incompatible with {1}", bridgeMT, SamMethodType)); } } // If instance: first captured arg (receiver) must be subtype of class where impl method is defined //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int capturedStart; int capturedStart; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int samStart; int samStart; if (ImplIsInstanceMethod) { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final Class receiverClass; Class receiverClass; // implementation is an instance method, adjust for receiver in captured variables / SAM arguments if (capturedArity == 0) { // receiver is function parameter capturedStart = 0; samStart = 1; receiverClass = InstantiatedMethodType.ParameterType(0); } else { // receiver is a captured variable capturedStart = 1; samStart = 0; receiverClass = InvokedType.ParameterType(0); } // check receiver type if (!receiverClass.IsSubclassOf(ImplDefiningClass)) { throw new LambdaConversionException(string.Format("Invalid receiver type {0}; not a subtype of implementation type {1}", receiverClass, ImplDefiningClass)); } Class implReceiverClass = ImplMethod.Type().ParameterType(0); if (implReceiverClass != ImplDefiningClass && !receiverClass.IsSubclassOf(implReceiverClass)) { throw new LambdaConversionException(string.Format("Invalid receiver type {0}; not a subtype of implementation receiver type {1}", receiverClass, implReceiverClass)); } } else { // no receiver capturedStart = 0; samStart = 0; } // Check for exact match on non-receiver captured arguments //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int implFromCaptured = capturedArity - capturedStart; int implFromCaptured = capturedArity - capturedStart; for (int i = 0; i < implFromCaptured; i++) { Class implParamType = ImplMethodType.ParameterType(i); Class capturedParamType = InvokedType.ParameterType(i + capturedStart); if (!capturedParamType.Equals(implParamType)) { throw new LambdaConversionException(string.Format("Type mismatch in captured lambda parameter {0:D}: expecting {1}, found {2}", i, capturedParamType, implParamType)); } } // Check for adaptation match on SAM arguments //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int samOffset = samStart - implFromCaptured; int samOffset = samStart - implFromCaptured; for (int i = implFromCaptured; i < implArity; i++) { Class implParamType = ImplMethodType.ParameterType(i); Class instantiatedParamType = InstantiatedMethodType.ParameterType(i + samOffset); if (!IsAdaptableTo(instantiatedParamType, implParamType, true)) { throw new LambdaConversionException(string.Format("Type mismatch for lambda argument {0:D}: {1} is not convertible to {2}", i, instantiatedParamType, implParamType)); } } // Adaptation match: return type Class expectedType = InstantiatedMethodType.ReturnType(); Class actualReturnType = (ImplKind == MethodHandleInfo.REF_newInvokeSpecial) ? ImplDefiningClass : ImplMethodType.ReturnType(); Class samReturnType = SamMethodType.ReturnType(); if (!IsAdaptableToAsReturn(actualReturnType, expectedType)) { throw new LambdaConversionException(string.Format("Type mismatch for lambda return: {0} is not convertible to {1}", actualReturnType, expectedType)); } if (!IsAdaptableToAsReturnStrict(expectedType, samReturnType)) { throw new LambdaConversionException(string.Format("Type mismatch for lambda expected return: {0} is not convertible to {1}", expectedType, samReturnType)); } foreach (MethodType bridgeMT in AdditionalBridges) { if (!IsAdaptableToAsReturnStrict(expectedType, bridgeMT.ReturnType())) { throw new LambdaConversionException(string.Format("Type mismatch for lambda expected return: {0} is not convertible to {1}", expectedType, bridgeMT.ReturnType())); } } }