Exemplo n.º 1
0
        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;
            }
        }
Exemplo n.º 3
0
        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()));
                }
            }
        }