static ExpressionList GenerateMethodCallParameters(IEnumerable <TypeAssertionAttribute> typeAssertions,
                                                           PrimitiveAttribute primitiveInformation)
        {
            IEnumerable <Expression> Parameters(ParameterExpression input) => Enumerable
            .Range(0, primitiveInformation.InputCount)
            .Select(x => Property(input, "Item", Constant(x)));

            List <Expression> GenerateCallParameterCasts(ExpressionList parameters)
            => parameters.Select((expression, index) =>
            {
                if (!(typeAssertions.FirstOrDefault(x => x.Index == index) is TypeAssertionAttribute assertion))
                {
                    return(expression);
                }
        static Expression GenerateParameterCountCheck(PrimitiveAttribute primitive
                                                      , IEnumerable <TypeAssertionAttribute> typeAssertions)
        {
            var        expectedCount      = Constant(primitive.InputCount);
            var        optionalParameters = typeAssertions.Count(x => x.Optional);
            Expression countPredicate     = null;
            var        difference         = "";

            if (optionalParameters == 0)
            {
                if (primitive.InputCount != 0)
                {
                    countPredicate = LessThan(ArgumentCount, expectedCount);
                    difference     = "Not enough";
                }
                if (!primitive.Variadic)
                {
                    var compareInputWithExpected = NotEqual(ArgumentCount, expectedCount);
                    if (countPredicate == null)
                    {
                        difference     = "Too many";
                        countPredicate = compareInputWithExpected;
                    }
                    else
                    {
                        difference    += " or too many";
                        countPredicate = Or(countPredicate, compareInputWithExpected);
                    }
                }
            }
            else
            {
                difference     = "Not enough or too many";
                countPredicate = Or(GreaterThan(ArgumentCount, expectedCount)
                                    , LessThan(ArgumentCount, Constant(primitive.InputCount - optionalParameters)));
            }

            return(countPredicate == null
                ? Empty()
                : (Expression)Block(
#if DebugCallMethods
                       Call(null, typeof(Console).GetMethod("Write", new[] { typeof(string) }), Constant($"The function {primitive.PrimitiveName} has input count {primitive.InputCount} and receives ")),
                       Call(null, typeof(Console).GetMethod("WriteLine", new[] { typeof(int) }), realCount),
                       Call(null, typeof(Console).GetMethod("Write", new[] { typeof(string) }), Constant("With Input ")),
                       Call(null, typeof(Console).GetMethod("WriteLine", new[] { typeof(object) }), Input),
#endif
                       ThrowIF(countPredicate, $"{difference} arguments for combiner '{primitive.PrimitiveName}'")));
        }