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); }
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); }
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); }
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); }