import { RType } from '../r-bridge/lang-4.x/ast/model/type';
import type { VertexType } from '../dataflow/graph/vertex';
import type { ParentInformation } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
import type { FlowrSearchElement } from './flowr-search';
import type { Enrichment } from './search-executor/search-enrichers';
import type { DataflowInformation } from '../dataflow/info';
import type { BuiltInProcName } from '../dataflow/environments/built-in-proc-name';
import type { RoleInParent } from '../r-bridge/lang-4.x/ast/model/processing/role';
import type { CallProps } from '../dataflow/environments/built-in-props';
export type FlowrFilterName = keyof typeof FlowrFilters;
interface FlowrFilterWithArgs<Filter extends FlowrFilterName, Args extends FlowrFilterArgs<Filter>> {
    name: Filter;
    args: Args;
}
export declare enum FlowrFilter {
    /**
     * Drops search elements that represent empty arguments. Specifically, all nodes that are arguments and have an undefined name are skipped.
     * This filter does not accept any arguments.
     */
    DropEmptyArguments = "drop-empty-arguments",
    /**
     * Only returns search elements whose enrichments' JSON representations match a given test regular expression.
     * This filter accepts {@link MatchesEnrichmentArgs}, which includes the enrichment to match for, as well as the regular expression to test the enrichment's (non-pretty-printed) JSON representation for.
     * To test for included function names in an enrichment like {@link Enrichment.CallTargets}, the helper function {@link matchIdentifiers} can be used.
     */
    MatchesEnrichment = "matches-enrichment",
    /**
     * Only returns search elements whose {@link FunctionOriginInformation} match a given pattern or value.
     * This filter accepts {@link OriginKindArgs}, which includes the {@link DataflowGraphVertexFunctionCall.origin} to match for, whether to match for every or some origins, and whether to include non-function-calls in the filtered query.
     */
    OriginKind = "origin-kind",
    /**
     * Only returns search element whose {@link RoleInParent} matches a given {@link RoleInParent}.
     * This filter accepts an object containing a `roleInParent` argument of type {@link RoleInParent}.
     */
    RoleInParent = "role-in-parent",
    /**
     * Only returns search elements whose file path matches the given regular expression.
     * This filter accepts {@link FilePathFilterArgs}, which includes the file path regex to test against.
     */
    FilePathFilter = "file-path-filter",
    /**
     * Only returns function calls whose {@link CallProp} bits match the given mask, so that _every call that asks
     * the user_ or _every call that closes a device_ can be searched for without naming a single function.
     * This filter accepts {@link CallPropsArgs}.
     */
    CallProps = "call-props"
}
export type FlowrFilterFunction<T> = (e: FlowrSearchElement<ParentInformation>, args: T, data: {
    dataflow: DataflowInformation;
}) => boolean;
export declare const ValidFlowrFilters: Set<string>;
export declare const ValidFlowrFiltersReverse: {
    [k: string]: string;
};
export declare const FlowrFilters: {
    readonly "drop-empty-arguments": (e: FlowrSearchElement<ParentInformation>, _args: never) => boolean;
    readonly "matches-enrichment": (e: FlowrSearchElement<ParentInformation>, args: MatchesEnrichmentArgs<Enrichment>) => never;
    readonly "origin-kind": (e: FlowrSearchElement<ParentInformation>, args: OriginKindArgs, data: {
        dataflow: DataflowInformation;
    }) => boolean;
    readonly "role-in-parent": (e: FlowrSearchElement<ParentInformation>, { roleInParent }: {
        roleInParent: RoleInParent;
    }) => boolean;
    readonly "file-path-filter": (e: FlowrSearchElement<ParentInformation>, args: FilePathFilterArgs) => boolean;
    readonly "call-props": (e: FlowrSearchElement<ParentInformation>, args: CallPropsArgs, data: {
        dataflow: DataflowInformation;
    }) => boolean;
};
export type FlowrFilterArgs<F extends FlowrFilter> = typeof FlowrFilters[F] extends FlowrFilterFunction<infer Args> ? Args : never;
export interface MatchesEnrichmentArgs<E extends Enrichment> {
    enrichment: E;
    /**
     * The object to test the enrichment value against, which should be a partial {@link EnrichmentElementContent} with each value to test for replaced by a {@link RegExp} or value to match against. The test will pass if the partial structure matches and the enrichment value at each {@link RegExp}, string or primitive location matches the corresponding regular expression. For array entries, {@link arrayMatch} determines whether every element in the array has to match the given expected value, or only some.
     */
    test: Record<string, unknown>;
    /**
     * For array entries, the expected value in {@link test} is compared against each array entry in the real value. This property determines whether every element in the array has to match, or only some. If unset, this defaults to `some`.
     */
    arrayMatch?: 'some' | 'every';
}
export interface OriginKindArgs {
    origin: BuiltInProcName | RegExp;
    matchType?: 'some' | 'every';
    keepNonFunctionCalls?: boolean;
}
export interface FilePathFilterArgs {
    filePathRegex: string | RegExp;
}
export interface CallPropsArgs {
    /** the {@link CallProp} bits to look for, e.g. `CallProp.User | CallProp.Closes` */
    props: CallProps;
    /** whether a call has to carry every bit of {@link props} or just one of them (the default) */
    matchType?: 'some' | 'every';
}
type ValidFilterTypes<F extends FlowrFilter = FlowrFilter> = FlowrFilterName | FlowrFilterWithArgs<F, FlowrFilterArgs<F>> | RType | VertexType;
/**
 * By default, we provide filter for every {@link RType} and {@link VertexType}.
 */
