import type { AstIdMap, ParentInformation } from '../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
import type { NodeId } from '../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
import type { DataflowGraph } from '../../../../graph/graph';
import type { ControlFlowGraph } from '../../../../../control-flow/control-flow-graph';
/** The reads that may force the expression, and the control flow deciding what they can see. */
export interface ForceSites {
    readonly cfg: ControlFlowGraph;
    readonly sites: readonly NodeId[];
    /** the name the deferred expression is bound to, whose binding its own writes replace */
    readonly binding: NodeId;
}
/** Where a name is bound and where it is read, so that a deferred expression can reach either. */
interface NameIndex {
    readonly definitions: ReadonlyMap<string, NodeId[]>;
    readonly uses: ReadonlyMap<string, NodeId[]>;
}
/**
 * An expression R evaluates at a time we cannot pin down: the body a `delayedAssign` binds, forced at some
 * later read of the name, or a promise a closure carries past the call that created it.
 *
 * Since the moment is open, every binding the expression may meet is a candidate, and symmetrically so:
 * a name it reads may read any definition of that name, and a name it writes may be read by any use of it.
 * That is the may-analysis both directions ask for, so nothing the expression really depends on, and nothing
 * really depending on it, can be missed.
 */
export declare const Deferred: {
    readonly name: "Deferred";
    /** Where each name is bound and read, built once and shared by every deferred expression in the graph. */
    readonly indexOf: <Info>(this: void, graph: DataflowGraph, idMap: AstIdMap<Info & ParentInformation>) => NameIndex;
    /**
     * The reads that may be the one forcing `binding`: every read of it that no other read always precedes,
     * since an earlier read would already have forced it and cached the value.
     */
    readonly forcedAt: (this: void, graph: DataflowGraph, binding: NodeId, cfg: ControlFlowGraph) => readonly NodeId[];
    /**
     * Links the writes an expression performs to the uses that may observe them, for a call evaluating the
     * expression at a point control flow can pin down (`eval`). The reads are settled by the evaluating call
     * itself, against the environment in effect there, so only this direction is left open.
     */
    readonly publish: <Info>(this: void, graph: DataflowGraph, expr: NodeId, index: NameIndex, idMap: AstIdMap<Info & ParentInformation>, at: NodeId, cfg?: ControlFlowGraph) => void;
    /**
     * Links the expression rooted at `expr` to the bindings it may meet when it is evaluated. Given the reads
     * that may force it, control flow rules out what no force can reach; without them every binding stays a
     * candidate.
     */
    readonly link: <Info>(this: void, graph: DataflowGraph, expr: NodeId, index: NameIndex, idMap: AstIdMap<Info & ParentInformation>, forces?: ForceSites) => void;
};
export {};
