Beispiel #1
0
        private static CoercionFlags?GetCoercion(FunctionMethod overload, ImmutableArray <MRepr> inputs)
        {
            var coercionFlags = CoercionFlags.None;

            for (int i = 0; i < inputs.Length; ++i)
            {
                MRepr provided = inputs[i];
                MRepr expected = overload.Signature.Inputs[i];

                if (provided == expected)
                {
                    continue;
                }

                if (expected.IsAny)
                {
                    coercionFlags |= CoercionFlags.ToAny;
                    continue;
                }

                // Check structural class compatibility
                if (provided.StructuralClass != expected.StructuralClass)
                {
                    // TODO: Check the subtyping relation of the structural classes
                    if (expected.StructuralClass == MStructuralClass.Scalar)
                    {
                        return(null);
                    }
                    coercionFlags |= CoercionFlags.StructuralClassChange;
                }

                // Check complex attribute compatibility
                if (provided.IsComplex != expected.IsComplex)
                {
                    if (provided.IsComplex)
                    {
                        return(null);                                        // Complex to real
                    }
                    coercionFlags |= CoercionFlags.RealToComplex;
                }

                // Check class compatibility.
                if (provided.Class != expected.Class)
                {
                    if (provided.Class.IsInteger && expected.Class.IsReal)
                    {
                        coercionFlags |= CoercionFlags.IntegerToFloat;
                    }
                    else
                    {
                        return(null);
                    }
                }
            }

            return(coercionFlags);
        }
Beispiel #2
0
        public FunctionMethod Lookup(string name, ImmutableArray <MRepr> inputs)
        {
            Contract.Requires(name != null);

            var key = new GroupKey(name, inputs.Length);

            FunctionMethod bestOverload = null;

            // Perform overload resolution based on the required input coercions
            List <FunctionMethod> overloads;

            if (functions.TryGetValue(key, out overloads))
            {
                var leastCoercionFlags = CoercionFlags.None;
                foreach (var overload in overloads)
                {
                    var overloadCoercionFlags = GetCoercion(overload, inputs);
                    if (!overloadCoercionFlags.HasValue)
                    {
                        continue;                                                      // Not admissible
                    }
                    if (bestOverload == null || overloadCoercionFlags.Value < leastCoercionFlags)
                    {
                        // TODO: assert we don't have multiple overloads with the same minimal admissibility
                        bestOverload       = overload;
                        leastCoercionFlags = overloadCoercionFlags.Value;
                    }
                }
            }

            // Make sure we have an admissible overload
            if (bestOverload == null)
            {
                var message = new StringBuilder();
                message.Append("No admissible overload for function ")
                .Append(name)
                .Append(" with input types (");
                for (int i = 0; i < inputs.Length; ++i)
                {
                    if (i >= 1)
                    {
                        message.Append(", ");
                    }
                    message.Append(inputs[i].ToString());
                }

                message.Append(')');

                throw new KeyNotFoundException(message.ToString());
            }

            return(bestOverload);
        }
Beispiel #3
0
        public void AddFunction(FunctionMethod function)
        {
            Contract.Requires(function != null);

            var key = new GroupKey(function.Name, function.Signature.Inputs.Count);

            List <FunctionMethod> overloads;

            if (!functions.TryGetValue(key, out overloads))
            {
                overloads = new List <FunctionMethod>();
                functions.Add(key, overloads);
            }

            overloads.Add(function);
        }
Beispiel #4
0
        public void AddMethod(MethodInfo method)
        {
            Contract.Requires(method != null);

            if (method.IsGenericMethodDefinition)
            {
                foreach (var instantiation in InstantiateGenericMethod(method))
                {
                    AddMethod(instantiation);
                }
                return;
            }

            // TODO: Support variadic arguments
            // TODO: Support variadic return parameters
            var function = new FunctionMethod(method);

            AddFunction(function);
        }