import { type Lattice, Bottom, Top } from './lattice';
/**
 * The default limit of inferred constraints in {@link AbstractDomain|AbstractDomains}.
 */
export declare const DEFAULT_INFERENCE_LIMIT = 50;
/**
 * An abstract domain as complete lattice with a widening and narrowing operator.
 * All operations of value abstract domains should not modify the domain in-place but return new values using {@link create}.
 * @template Value - Type of an abstract element of the abstract domain representing possible elements (excludes `Top` and `Bot`)
 * @template Top   - Type of the Top element of the abstract domain representing all possible elements
 * @template Bot   - Type of the Bottom element of the abstract domain representing no possible elements
 * @template Lift  - Type of the current abstract value in the abstract domain (defaults to `Value` or `Top` or `Bot`)
 */
export declare abstract class AbstractDomain<Value, Top, Bot, Lift extends Value | Top | Bot = Value | Top | Bot> implements Lattice<Value, Top, Bot, Lift> {
    protected readonly _value: Lift;
    constructor(value: Lift);
    get value(): Lift;
    abstract create(value: Value | Top | Bot): this;
    abstract top(): this & AbstractDomain<Value, Top, Bot, Top>;
    abstract bottom(): this & AbstractDomain<Value, Top, Bot, Bot>;
    equals(other: this): boolean;
    protected abstract equalsValue(this: AbstractDomain<Value, Top, Bot, Value>, other: AbstractDomain<Value, Top, Bot, Value>): boolean;
    leq(other: this): boolean;
    protected abstract leqValue(this: AbstractDomain<Value, Top, Bot, Value>, other: AbstractDomain<Value, Top, Bot, Value>): boolean;
    join(other: this | Value | Top | Bot): this;
    protected abstract joinValue(this: AbstractDomain<Value, Top, Bot, Value>, other: AbstractDomain<Value, Top, Bot, Value>): this;
    /**
     * Joins the current abstract value with multiple other abstract values.
     */
    joinAll(values: readonly this[]): this;
    meet(other: this | Value | Top | Bot): this;
    protected abstract meetValue(this: AbstractDomain<Value, Top, Bot, Value>, other: AbstractDomain<Value, Top, Bot, Value>): this;
    /**
     * Meets the current abstract value with multiple other abstract values.
     */
    meetAll(values: readonly this[]): this;
    /**
     * Widens the current abstract value with another abstract value as a sound over-approximation of the join (least upper bound) for fixpoint iteration acceleration.
     */
    widen(other: this): this;
    protected widenValue?(this: AbstractDomain<Value, Top, Bot, Value>, other: AbstractDomain<Value, Top, Bot, Value>): this;
    /**
     * Narrows the current abstract value with another abstract value as a sound over-approximation of the meet (greatest lower bound) to refine the value after widening.
     */
    narrow(other: this): this;
    protected narrowValue?(this: AbstractDomain<Value, Top, Bot, Value>, other: AbstractDomain<Value, Top, Bot, Value>): this;
    transform(transform: (value: Value) => Value | Top | Bot, bottomDefault: Value | Top | Bot, topDefault: Value | Top | Bot): this;
    transform(transform: (value: Value | Top) => Value | Top | Bot, bottomDefault: Value | Top | Bot): this;
    transform(transform: (value: Value | Top | Bot) => Value | Top | Bot): this;
    merge(other: this, merge: (first: Value, second: Value) => Value | Top | Bot, bottomDefault: (other: Value | Top | Bot) => Value | Top | Bot, topDefault: (other: Value | Top | Bot) => Value | Top | Bot): this;
    merge(other: this, merge: (first: Value | Top, second: Value | Top) => Value | Top | Bot, bottomDefault: (other: Value | Top | Bot) => Value | Top | Bot): this;
    merge(other: this, merge: (first: Value | Top | Bot, second: Value | Top | Bot) => Value | Top | Bot): this;
    toJSON(): unknown;
    protected abstract jsonify(this: AbstractDomain<Value, Top, Bot, Exclude<Value | Top | Bot, typeof Top | typeof Bottom>>): unknown;
    toString(): string;
    protected abstract stringify(this: AbstractDomain<Value, Top, Bot, Exclude<Value | Top | Bot, typeof Top | typeof Bottom>>): string;
    abstract isTop(): this is this & AbstractDomain<Value, Top, Bot, Top>;
    isNotTop(): this is this & AbstractDomain<Value, Top, Bot, Value | Bot>;
    abstract isBottom(): this is this & AbstractDomain<Value, Top, Bot, Bot>;
    isNotBottom(): this is this & AbstractDomain<Value, Top, Bot, Value | Top>;
    abstract isValue(): this is this & AbstractDomain<Value, Top, Bot, Value>;
    isNotValue(): this is this & AbstractDomain<Value, Top, Bot, Top | Bot>;
    /**
     * Joins an array of abstract values by joining the first abstract value with the other values in the array.
     * The provided array of abstract values must not be empty or a default value must be provided!
     */
    static joinAll<Domain extends AnyAbstractDomain>(values: Domain[], defaultValue?: Domain): Domain;
    /**
     * Meets an array of abstract values by meeting the first abstract value with the other values in the array.
     * The provided array of abstract values must not be empty or a default value must be provided!
     */
    static meetAll<Domain extends AnyAbstractDomain>(values: Domain[], defaultValue?: Domain): Domain;
    /**
     * Converts an element of an abstract domain into a string.
     */
    static toString(this: void, value: AnyAbstractDomain | unknown): string;
}
/**
 * A type representing any abstract domain without additional information.
 */
export type AnyAbstractDomain = AbstractDomain<unknown, unknown, unknown>;
/**
 * The type of the abstract values of an abstract domain (including the Top and Bottom element).
 * @template Domain - The abstract domain to get the abstract value type for
 */
export type AbstractValue<Domain extends AnyAbstractDomain> = Domain extends AbstractDomain<infer Value, infer Top, infer Bot> ? Value | Top | Bot : never;
/**
 * The type of an abstract domain holding an abstract value of the domain.
 * @template Domain - The abstract domain abstract domain value type for
 */
export type AbstractDomainValue<Domain extends AnyAbstractDomain> = Domain extends AbstractDomain<infer Value, infer Top, infer Bot> ? Domain & AbstractDomain<Value, Top, Bot, Value> : never;
/**
 * The type an abstract domain holding the Top element (greatest element) of the domain.
 * @template Domain - The abstract domain to get the abstract domain top for
 */
export type AbstractDomainTop<Domain extends AnyAbstractDomain> = Domain extends AbstractDomain<infer Value, infer Top, infer Bot> ? Domain & AbstractDomain<Value, Top, Bot, Top> : never;
/**
 * The type an abstract domain holding the Bottom element (least element) of the domain.
 * @template Domain - The abstract domain to get the abstract domain bottom for
 */
export type AbstractDomainBottom<Domain extends AnyAbstractDomain> = Domain extends AbstractDomain<infer Value, infer Top, infer Bot> ? Domain & AbstractDomain<Value, Top, Bot, Bot> : never;
