import { Interpreter } from "../interpreter";
import * as Brs from ".";
import * as Expr from "../parser/Expression";
import { Location } from "../lexer";
/** An argument to a BrightScript `function` or `sub`. */
export interface Argument {
    /** Where the argument exists in the parsed source file(s). */
    readonly location: Location;
    /** The argument's name. */
    readonly name: {
        text: string;
        location: Location;
    };
    /** The type of the argument expected by the BrightScript runtime. */
    readonly type: {
        kind: Brs.ValueKind;
        location: Location;
    };
    /** The default value to use for the argument if none is provided. */
    readonly defaultValue?: Expr.Expression;
}
/**
 * A variant of the `Argument` interface intended for use only when creating standard library
 * functions.
 */
export declare class StdlibArgument implements Argument {
    readonly location: Argument["location"];
    readonly name: Argument["name"];
    readonly type: Argument["type"];
    readonly defaultValue: Argument["defaultValue"];
    /**
     * Creates an `Argument` without requiring locations to be specified.
     * @param name the name of the argument, used for presentation to users
     * @param type the type of value accepted at runtime
     * @param defaultValue the optional default value to use for this argument if one isn't
     *                     provided at runtime
     */
    constructor(name: string, type: Brs.ValueKind, defaultValue?: Brs.BrsType);
    /** A fake location exists only within the BRS runtime. */
    static readonly InternalLocation: {
        file: string;
        start: {
            line: number;
            column: number;
        };
        end: {
            line: number;
            column: number;
        };
    };
}
/** A BrightScript `function` or `sub`'s signature. */
export interface Signature {
    /** The set of arguments a function accepts. */
    readonly args: Argument[];
    /** Whether the function accepts a variable number of arguments. */
    readonly variadic?: boolean;
    /** The type of BrightScript value the function will return. `sub`s must use `ValueKind.Void`. */
    readonly returns: Brs.ValueKind;
}
/** A BrightScript function signature paired with its implementation. */
export type SignatureAndImplementation = {
    /** A BrightScript function's signature. */
    signature: Signature;
    /** The implementation corresponding to `signature`. */
    impl: CallableImplementation;
};
type SignatureMismatch = AnonymousMismatch | ArgumentMismatch;
type SignatureSatisfaction = SignatureAndImplementation & {
    readonly coercedArgs: Brs.BrsType[];
    mismatches: SignatureMismatch[];
};
/** A mismatch between a BrightScript function's signature and its received arguments. */
export interface AnonymousMismatch {
    /** The type of mismatch that was received. */
    reason: MismatchReason.TooFewArguments | MismatchReason.TooManyArguments;
    /** The number of arguments that was expected. */
    expected: string;
    /** The number of arguments that was actually received. */
    received: string;
}
/** A mismatch between a function argument's expected type and its runtime type. */
export interface ArgumentMismatch {
    /** The type of mismatch that was received. */
    reason: MismatchReason.ArgumentTypeMismatch;
    /** The BrightScript type that was expected for argument `argName`. */
    expected: string;
    /** The BrightScript type that was actually received. */
    received: string;
    /** The name of the argument that had a type mismatch. */
    argName: string;
}
/** The set of possible reasons why a signature and runtime arguments don't match. */
export declare enum MismatchReason {
    /** Not enough arguments were provided to satisfy a signature. */
    TooFewArguments = 0,
    /** Too many arguments were provided to satisfy a signature. */
    TooManyArguments = 1,
    /** An argument's type didn't match the signature's type. */
    ArgumentTypeMismatch = 2
}
/** A BrightScript function's signature, paired with a set of detected signature mismatches. */
export type SignatureAndMismatches = SignatureAndImplementation & {
    /** A copy of the provided arguments, coerced into `signature`'s types if possible. */
    readonly coercedArgs?: Brs.BrsType[];
    /** The set of mismatches between `signature` and the detected mismatches. */
    mismatches: SignatureMismatch[];
};
/** The function type required for all concrete Callables to provide. */
export type CallableImplementation = (interpreter: Interpreter, ...args: any[]) => Brs.BrsType;
/** A `function` or `sub` (either "native" or implemented in BrightScript) that can be called in a BrightScript file. */
export declare class Callable implements Brs.BrsValue, Brs.Boxable {
    readonly kind = Brs.ValueKind.Callable;
    inArray: boolean;
    /** The name of this function within the BrightScript runtime. */
    readonly name: string | undefined;
    /** The signature of this callable within the BrightScript runtime. */
    readonly signatures: SignatureAndImplementation[];
    /** The context (m) that this callable is running under (if `undefined` is running on root m) */
    private context;
    /** The location where this callable is on the source code */
    private location;
    /**
     * Calls the function this `Callable` represents with the provided `arg`uments using the
     * provided `Interpreter` instance.
     *
     * @param interpreter the interpreter to execute this callable in.
     * @param args the arguments to pass to the callable routine.
     *
     * @returns the return value of the function, or `invalid` if nothing is explicitly returned.
     */
    call(interpreter: Interpreter, ...args: Brs.BrsType[]): Brs.BrsType;
    /**
     * Creates a new BrightScript `function` or `sub`.
     * @param name the name this callable should have within the BrightScript runtime.
     * @param signatures the signatures and associated (JavaScript) implementations this callable should
     *                   have within the BrightScript runtime.
     */
    constructor(name: string | undefined, ...signatures: SignatureAndImplementation[]);
    lessThan(other: Brs.BrsType): Brs.BrsBoolean;
    greaterThan(other: Brs.BrsType): Brs.BrsBoolean;
    equalTo(other: Brs.BrsType): Brs.BrsBoolean;
    toString(parent?: Brs.BrsType): string;
    box(): Brs.RoFunction;
    getName(): string;
    getContext(): Brs.RoAssociativeArray | undefined;
    setContext(context: Brs.RoAssociativeArray): void;
    setLocation(location: Location): void;
    getLocation(): Location | undefined;
    /**
     * Attempts to satisfy each signature of this Callable using the provided arguments, coercing arguments into other
     * types where necessary and possible, returning the first satisfied signature and the arguments.
     * @param args - the arguments to satisfy this Callable with
     * @returns the signature, implementation, type mismatches, and coerced arguments for the first encountered
     *          signature satisfied by the provide arguments.
     */
    getFirstSatisfiedSignature(args: Brs.BrsType[]): SignatureSatisfaction | undefined;
    /**
     * Attempts to satisfy each signature of this Callable using the provided arguments, coercing arguments into other
     * types where necessary and possible.
     * @param args - the arguments to satisfy this Callable with
     * @returns the signature, implementation, type mismatches, and coerced arguments for each signature in this
     *          Callable.
     */
    getAllSignatureMismatches(args: Brs.BrsType[]): SignatureSatisfaction[];
    private trySatisfySignature;
    /**
     * Creates several copies of the provided signature and implementation pair, simulating variadic types by
     * creating a function that accepts zero args, one that accepts one arg, one that accepts two args, (…).
     *
     * @param signatureAndImpl the base signature and implementation to make variadic
     *
     * @returns an array containing psuedo-variadic versions of the provided signature and implementation
     */
    static variadic(signatureAndImpl: SignatureAndImplementation): SignatureAndImplementation[];
}
export {};
