import type { BindingElem, ClassMember, GetAccessorDecl, MethodDecl, ParameterDecl, SetAccessorDecl, VariableDecl } from "./declaration";
import { BaseNode, BindingDecl, FunctionlessNode } from "./node";
import { NodeKind } from "./node-kind";
import { Span } from "./span";
import type { BlockStmt, Stmt } from "./statement";
import type { AnyClass, AnyFunction } from "./util";
/**
 * An {@link Expr} (Expression) is a Node that will be interpreted to a value.
 */
export declare type Expr = Argument | ArrayLiteralExpr | ArrowFunctionExpr | AwaitExpr | BigIntExpr | BinaryExpr | BooleanLiteralExpr | CallExpr | ClassExpr | ComputedPropertyNameExpr | ConditionExpr | DeleteExpr | ElementAccessExpr | FunctionExpr | Identifier | NewExpr | NoSubstitutionTemplateLiteralExpr | NullLiteralExpr | NumberLiteralExpr | ObjectLiteralExpr | OmittedExpr | ParenthesizedExpr | PostfixUnaryExpr | PrivateIdentifier | PropAccessExpr | PropAssignExpr | ReferenceExpr | RegexExpr | SpreadAssignExpr | SpreadElementExpr | StringLiteralExpr | SuperKeyword | TaggedTemplateExpr | TemplateExpr | ThisExpr | TypeOfExpr | UnaryExpr | UndefinedLiteralExpr | VoidExpr | YieldExpr;
export declare abstract class BaseExpr<Kind extends NodeKind, Parent extends FunctionlessNode | undefined = BindingElem | Expr | Stmt | VariableDecl> extends BaseNode<Kind, Parent> {
    readonly nodeKind: "Expr";
}
export declare class ArrowFunctionExpr<F extends AnyFunction = AnyFunction> extends BaseExpr<NodeKind.ArrowFunctionExpr, FunctionlessNode | undefined> {
    readonly parameters: ParameterDecl[];
    readonly body: BlockStmt;
    /**
     * true if this function has an `async` modifier
     * ```ts
     * async () =>  {}
     * ```
     */
    readonly isAsync: boolean;
    /**
     * Name of the source file this node originates from.
     *
     * Only set on the root of the tree, i.e. when `this` is `undefined`.
     */
    readonly filename?: string | undefined;
    readonly _functionBrand?: F;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, parameters: ParameterDecl[], body: BlockStmt, 
    /**
     * true if this function has an `async` modifier
     * ```ts
     * async () =>  {}
     * ```
     */
    isAsync: boolean, 
    /**
     * Name of the source file this node originates from.
     *
     * Only set on the root of the tree, i.e. when `this` is `undefined`.
     */
    filename?: string | undefined);
}
export declare class FunctionExpr<F extends AnyFunction = AnyFunction> extends BaseExpr<NodeKind.FunctionExpr> {
    readonly name: string | undefined;
    readonly parameters: ParameterDecl[];
    readonly body: BlockStmt;
    /**
     * true if this function has an `async` modifier
     * ```ts
     * async function foo() {}
     * // asterisk can co-exist
     * async function *foo() {}
     * ```
     */
    readonly isAsync: boolean;
    /**
     * true if this function has an `*` modifier
     *
     * ```ts
     * function foo*() {}
     *
     * // async can co-exist
     * async function *foo() {}
     * ```
     */
    readonly isAsterisk: boolean;
    /**
     * Name of the source file this node originates from.
     *
     * Only set on the root of the tree, i.e. when `this` is `undefined`.
     */
    readonly filename?: string | undefined;
    readonly _functionBrand?: F;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, name: string | undefined, parameters: ParameterDecl[], body: BlockStmt, 
    /**
     * true if this function has an `async` modifier
     * ```ts
     * async function foo() {}
     * // asterisk can co-exist
     * async function *foo() {}
     * ```
     */
    isAsync: boolean, 
    /**
     * true if this function has an `*` modifier
     *
     * ```ts
     * function foo*() {}
     *
     * // async can co-exist
     * async function *foo() {}
     * ```
     */
    isAsterisk: boolean, 
    /**
     * Name of the source file this node originates from.
     *
     * Only set on the root of the tree, i.e. when `this` is `undefined`.
     */
    filename?: string | undefined);
}
export declare class ClassExpr<C extends AnyClass = AnyClass> extends BaseExpr<NodeKind.ClassExpr, FunctionlessNode | undefined> {
    readonly name: Identifier | undefined;
    readonly heritage: Expr | undefined;
    readonly members: ClassMember[];
    /**
     * Name of the source file this node originates from.
     *
     * Only set on the root of the tree, i.e. when `this` is `undefined`.
     */
    readonly filename?: string | undefined;
    readonly _classBrand?: C;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, name: Identifier | undefined, heritage: Expr | undefined, members: ClassMember[], 
    /**
     * Name of the source file this node originates from.
     *
     * Only set on the root of the tree, i.e. when `this` is `undefined`.
     */
    filename?: string | undefined);
}
export declare class ReferenceExpr<R = unknown> extends BaseExpr<NodeKind.ReferenceExpr> {
    /**
     * Name of the referenced variable.
     *
     * ```ts
     * let i;
     *
     * i; // "i"
     * ```
     */
    readonly name: string;
    /**
     * A closure that produces the referred value.
     */
    readonly ref: () => R;
    /**
     * A number that uniquely identifies the variable within this AST.
     *
     * This is used to ensure that two ReferenceExpr's pointing to the same variable still point
     * to the same variable after transformation.
     */
    readonly id: number | undefined;
    /**
     * Unique ID of this {@link ReferenceExpr}.
     */
    readonly referenceId: number | undefined;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, 
    /**
     * Name of the referenced variable.
     *
     * ```ts
     * let i;
     *
     * i; // "i"
     * ```
     */
    name: string, 
    /**
     * A closure that produces the referred value.
     */
    ref: () => R, 
    /**
     * A number that uniquely identifies the variable within this AST.
     *
     * This is used to ensure that two ReferenceExpr's pointing to the same variable still point
     * to the same variable after transformation.
     */
    id: number | undefined, 
    /**
     * Unique ID of this {@link ReferenceExpr}.
     */
    referenceId: number | undefined);
}
export declare type VariableReference = Identifier | PropAccessExpr | ElementAccessExpr;
export declare class Identifier extends BaseExpr<NodeKind.Identifier> {
    readonly name: string;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, name: string);
    lookup(): BindingDecl | undefined;
}
export declare class PrivateIdentifier extends BaseExpr<NodeKind.PrivateIdentifier> {
    readonly name: `#${string}`;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, name: `#${string}`);
    lookup(): BindingDecl | undefined;
}
export declare class PropAccessExpr extends BaseExpr<NodeKind.PropAccessExpr> {
    readonly expr: Expr | SuperKeyword;
    readonly name: Identifier | PrivateIdentifier;
    /**
     * Whether this is using optional chaining.
     * ```ts
     * a?.prop
     * ```
     */
    readonly isOptional: boolean;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr | SuperKeyword, name: Identifier | PrivateIdentifier, 
    /**
     * Whether this is using optional chaining.
     * ```ts
     * a?.prop
     * ```
     */
    isOptional: boolean);
}
export declare class ElementAccessExpr extends BaseExpr<NodeKind.ElementAccessExpr> {
    readonly expr: Expr;
    readonly element: Expr;
    /**
     * Whether this is using optional chaining.
     * ```ts
     * a?.[element]
     * ```
     */
    readonly isOptional: boolean;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr, element: Expr, 
    /**
     * Whether this is using optional chaining.
     * ```ts
     * a?.[element]
     * ```
     */
    isOptional: boolean);
}
export declare class Argument extends BaseExpr<NodeKind.Argument, CallExpr | NewExpr> {
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr);
}
export declare class CallExpr<E extends Expr | ImportKeyword = Expr | ImportKeyword> extends BaseExpr<NodeKind.CallExpr> {
    readonly expr: E;
    readonly args: Argument[];
    /**
     * Is this an optionally chained call?
     *
     * a?.()
     */
    readonly isOptional: boolean | undefined;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: E, args: Argument[], 
    /**
     * Is this an optionally chained call?
     *
     * a?.()
     */
    isOptional: boolean | undefined);
}
export declare class NewExpr extends BaseExpr<NodeKind.NewExpr> {
    readonly expr: Expr;
    readonly args: Argument[];
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr, args: Argument[]);
}
export declare class ConditionExpr extends BaseExpr<NodeKind.ConditionExpr> {
    readonly when: Expr;
    readonly then: Expr;
    readonly _else: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, when: Expr, then: Expr, _else: Expr);
}
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#arithmetic_operators
 */
