import { Construct } from "constructs";
import ts from "typescript";
import { BinaryOp, CallExpr, Expr, PropAccessExpr } from "./expression";
import { FunctionlessNode } from "./node";
export declare type AnyClass = new (...args: any[]) => any;
export declare type AnyFunction = (...args: any[]) => any;
export declare type AnyAsyncFunction = (...args: any[]) => Promise<any>;
/**
 * Create a memoized function.
 *
 * @param f the function that produces the value
 * @returns a function that computes a value on demand at most once.
 */
export declare function memoize<T>(f: () => T): () => T;
export declare function isInTopLevelScope(expr: FunctionlessNode): boolean;
declare type EnsureOr<T extends ((a: any) => a is any)[]> = T[number] extends (a: any) => a is infer T ? T : never;
export declare function anyOf<T extends ((a: any) => a is any)[]>(...fns: T): (a: any) => a is EnsureOr<T>;
export declare type AnyDepthArray<T> = T | T[] | AnyDepthArray<T>[];
export declare function flatten<T>(arr: AnyDepthArray<T>): T[];
export declare function hasParent(node: ts.Node, parent: ts.Node): boolean;
/**
 * Returns true when all ancestors match the predicate.
 * If there are no parents left, `true` is returned.
 * If there is a `stop` provided, matching stop will halt the search and return `true`.
 */
export declare function hasOnlyAncestors(node: ts.Node, cont: (node: ts.Node) => boolean, stop?: (node: ts.Node) => boolean): boolean;
export declare type ConstantValue = PrimitiveValue | {
    [key: string]: ConstantValue;
} | ConstantValue[];
export declare type PrimitiveValue = string | number | boolean | undefined | null;
export declare const isPrimitive: (val: any) => val is PrimitiveValue;
/**
 * Determines if a node looks like `Promise.all()`
 */
export declare function isPromiseAll(expr: CallExpr): expr is CallExpr & {
    expr: PropAccessExpr & {
        name: "all";
    };
};
export declare const singletonConstruct: <T extends Construct, S extends Construct>(scope: S, id: string, create: (scope: S, id: string) => T) => T;
export interface Constant {
    constant: unknown;
}
export declare function isConstant(x: any): x is Constant;
/**
 * Retrieves a string, number, boolean, undefined, or null constant from the given expression.
 * Wrap the value to not be ambiguous with the undefined value.
 * When one is not found, return undefined (not wrapped).
 *
 * Use assertConstant or assertPrimitive to make type assertions of the constant returned.
 * Values from external string may be complex types like functions.
 * We choose to late evaluate invalid values to support use cases like StepFunctions where it is both a function and has constant properties.
 * new StepFunction().stepFunctionArn
 *
 * "value" -> { constant: "value" }
 * undefined -> { constant: undefined }
 * null -> { constant: undefined }
 * call() -> undefined
 * true -> { constant: true }
 * -10 -> { constant: -10 }
 * "hello" -> { constant:  "hello" }
 * "hello" + "world" -> { constant:  "helloworld" }
 * "hello" + 1 -> { constant:  "hello1" }
 * 1 + "hello" -> { constant:  "2hello" }
 * 1 -> { constant:  1 }
 * -1 -> { constant:  -1 }
 * 1 + 2 -> { constant:  3 }
 *
 * Note: constants that follow references must already be resolved to a simple constant by {@link flattenedExpression}.
 * const obj = { val: "hello" };
 * obj.val -> { constant: "hello" }
 */
export declare const evalToConstant: (expr: Expr) => Constant | undefined;
export declare class DeterministicNameGenerator {
    private readonly generatedNames;
    /**
     * Generate a deterministic and unique variable name for a node.
     *
     * The value is cached so that the same node reference always has the same name.
     *
     * @param node the node to generate a name for
     * @returns a unique variable name that can be used in JSON Path
     */
    generateOrGet(node: FunctionlessNode): string;
}
/**
 * Generates unique names starting from the given name and then applying the given formatter function.
 *
 * Registers both the original name and the formatted name to ensure no collisions with given or formatted names.
 *
 * a -> a
 * a -> formatted(a, 1)
 * formatted(a, 1) -> formatted(formatted(a, 1), 1) // if a name is given that matches the output of formatted(a, 1), format the new name
 * formatted(a, 2) -> formatted(a, 2)
 * a -> formatted(a, 3) // the output of formatted(a, 2) already was registered, so try formatted(a, 3)
 */
export declare class UniqueNameGenerator {
    private formatter;
    private readonly nameCount;
    constructor(formatter: (name: string, n: number) => string);
    getUnique(name: string): string;
}
export declare const deploymentOnlyModule = true;
/**
 * Inverts directional binary operators.
 *
 * Useful when normalizing the processing of the left and right of a binary operator.
 *
 * < -> >
 * > -> <
 * >= -> <=
 * <= -> >=
 */
export declare const invertBinaryOperator: (op: BinaryOp) => BinaryOp;
export {};
//# sourceMappingURL=util.d.ts.map