import { types as t } from "@marko/compiler";
import { type Binding, type Intersection, type IntersectionMeta, type ParamBinding, type ReferencedBindings } from "./bindings";
import * as ContentType from "./constants/content-type";
import type * as Step from "./constants/step";
import * as StructureKind from "./constants/structure-kind";
import { type OneMany, type Opt, Sorted, type SortedOpt } from "./optional";
import { type KnownExprs, type Reason } from "./reasons";
import { type Slot } from "./slots";
import { type Sources } from "./sources";
export type ParamReasonGroup = NonNullable<Sources["param"]>;
export type ParamReasonGroups = [ParamReasonGroup, ...ParamReasonGroup[]];
type ContentType = ContentType.Value;
export { ContentType, StructureKind };
export type StructureRef = StructureSectionRef | StructureExportRef;
export interface StructureSectionRef {
    kind: typeof StructureKind.SectionRef;
    section: Section;
}
export interface StructureExportRef {
    kind: typeof StructureKind.ExportRef;
    program: t.ProgramExtra;
    path: string;
    hint: string;
}
export type StructureOp = string | Step.Value | StructureText | StructureNode | StructureChild | StructureModuleRead;
export interface StructureText {
    kind: typeof StructureKind.Text;
    value: string;
}
export interface StructureNode {
    kind: typeof StructureKind.Node;
    binding: Binding | undefined;
    marker: boolean;
}
export interface StructureChild {
    kind: typeof StructureKind.Child;
    name: string;
    binding: Binding;
    renderer?: StructureRef;
}
export interface StructureModuleRead {
    kind: typeof StructureKind.ModuleRead;
    read: string[];
}
export interface Section {
    id: number;
    name: string;
    loc: t.SourceLocation | undefined;
    depth: number;
    parent: Section | undefined;
    children: Section[];
    program: Section;
    params: undefined | ParamBinding;
    /** The attribute tag `<for>` params this content reads, held as its own
     * bindings that the loop binds as it creates it. */
    localClosures: ReferencedBindings;
    referencedClosures: ReferencedBindings;
    bindings: ReferencedBindings;
    hoisted: ReferencedBindings;
    /** The closures its `<for>` rows read only by comparing them to the row's
     * key, which a row selector updates. */
    selector: {
        key: Binding;
        closures: Set<Binding>;
    } | undefined;
    /** The canonical intersections its work waits on, once ids allocate. */
    intersections: Map<Intersection, IntersectionMeta> | undefined;
    /** The slots of its scope, its own and its bindings'. */
    slots: SortedOpt<Slot>;
    /** When client code reads anything in its scope: its slots' reasons merged. */
    reason: undefined | Reason;
    paramReasonGroups: ParamReasonGroups | undefined;
    returnValueExpr: t.NodeExtra | undefined;
    isHoistThrough: true | undefined;
    branchExpr: t.NodeExtra | undefined;
    /** For a `<define>` body or a template rendering itself, the sections whose
     * direct calls render it. */
    callSections: SortedOpt<Section>;
    /** The content's rendering tag (its extra), and each child binding that
     * derives from the content, at `properties`. */
    derives: {
        tag: t.MarkoTagExtra;
        binding: OneMany<Binding>;
        properties: Opt<string>;
        exprs: KnownExprs | undefined;
    } | undefined;
    /** Content a known child never reads, which no output renders. */
    dropped: boolean;
    hasAbortSignal: boolean;
    /** Count of distinct `$signal` expression roots; analyze allocates each
     * root's abort id from this so translates read, never re-derive. */
    abortSignalExprs: number;
    readsOwner: boolean;
    /** Whether analysis found work keyed by setup in the section, or in a
     * `<define>` body or template it calls in place. */
    hasSetupWork: boolean;
    /** Its tag, which renders it in place into branch scopes at the tag's node
     * binding, and whether its branch expression's value can leave it unrendered. */
    branch: {
        nodeBinding: Binding;
        optional: boolean;
        /** An `<if>` branch's place in its chain, the renderer index it renders as. */
        index?: number;
    } | undefined;
    content: null | {
        startType: ContentType;
        endType: ContentType;
        singleChild: boolean;
    };
    structure: StructureOp[] | null;
}
declare module "@marko/compiler/dist/types" {
    interface ProgramExtra {
        section?: Section;
        sections?: Section[];
    }
    interface MarkoTagBodyExtra {
        section?: Section;
    }
}
export declare const sectionUtil: Sorted<Section>;
export declare function ensureBodySection(path: t.NodePath<t.MarkoTagBody | t.Program>): Section | undefined;
export declare function ensureSection(path: t.NodePath<any>): Section;
export declare function getSectionForBody(body: t.NodePath<t.MarkoTagBody | t.Program>): Section | undefined;
export declare function removeDroppedContent(tag: t.NodePath<t.MarkoTag>): void;
export declare function getSection(path: t.NodePath): Section;
export declare const getScopeIdIdentifier: (section: Section) => t.Identifier;
export declare const getBranchRendererArgs: (section: Section) => [template?: t.Expression | undefined, walks?: t.Expression | undefined, setup?: t.Expression | undefined, params?: t.Expression | undefined], setBranchRendererArgs: (section: Section, value: [template?: t.Expression | undefined, walks?: t.Expression | undefined, setup?: t.Expression | undefined, params?: t.Expression | undefined]) => void;
export declare function forEachSection(fn: (section: Section) => void): void;
export declare function getDynamicTagContentClosures(section: Section): ReferencedBindings;
export declare function forEachAncestorSection<A>(from: Section, to: Section, fn: (section: Section, arg: A) => void, arg: A): void;
export declare function forEachSectionReverse(fn: (section: Section) => void): void;
export declare function getNodeContentType(path: t.NodePath<t.Statement>, edge: "startType" | "endType"): ContentType.Value | null;
export declare function getRendererReason(section: Section): false | Sources;
export declare function isOptionalBranch(section: Section): section is Section & {
    branch: NonNullable<Section["branch"]>;
};
export declare function isInParentSection(binding: Binding, section: Section): boolean;
export declare function isDirectClosure(section: Section, closure: Binding): boolean;
export declare function isDynamicClosure(section: Section, closure: Binding): boolean;
export declare function getDynamicClosureIndex(closure: Binding, closureSection: Section): number;
export declare function getDirectClosures(section: Section): SortedOpt<Binding>;
export declare function isSameOrAncestorSection(section: Section, other: Section): boolean;
export declare function getCommonSection(section: Section, other: Section): Section;
export declare function ensureSectionReasonGroups(section: Section): void;
export declare function ensureReasonGroups(reason: Section["reason"]): void;
export declare function getParamReasonGroupIndex(section: Section, group: ParamReasonGroup): number;
export declare function forEachParamGroup(params: Sources["param"], fn: (section: Section, group: ParamReasonGroup) => void): void;
export declare function reduceParamGroups<R>(params: Sources["param"], fn: (acc: R, section: Section, group: ParamReasonGroup) => R, initial: R): R;
export declare function setReadsOwner(from: Section, to: Section): void;