export declare type ArithmeticOp = "+" | "-" | "/" | "*" | "%" | "**";
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#assignment_operators
 */
export declare type AssignmentOp = "=" | "*=" | "**=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | ">>>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "??=";
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#binary_logical_operators
 */
export declare type BinaryLogicalOp = "&&" | "||" | "??";
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#bitwise_shift_operators
 */
export declare type BitwiseShiftOp = "<<" | ">>" | ">>>";
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators
 */
export declare type BitwiseBinaryOp = "&" | "|" | "^";
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#comma_operator
 */
export declare type CommaOp = ",";
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#equality_operators
 */
export declare type EqualityOp = "==" | "!=" | "===" | "!==";
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#relational_operators
 */
export declare type RelationalOp = "in" | "instanceof" | "<" | ">" | "<=" | ">=";
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators
 */
export declare type BinaryOp = ArithmeticOp | AssignmentOp | BinaryLogicalOp | BitwiseShiftOp | BitwiseBinaryOp | CommaOp | EqualityOp | RelationalOp;
export declare class BinaryExpr extends BaseExpr<NodeKind.BinaryExpr> {
    readonly left: Expr;
    readonly op: BinaryOp;
    readonly right: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, left: Expr, op: BinaryOp, right: Expr);
}
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#increment_and_decrement
 */
