import { Decl, VariableDecl } from "./declaration";
import { CallExpr, Expr, Identifier, ReferenceExpr, ThisExpr } from "./expression";
import { IntegrationImpl } from "./integration";
import { Stmt } from "./statement";
import { AnyFunction } from "./util";
export declare function isVTL(a: any): a is VTL;
export declare abstract class VTL {
    static readonly ContextName = "Velocity Template";
    readonly kind = "Velocity Template";
    private readonly statements;
    private varIt;
    constructor(...statements: string[]);
    toVTL(): string;
    add(...statements: string[]): void;
    protected newLocalVarName(): `$v${string}`;
    str(value: string): string;
    /**
     * Converts a variable {@link reference} to JSON using the built-in `$util.toJson` intrinsic function.
     *
     * @param reference variable reference
     * @returns VTL expression which yields a JSON string of the variable {@link reference}.
     */
    json(reference: string): string;
    /**
     * Evaluates an {@link expr} with the `$util.qr` statement.
     *
     * @param expr expression string to evaluate quietly (i.e. without emitting to output) .
     */
    qr(expr: string): void;
    /**
     * Add a statement which sets the variable {@link reference} to the value of the {@link expr}.
     *
     * @param reference the name of the variable to set
     * @param expr the value to set the variable to
     */
    set(reference: string, expr: Expr | string): string;
    /**
     * Stores the {@link expr} in a new variable with a uniquely generated name.
     *
     * @param expr the expression
     * @returns the variable name that contains the value.
     */
    var(expr: string | Expr): string;
    /**
     * The put method on an object.
     *
     * $var.put("name", "value")
     *
     * @param objVar should be a variable referencing an object.
     * @param name should be a quoted string or variable that represents the name to set in the object
     * @param expr should be a quoted string or a variable that represents the value to set
     */
    put(objVar: string, name: string, expr: string | Expr): void;
    /**
     * The putAll method on an object.
     *
     * $var.putAll($otherObj)
     *
     * @param objVar should be a variable referencing an object.
     * @param expr should be a variable that represents an object to merge with the expression
     */
    putAll(objVar: string, expr: Expr): void;
    /**
     * Evaluate and return an {@link expr}.
     *
     * @param expr expression to evaluate
     * @returns a `#return` VTL expression.
     */
    return(expr: string | Expr): void;
    printExpr(val: string | Expr): string;
    printBody(body: string | Stmt | (() => void)): void;
    ifStmt(condition: string | Expr, body: string | Stmt | (() => void), elseBody?: string | Stmt | (() => void), _returnVariable?: string): void;
    foreach(iterVar: string | Expr | VariableDecl, iterValue: string | Expr, body: string | Stmt | (() => void)): void;
    /**
     * Call a service API. The Call expression will be evaluated and JSON will be rendered
     * to the Velocity Template output. This JSON payload will be passed to the
     * service-to-service integration, e.g. a Dynamo API request.
     *
     * ```json
     * #set($payload = {
     *   "operation": "GetItem",
     *   "key": $util.toJson($util.toDynamoDB($key)),
     * })
     * $util.toJson($payload)
     * ```
     * @param call
     */
    call(call: CallExpr): void;
    /**
     * Configure the integration between this VTL template and a target service.
     * @param target the target service to integrate with.
     * @param call the CallExpr representing the integration logic
     */
    protected abstract integrate(target: IntegrationImpl<AnyFunction> | undefined, call: CallExpr): string;
    protected abstract dereference(id: Identifier | ReferenceExpr | ThisExpr): string;
    /**
     * Evaluate an {@link Expr} or {@link Stmt} by emitting statements to this VTL template and
     * return a variable reference to the evaluated value.
     *
     * @param node the {@link Expr} or {@link Stmt} to evaluate.
     * @returns a variable reference to the evaluated value
     */
    eval(node?: Expr, returnVar?: string): string;
    eval(node: Stmt, returnVar?: string): void;
    /**
     * Evaluates a declaration, currently supporting {@link VariableDecl} or {@link ParameterDecl}.
     *
     * VariableDecl(Identifier("name"), StringLiteralExpr("value"))
     * =>
     * #set($name = "value")
     *
     * VariableDecl(ObjectBinding([BindingElm("name")), Identifier("ref"))
     * =>
     * #set($name = $ref.name)
     *
     * @param initialValueVar - Optional variable name to use when an initializer is supported.
     *                          Overrides the `decl.initializer` if supported by the Node.
     */
    evalDecl(decl: Decl, initialValueVar?: string): string | undefined;
    addAll(items: Expr[]): string;
    /**
     * Expands a destructure/binding declaration to separate variable declarations in velocity
     *
     * Applies default values.
     * Supports "rest" destructure expressions.
     *
     * const { a } = b;
     *         ^ name ^ right side of var stmt
     * => a = b.a
     * const { a : b } = c;
     *        ^prop ^name ^ right side of var stmt
     * => b = b.c
     * const { a: { b } } = c;
     *         ^parent prop name
     *              ^ name  ^ right side of var statement
     * => b = c.a.b
     * const { a: { b = 1 } = {} } = c;
     * => temp1 = c.a ? c.a : {}
     *    b = temp1.b ? temp1.b : 1
     *
     * { a } = b;
     * =>
     * const a = b.a;
     *
     * { a, c } = b;
     * =>
     * const a = b.a;
     * const c = b.c;
     *
     * { a: { c } } = b;
     * =>
     * const c = b.a.c;
     *
     * { a, ...rest } = b;
     * =>
     * const a = b.a;
     * const rest = {}
     * for(key in b)
     *   rest[key] = b[key]
     *
     * { a: c } = b;
     * =>
     * const c = b.a;
     *
     * { a: [c] } = b;
     * =>
     * const c = b.a[0];
     *
     * [a] = b;
     * =>
     * b[0]
     *
     * [ a, c ] = b;
     * =>
     * const a = b[0]
     * const c = b[1]
     *
     * [ a, ...rest ] = b;
     * =>
     * const a = b[0]
     * const rest = []
     * for(key in b)
     *    if(key > 0)
     *      rest.push(b[key])
     *
     * [ a: { c } ] = b;
     * =>
     * const c = b[0].c;
     *
     * [a, ...rest] = b
     * const a = b[0]
     * const rest = b[1..]
     */
    private evaluateBindingPattern;
    /**
     * Adds the VTL required to execute the body of a single map or forEach.
     *
     * @param call the map or foreach to render
     * @param list the list to give to the `array` parameter, should be the same one used in the vtl foreach
     * @param returnVariable The variable to put the final map value into. If not provided, will be generated.
     *                       Should start with a '$'.
     * @param index The optional `index` variable name to add if present.
     *              Should start with a '$'.
     * @param array The optional `array` variable name to add if present.
     *              Should start with a '$'.
     * @returns The returnVariable or generated variable name.
     */
    private renderMapOrForEachBody;
    /**
     * Recursively flattens map operations until a non-map or a map with `array` parameter is found.
     * Evaluates the expression after the last map.
     *
     * @param before a method which executes once the
     * @return [firstVariable, list variable, render function]
     */
    private flattenListMapOperations;
}
export declare const deploymentOnlyModule = true;
//# sourceMappingURL=vtl.d.ts.map