public static AstFilter Not(AstFilter filter)
        {
            if (filter is AstFieldOperationFilter fieldOperationFilter)
            {
                if (fieldOperationFilter.Operation is AstNotFilterOperation notFilterOperation)
                {
                    return(new AstFieldOperationFilter(fieldOperationFilter.Field, notFilterOperation.Operation));
                }

                if (fieldOperationFilter.Operation is AstComparisonFilterOperation comparisonFilterOperation)
                {
                    var comparisonOperator = comparisonFilterOperation.Operator;
                    if (comparisonOperator == AstComparisonFilterOperator.Eq || comparisonOperator == AstComparisonFilterOperator.Ne)
                    {
                        var oppositeComparisonOperator = comparisonOperator == AstComparisonFilterOperator.Eq ? AstComparisonFilterOperator.Ne : AstComparisonFilterOperator.Eq;
                        return(new AstFieldOperationFilter(fieldOperationFilter.Field, new AstComparisonFilterOperation(oppositeComparisonOperator, comparisonFilterOperation.Value)));
                    }
                }

                if (fieldOperationFilter.Operation is AstInFilterOperation inFilterOperation)
                {
                    return(new AstFieldOperationFilter(fieldOperationFilter.Field, new AstNinFilterOperation(inFilterOperation.Values)));
                }

                if (fieldOperationFilter.Operation is AstNinFilterOperation ninFilterOperation)
                {
                    return(new AstFieldOperationFilter(fieldOperationFilter.Field, new AstInFilterOperation(ninFilterOperation.Values)));
                }

                return(new AstFieldOperationFilter(fieldOperationFilter.Field, new AstNotFilterOperation(fieldOperationFilter.Operation)));
            }

            if (filter is AstNorFilter norFilter && norFilter.Filters.Count == 1)
            {
                return(norFilter.Filters[0]);
            }

            if (filter.NodeType == AstNodeType.MatchesEverythingFilter)
            {
                return(AstFilter.MatchesNothing());
            }

            if (filter.NodeType == AstNodeType.MatchesNothingFilter)
            {
                return(AstFilter.MatchesEverything());
            }

            return(new AstNorFilter(new[] { filter }));
        }