export declare type PostfixUnaryOp = "--" | "++";
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#unary_operators
 */
export declare type UnaryOp = "!" | "+" | "-" | "~" | PostfixUnaryOp;
export declare class UnaryExpr extends BaseExpr<NodeKind.UnaryExpr> {
    readonly op: UnaryOp;
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, op: UnaryOp, expr: Expr);
}
export declare class PostfixUnaryExpr extends BaseExpr<NodeKind.PostfixUnaryExpr> {
    readonly op: PostfixUnaryOp;
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, op: PostfixUnaryOp, expr: Expr);
}
export declare class NullLiteralExpr extends BaseExpr<NodeKind.NullLiteralExpr> {
    readonly value: null;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span);
}
export declare class UndefinedLiteralExpr extends BaseExpr<NodeKind.UndefinedLiteralExpr> {
    readonly value: undefined;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span);
}
export declare class BooleanLiteralExpr extends BaseExpr<NodeKind.BooleanLiteralExpr> {
    readonly value: boolean;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, value: boolean);
}
export declare class BigIntExpr extends BaseExpr<NodeKind.BigIntExpr> {
    readonly value: bigint;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, value: bigint);
}
export declare class NumberLiteralExpr extends BaseExpr<NodeKind.NumberLiteralExpr> {
    readonly value: number;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, value: number);
}
export declare class StringLiteralExpr extends BaseExpr<NodeKind.StringLiteralExpr> {
    readonly value: string;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, value: string);
}
export declare class ArrayLiteralExpr extends BaseExpr<NodeKind.ArrayLiteralExpr> {
    readonly items: Expr[];
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, items: Expr[]);
}
export declare type ObjectElementExpr = GetAccessorDecl | MethodDecl | PropAssignExpr | SetAccessorDecl | SpreadAssignExpr;
export declare class ObjectLiteralExpr extends BaseExpr<NodeKind.ObjectLiteralExpr> {
    readonly properties: ObjectElementExpr[];
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, properties: ObjectElementExpr[]);
    getProperty(name: string): ObjectElementExpr | undefined;
}
export declare type PropName = Identifier | PrivateIdentifier | ComputedPropertyNameExpr | StringLiteralExpr | NumberLiteralExpr;
export declare class PropAssignExpr extends BaseExpr<NodeKind.PropAssignExpr, ObjectLiteralExpr> {
    readonly name: PropName;
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, name: PropName, expr: Expr);
}
export declare class ComputedPropertyNameExpr extends BaseExpr<NodeKind.ComputedPropertyNameExpr, PropAssignExpr> {
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr);
}
export declare class SpreadAssignExpr extends BaseExpr<NodeKind.SpreadAssignExpr, ObjectLiteralExpr> {
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr);
}
export declare class SpreadElementExpr extends BaseExpr<NodeKind.SpreadElementExpr, ObjectLiteralExpr> {
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr);
}
export declare type TemplateLiteral = TemplateExpr | NoSubstitutionTemplateLiteralExpr;
/**
 * A Template literal with no substitutions.
 *
 * ```ts
 * `has no substitutions`
 * ```
 */
export declare class NoSubstitutionTemplateLiteralExpr extends BaseExpr<NodeKind.NoSubstitutionTemplateLiteral> {
    readonly text: string;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, text: string);
}
/**
 * A template expression.
 *
 * ```ts
 * `<head>(${expr}<literal>)*
 * ```
 */
export declare class TemplateExpr extends BaseExpr<NodeKind.TemplateExpr> {
    /**
     * The literal text prefix of the template.
     * ```
     * `head${expr}` // "head"
     * `${expr}` // ""
     * ```
     */
    readonly head: TemplateHead;
    /**
     * A chain of {@link TemplateSpan}s. The last {@link TemplateSpan}'s `literal` is always a
     * {@link TemplateTail} and the former are always {@link TemplateMiddle}s.
     */
    readonly spans: [
        ...TemplateSpan<TemplateMiddle>[],
        TemplateSpan<TemplateTail>
    ];
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, 
    /**
     * The literal text prefix of the template.
     * ```
     * `head${expr}` // "head"
     * `${expr}` // ""
     * ```
     */
    head: TemplateHead, 
    /**
     * A chain of {@link TemplateSpan}s. The last {@link TemplateSpan}'s `literal` is always a
     * {@link TemplateTail} and the former are always {@link TemplateMiddle}s.
     */
    spans: [
        ...TemplateSpan<TemplateMiddle>[],
        TemplateSpan<TemplateTail>
    ]);
}
/**
 * A tagged template expression.
 *
 * ```ts
 * <tag>`<head>(${expr}<literal>)*
 * ```
 */
