Ejemplo n.º 1
0
        /// <summary>
        /// Проверяет, подходит ли фаункция для вызова с указанными параметрами
        /// </summary>
        /// <param name="candidate"></param>
        /// <param name="givenParameterTypes">Типы параметров, указанные пользователем</param>
        /// <returns></returns>
        private bool IsSuitableFunction(
            function_node candidate,
            type_node[] givenParameterTypes,
            expression_node patternInstance,
            location deconstructionLocation,
            out type_node[] parameterTypes)
        {
            parameterTypes = new type_node[givenParameterTypes.Length];
            var selfParameter = candidate.is_extension_method ? candidate.parameters.First(IsSelfParameter) : null;

            Debug.Assert(!candidate.is_extension_method || selfParameter != null, "Couldn't find self parameter in extension method");
            var candidateParameterTypes =
                candidate.is_extension_method ?
                candidate.parameters.Where(x => !IsSelfParameter(x)).ToArray() :
                candidate.parameters.ToArray();

            if (candidateParameterTypes.Length != givenParameterTypes.Length)
            {
                return(false);
            }

            // Разрешаем только deconstruct текущего класса, родительские в расчет не берем
            if (candidate is common_method_node commonMethod && !AreTheSameType(patternInstance.type, commonMethod.cont_type))
            {
                return(false);
            }

            var genericDeduceNeeded = candidate.is_extension_method && candidate.is_generic_function;

            type_node[] deducedGenerics = new type_node[candidate.generic_parameters_count];
            if (genericDeduceNeeded)
            {
                // Выводим дженерики по self
                var nils           = new List <int>();
                var deduceSucceded = generic_convertions.DeduceInstanceTypes(selfParameter.type, patternInstance.type, deducedGenerics, nils);
                if (!deduceSucceded || deducedGenerics.Contains(null))
                {
                    return(false);
                }
            }

            for (int i = 0; i < givenParameterTypes.Length; i++)
            {
                var givenParameter     = givenParameterTypes[i];
                var candidateParameter = candidateParameterTypes[i].type;
                if (genericDeduceNeeded && (candidateParameter.is_generic_parameter || candidateParameter.is_generic_type_instance))
                {
                    candidateParameter = InstantiateParameter(candidateParameter, deducedGenerics);
                }

                if (givenParameter != null && !AreTheSameType(candidateParameter, givenParameter))
                {
                    return(false);
                }

                parameterTypes[i] = candidateParameter;
            }

            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Проверяет, подходит ли фаункция для вызова с указанными параметрами
        /// </summary>
        /// <param name="candidate"></param>
        /// <param name="givenParameterTypes">Типы параметров, указанные пользователем</param>
        /// <returns></returns>
        private bool IsSuitableFunction(
            function_node candidate,
            type_node[] givenParameterTypes,
            expression_node patternInstance,
            location deconstructionLocation,
            out type_node[] parameterTypes)
        {
            parameterTypes = new type_node[givenParameterTypes.Length];
            var selfParameter = candidate.is_extension_method ? candidate.parameters.First(IsSelfParameter) : null;

            Debug.Assert(!candidate.is_extension_method || selfParameter != null, "Couldn't find self parameter in extension method");
            var candidateParameterTypes =
                candidate.is_extension_method ?
                candidate.parameters.Where(x => !IsSelfParameter(x)).ToArray() :
                candidate.parameters.ToArray();

            if (candidateParameterTypes.Length != givenParameterTypes.Length)
            {
                return(false);
            }

            var genericDeduceNeeded = candidate.is_extension_method && candidate.is_generic_function;

            type_node[] deducedGenerics = new type_node[candidate.generic_parameters_count];
            if (genericDeduceNeeded)
            {
                // Выводим дженерики по self
                var nils           = new List <int>();
                var deduceSucceded = generic_convertions.DeduceInstanceTypes(selfParameter.type, patternInstance.type, deducedGenerics, nils);
                if (!deduceSucceded || deducedGenerics.Contains(null))
                {
                    // Проверка на то, что в Deconstruct все дженерики выводятся по self делается в другом месте
                    // TODO Patterns: сделать проверку из коммента выше
                    // TODO Patterns: запретить дженерик методы в классах. Можно использовать только дженерик-типы самого класса в качестве параметров
                    //AddError(deconstructionLocation, "COULDNT_DEDUCE_DECONSTRUCT_GENERIC_TYPE");
                    return(false);
                }
            }

            for (int i = 0; i < givenParameterTypes.Length; i++)
            {
                var givenParameter     = givenParameterTypes[i];
                var candidateParameter = candidateParameterTypes[i].type;
                if (genericDeduceNeeded && (candidateParameter.is_generic_parameter || candidateParameter.is_generic_type_instance))
                {
                    candidateParameter = InstantiateParameter(candidateParameter, deducedGenerics);
                }

                if (givenParameter != null && !AreTheSameType(candidateParameter, givenParameter))
                {
                    return(false);
                }

                parameterTypes[i] = candidateParameter;
            }

            return(true);
        }