private static string ComputeArray(Expression array, ArrayPostfixMode arrayPostfixMode, RequestBuilderConfiguration configuration)
        {
            var list = string.Join(
                ",",
                (array as NewArrayExpression).Expressions.Select(e => Run(e as ConstantExpression, configuration))
                );

            return(arrayPostfixMode switch
            {
                ArrayPostfixMode.ContainsAny => $"({list})",
                ArrayPostfixMode.ContainsAll => $"[{list}]",
                ArrayPostfixMode.ExactMatch => $"{{{list}}}",
                _ => throw new Exception("Unknown array postfix mode"),
            });
        /// <summary>
        /// Interpretes a predicate to convert it to a string usable by IGDB API
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static string Run(Expression predicate, RequestBuilderConfiguration configuration, bool invert = false, ArrayPostfixMode arrayPostfixMode = ArrayPostfixMode.ContainsAny)
        {
            if (predicate is null)
            {
                throw new ArgumentNullException(nameof(predicate));
            }

            var binaryPredicate = predicate as BinaryExpression;

            switch (predicate.NodeType)
            {
            /*
             * First part of switch : binary operators
             * -------
             * if Node type referes to a binary operators we set the operator
             * and let the method continue after the switch to create the
             * expression.
             * binary operators are either logical operators (&& or ||),
             * relational operators (>, >=, <, <=) or equality operators (==, !=)
             */
            case ExpressionType.AndAlso:
                return(ComputeBinaryOperator(binaryPredicate.Left, binaryPredicate.Right, "&", configuration));

            case ExpressionType.OrElse:
                return(ComputeBinaryOperator(binaryPredicate.Left, binaryPredicate.Right, "|", configuration));

            case ExpressionType.GreaterThan:
                return(ComputeBinaryOperator(binaryPredicate.Left, binaryPredicate.Right, ">", configuration));

            case ExpressionType.GreaterThanOrEqual:
                return(ComputeBinaryOperator(binaryPredicate.Left, binaryPredicate.Right, ">=", configuration));

            case ExpressionType.LessThan:
                return(ComputeBinaryOperator(binaryPredicate.Left, binaryPredicate.Right, "<", configuration));

            case ExpressionType.LessThanOrEqual:
                return(ComputeBinaryOperator(binaryPredicate.Left, binaryPredicate.Right, "<=", configuration));

            case ExpressionType.NotEqual:
                return(ComputeBinaryOperator(binaryPredicate.Left, binaryPredicate.Right, "!=", configuration));

            case ExpressionType.Equal:
                return(ComputeBinaryOperator(binaryPredicate.Left, binaryPredicate.Right, "=", configuration));

            /*
             * Second part of switch : members
             * -------
             * If node type refers to a member, a constant or an array then
             * then return an interpretation.
             */
            case ExpressionType.MemberAccess:
                return(ComputeMemberAccess(predicate, configuration));

            case ExpressionType.Constant:
                return(ComputeConstant(predicate, configuration));

            case ExpressionType.NewArrayInit:
                return(ComputeArray(predicate, arrayPostfixMode, configuration));

            /*
             * Third part of switch : methods
             * -------
             * if node type referes to a method corresponding to
             */
            case ExpressionType.Not:
                return(ComputeNotCall(predicate, configuration));

            case ExpressionType.Call:
                return(ComputeMethodCall(predicate, configuration, invert));

            default:
                throw new InvalidPredicateException(predicate);
            }
        }