export declare class TaggedTemplateExpr extends BaseExpr<NodeKind.TaggedTemplateExpr> {
    readonly tag: Expr;
    readonly template: TemplateLiteral;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, tag: Expr, template: TemplateLiteral);
}
/**
 * The first quasi string at the beginning of a {@link TemplateExpr}.
 *
 * ```ts
 * const s = `abc${def}`
 *          // ^ TemplateHead
 * ```
 *
 * Is empty in the case when there is no head quasi:
 * ```ts
 * `${abc}`
 * // TemplateHead is "".
 * ```
 */
export declare class TemplateHead extends BaseNode<NodeKind.TemplateHead, TemplateExpr> {
    readonly text: string;
    readonly nodeKind = "Node";
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, text: string);
}
/**
 * A span of text and expression within a {@link TemplateExpr} or {@link TaggedTemplateExpr}.
 *
 * ```ts
 * `${expr}<literal>`
 * ```
 */
export declare class TemplateSpan<Literal extends TemplateMiddle | TemplateTail = TemplateMiddle | TemplateTail> extends BaseNode<NodeKind.TemplateSpan, TemplateExpr> {
    readonly expr: Expr;
    readonly literal: Literal;
    readonly nodeKind = "Node";
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr, literal: Literal);
}
export declare class TemplateMiddle extends BaseNode<NodeKind.TemplateMiddle, TemplateSpan> {
    readonly text: string;
    readonly nodeKind = "Node";
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, text: string);
}
export declare class TemplateTail extends BaseNode<NodeKind.TemplateTail, TemplateSpan> {
    readonly text: string;
    readonly nodeKind = "Node";
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, text: string);
}
export declare class TypeOfExpr extends BaseExpr<NodeKind.TypeOfExpr> {
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr);
}
export declare class AwaitExpr extends BaseExpr<NodeKind.AwaitExpr> {
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr);
}
export declare class ThisExpr<T = any> extends BaseExpr<NodeKind.ThisExpr> {
    /**
     * Produce the value of `this`
     */
    readonly ref: (() => T) | undefined;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, 
    /**
     * Produce the value of `this`
     */
    ref: (() => T) | undefined);
}
export declare class SuperKeyword extends BaseExpr<NodeKind.SuperKeyword> {
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span);
}
export declare class ImportKeyword extends BaseNode<NodeKind.ImportKeyword> {
    readonly nodeKind = "Node";
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span);
}
export declare class YieldExpr<Delegate extends boolean = boolean> extends BaseExpr<NodeKind.YieldExpr> {
    /**
     * The expression to yield (or delegate) to.
     *
     * If {@link delegate} is `true`, then {@link expr} must be defined, because
     * `yield*` defers to another Generator, which `undefined` is not.
     */
    readonly expr: Expr | Delegate extends true ? undefined : never;
    /**
     * Is a `yield*` delegate expression.
     */
    readonly delegate: Delegate;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, 
    /**
     * The expression to yield (or delegate) to.
     *
     * If {@link delegate} is `true`, then {@link expr} must be defined, because
     * `yield*` defers to another Generator, which `undefined` is not.
     */
    expr: Expr | Delegate extends true ? undefined : never, 
    /**
     * Is a `yield*` delegate expression.
     */
    delegate: Delegate);
}
export declare class RegexExpr extends BaseExpr<NodeKind.RegexExpr> {
    readonly regex: RegExp;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, regex: RegExp);
}
export declare class VoidExpr extends BaseExpr<NodeKind.VoidExpr> {
    /**
     * The expression to yield (or delegate) to.
     */
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, 
    /**
     * The expression to yield (or delegate) to.
     */
    expr: Expr);
}
export declare class DeleteExpr extends BaseExpr<NodeKind.DeleteExpr> {
    readonly expr: PropAccessExpr | ElementAccessExpr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: PropAccessExpr | ElementAccessExpr);
}
export declare class ParenthesizedExpr extends BaseExpr<NodeKind.ParenthesizedExpr> {
    readonly expr: Expr;
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span, expr: Expr);
    unwrap(): Expr | undefined;
}
export declare class OmittedExpr extends BaseExpr<NodeKind.OmittedExpr> {
    constructor(
    /**
     * Range of text in the source file where this Node resides.
     */
    span: Span);
}
export declare const deploymentOnlyModule = true;
//# sourceMappingURL=expression.d.ts.map