export type FlowrFilterExpression<F extends FlowrFilter = FlowrFilter> = FlowrFilterCombinator | ValidFilterTypes<F>;
interface BooleanBinaryNode<Composite> {
    readonly type: 'and' | 'or' | 'xor';
    readonly left: Composite;
    readonly right: Composite;
}
interface BooleanUnaryNode<Composite> {
    readonly type: 'not';
    readonly operand: Composite;
}
type LeafRType = {
    readonly type: 'r-type';
    readonly value: RType;
};
type LeafVertexType = {
    readonly type: 'vertex-type';
    readonly value: VertexType;
};
type LeafSpecial<F extends FlowrFilter = FlowrFilter> = {
    readonly type: 'special';
    readonly value: FlowrFilterName | FlowrFilterWithArgs<F, FlowrFilterArgs<F>>;
};
type Leaf = LeafRType | LeafVertexType | LeafSpecial;
type BooleanNode = BooleanBinaryNode<BooleanNode> | BooleanUnaryNode<BooleanNode> | Leaf;
type BooleanNodeOrCombinator = BooleanNode | FlowrFilterCombinator;
/**
 * @see {@link FlowrFilterCombinator.is}
 * @see {@link evalFilter}
 * @see {@link binaryTreeToString}
 */
export declare class FlowrFilterCombinator {
    private tree;
    protected constructor(init: BooleanNodeOrCombinator);
    static is<F extends FlowrFilter = FlowrFilter>(value: BooleanNodeOrCombinator | ValidFilterTypes<F>): FlowrFilterCombinator;
    static and<FLeft extends FlowrFilter = FlowrFilter, FRight extends FlowrFilter = FlowrFilter>(left: BooleanNodeOrCombinator | ValidFilterTypes<FLeft>, right: BooleanNodeOrCombinator | ValidFilterTypes<FRight>): FlowrFilterCombinator;
    static or<FLeft extends FlowrFilter = FlowrFilter, FRight extends FlowrFilter = FlowrFilter>(left: BooleanNodeOrCombinator | ValidFilterTypes<FLeft>, right: BooleanNodeOrCombinator | ValidFilterTypes<FRight>): FlowrFilterCombinator;
    static xor<FLeft extends FlowrFilter = FlowrFilter, FRight extends FlowrFilter = FlowrFilter>(left: BooleanNodeOrCombinator | ValidFilterTypes<FLeft>, right: BooleanNodeOrCombinator | ValidFilterTypes<FRight>): FlowrFilterCombinator;
    static not<F extends FlowrFilter = FlowrFilter>(value: BooleanNodeOrCombinator | ValidFilterTypes<F>): FlowrFilterCombinator;
    and<F extends FlowrFilter = FlowrFilter>(right: BooleanNodeOrCombinator | ValidFilterTypes<F>): this;
    or<F extends FlowrFilter = FlowrFilter>(right: BooleanNodeOrCombinator | ValidFilterTypes<F>): this;
    xor<F extends FlowrFilter = FlowrFilter>(right: BooleanNodeOrCombinator | ValidFilterTypes<F>): this;
    private binaryRight;
    not(): this;
    private unary;
    private unpack;
    get(): BooleanNode;
}
export declare const F: typeof FlowrFilterCombinator;
/**
 * Converts the given binary tree to a string representation.
 */
export declare function binaryTreeToString(tree: BooleanNode): string;
/**
 * Checks whether the given value is a binary tree combinator.
 * @see {@link FlowrFilterCombinator}
 */
export declare function isBinaryTree(tree: unknown): tree is {
    tree: BooleanNode;
};
interface FilterData {
    readonly element: FlowrSearchElement<ParentInformation>;
    readonly data: {
        dataflow: DataflowInformation;
    };
}
/** A filter expression resolved to the function testing one element. */
export type PreparedFilter = (element: FlowrSearchElement<ParentInformation>, data: {
    dataflow: DataflowInformation;
}) => boolean;
/**
 * Resolve a filter expression to the function that tests one element.
 * Nothing here depends on the element, so a search over `n` elements should do this once instead of `n` times:
 * a bare {@link VertexType}/{@link RType} filter otherwise builds a {@link FlowrFilterCombinator} per element.
 * @see {@link evalFilter} - the one-shot form, if you only test a single element
 */
export declare function prepareFilter<Filter extends FlowrFilter>(filter: FlowrFilterExpression<Filter>): PreparedFilter;
/**
 * Evaluates the given filter expression against the provided data.
 * @see {@link prepareFilter} - resolve once when testing more than one element
 */
export declare function evalFilter<Filter extends FlowrFilter>(filter: FlowrFilterExpression<Filter>, data: FilterData): boolean;
export {};
