private Expression DispatchByTypeSystem(SymbolTable symbols, Type expectedType)
{
return ImplicitConvert(this.GetMembers(symbols)
.Select(CreateCandidate)
.Choose(c => c.ParameterMap != null
? c.ParameterMap
.Select(_ => _.Item2.Reduce(symbols, _.Item1))
.ToArray()
.If(
es => es.All(a => a != null),
es => c.Clone(argumentNames: new String[c.Parameters.Count], arguments: es),
es => null
)
: null
)
.Where(c => c.ParameterMap.Select(_ => _.Item1.GetDelegateSignature().Null(m => m.GetParameters().Length))
.SequenceEqual(c.ParameterMap.Select(_ => Math.Max(
(_.Item2 as LambdaExpression).Null(e => e.Parameters.Count),
(_.Item2 as AmbiguousLambdaExpression).Null(e => e.Parameters.Count)
)))
)
.Choose(c => InferTypeArguments(c, c.TypeArgumentMap, symbols))
.Where(c => !c.Arguments.Any(e => e == null || e is YacqExpression))
.Choose(c => c.TypeArgumentMap.All(p => p.Key.IsAppropriate(p.Value))
? c.Clone(arguments: (c.IsParamArrayContext
? c.Arguments
.Take(c.Parameters.Count - 1)
.EndWith(Vector(symbols, c.Arguments.Skip(c.Parameters.Count - 1))
.Reduce(symbols, c.Parameters.Last().ParameterType)
)
: c.ParameterMap.Select(_ => _.Item2)
).ToArray())
: null
)
.OrderBy(c => c)
.ThenBy(c => c.Arguments.Sum(e => e.GetParameterCount()))
.ThenBy(c => c.Arguments.Sum(a => EnumerableEx.Generate(
a,
_ => _ is UnaryExpression && _.NodeType == ExpressionType.Convert,
_ => ((UnaryExpression) _).Operand,
_ => _
).Count()))
.FirstOrDefault()
.Null(c => this.GetResultExpression(symbols, c))
?? this.DispatchFailback(symbols),
expectedType
);
}