import type { AgencyNode, Assignment, Expression, ScopeType, VariableType } from "../../types.js";
import type { AccessChainElement, ValueAccess } from "../../types/access.js";
import type { TsNode } from "../../ir/tsIR.js";
import type { ScopeManager } from "./scopeManager.js";
/**
 * Callbacks PipeChainEmitter needs from the parent TypeScriptBuilder.
 *
 * Pipe lowering recursively delegates back into the main expression /
 * statement emitter, so we accept the relevant builder methods as
 * dependencies rather than holding a reference to the whole builder.
 */
export type PipeChainEmitterDeps = {
    processNode: (node: AgencyNode) => TsNode;
    /**
     * The builder's full ValueAccess lowering. Used to build pipe-stage
     * receivers correctly — see the doc comment on `processValueAccessPartial`.
     */
    processValueAccess: (node: ValueAccess) => TsNode;
    buildAssignmentLhs: (scope: ScopeType, varName: string, accessChain?: AccessChainElement[]) => TsNode;
    buildStateConfig: () => TsNode | undefined;
    /**
     * Build a zod validation schema string for a VariableType taken from
     * user source. Must deep-resolve generic aliases before lowering, just
     * like the rest of the TS builder does. See `TypeScriptBuilder.zodSchemaFor`.
     */
    zodSchemaFor: (t: VariableType) => string;
    scopes: ScopeManager;
};
/**
 * Lowers `|>` pipe chains into runner steps.
 *
 * A pipe chain `a |> f |> g` is parsed left-associatively as
 * `(a |> f) |> g`. This emitter flattens that tree into ordered stages
 * (`[a, f, g]`) and produces one runner step per stage so that interrupts
 * resume between stages without replaying the earlier ones.
 *
 * Public API:
 *   - {@link tryGetChainStages} — flatten an assignment-of-pipe into stages
 *   - {@link expand}           — turn an assignment + stages into runner nodes
 *   - {@link bind}             — lower a bare `lhs |> rhs` expression
 */
export declare class PipeChainEmitter {
    private deps;
    private counter;
    constructor(deps: PipeChainEmitterDeps);
    /**
     * Walk a left-recursive `|>` tree under an assignment and return
     * [initial, stage1, stage2, ...] in evaluation order.
     * Returns null if the node is not an assignment whose value is a pipe chain.
     */
    tryGetChainStages(node: AgencyNode): Expression[] | null;
    /**
     * Lower a bare pipe expression `left |> stage` (not an assignment) into
     * `await __pipeBind(left, async (__pipeArg) => stage(__pipeArg))`.
     */
    bind(leftIR: TsNode, stage: Expression): TsNode;
    /**
     * Expand a pipe-chain assignment into one runner node per stage.
     *
     * Layout (for `x = a |> f |> g`):
     *   step baseId+0:   __pipe_N = a
     *   pipe baseId+1:   __pipe_N = await __pipeBind(__pipe_N, lambda(f))
     *   pipe baseId+2:   x        = await __pipeBind(__pipe_N, lambda(g))
     *
     * If the assignment is validated (`x!: T = ...`), an extra runner step
     * wraps the final result in `__validateType`.
     */
    expand(stmt: Assignment, stages: Expression[], baseId: number): TsNode[];
    private buildPipeLambda;
    /**
     * Build the body expression for a pipe stage (without the outer arrow
     * function wrapper). Returns `await __call(...)` — the caller wraps this
     * in an arrow function or `__catchResult(...)`.
     */
    private buildPipeStageBody;
    /**
     * Process a ValueAccess up to but not including the last chain element.
     * Used by pipe lowering to get the receiver for a method call —
     * the LAST chain element is the pipe stage's method name, which the
     * caller hands to `__callMethod(receiver, name, …)` directly.
     *
     * Delegates to the builder's full `processValueAccess` (via deps) on
     * a synthetic node with `chain.slice(0, -1)`. This keeps every
     * subtlety of receiver lowering in one place — awaiting + paren-
     * wrapping a `functionCall` base, paren-wrapping a non-trivial base,
     * propagating the `optional` flag through chain elements, handling
     * the `call` chain-element kind, etc. Previously this method
     * duplicated the chain-walk and silently dropped all of those
     * behaviours; see the "pipe receiver precedence" issue for the
     * shapes that were broken (`getObj().foo.bar |> stage`, `obj?.foo
     * |> stage`, `factories.makeOne().bar |> stage`, etc.).
     */
    private processValueAccessPartial;
}
