import type { FunctionDefinition, GraphNodeDefinition } from "../types.js";
import type { ImportedFunctionSignature } from "../compilationUnit.js";
import type { BuiltinSignature } from "./types.js";
/**
 * Names of Agency's *built-in* functions — language primitives with no
 * `def` source. Users cannot redefine these via `def` or `node`. Single
 * source of truth — imported by typeChecker/index.ts.
 *
 * Stdlib functions (print, read, fetch, etc.) are NOT here. They are
 * regular Agency code in stdlib/index.agency and users may shadow them.
 *
 * Built-ins fall into two parse-time categories:
 *
 *   1. Parsed as plain `functionCall`. Their typed signatures live in
 *      BUILTIN_FUNCTION_TYPES, so they resolve as `kind: "builtin"` before
 *      reaching the reserved-name fallback below. Listed here too as
 *      defense-in-depth (if a BUILTIN_FUNCTION_TYPES entry is ever removed,
 *      the reservation still prevents user redefinition).
 *
 *   2. Parsed as their own AST node — never reach functionCall handling:
 *
 *        schema(Type)  → SchemaExpression  — a language primitive that
 *          bridges *type space* and *value space*: the argument is a
 *          VariableType (not a value expression), and at runtime it
 *          constructs a zod schema from that type. Reserved here only so
 *          that `def schema()` can't create parse ambiguity. The typechecker
 *          currently synthesizes its result type as "any" — populating it
 *          with a structured `Schema<T>` type is future work.
 *
 *        interrupt ...  → InterruptStatement
 *        debugger       → DebuggerStatement
 */
export declare const RESERVED_FUNCTION_NAMES: Set<string>;
/**
 * Registry of JavaScript / Node.js globals that compiled Agency output
 * is allowed to call. Each entry is either:
 *   - kind: "callable"  — a function (sig is optional; populating it
 *                         later enables type-checking)
 *   - kind: "namespace" — an object with named members, each of which
 *                         is itself a JsRegistryEntry
 *
 * Phase 1 uses only the structure (existence checks). Phase 2 will
 * populate `sig` for entries we want type-checked; the typechecker
 * starts enforcing arity/types when `sig` is present.
 *
 * Names already supported natively by Agency (null, undefined) or rare
 * enough to defer (NaN, Infinity) are intentionally absent.
 */
export type JsRegistryEntry = {
    kind: "callable";
    sig?: BuiltinSignature;
} | {
    kind: "namespace";
    members: Record<string, JsRegistryEntry>;
};
export declare const JS_GLOBALS: Record<string, JsRegistryEntry>;
/**
 * Walk a namespace path through `JS_GLOBALS`. Returns the leaf entry if
 * the full chain resolves, otherwise null.
 *
 * Examples:
 *   lookupJsMember(["JSON", "parse"])     → { kind: "callable", sig: undefined }
 *   lookupJsMember(["JSON", "banana"])    → null
 *   lookupJsMember(["NotAGlobal", "x"])   → null
 */
export declare function lookupJsMember(path: string[]): JsRegistryEntry | null;
type ResolveCallInput = {
    functionDefs: Record<string, FunctionDefinition>;
    nodeDefs: Record<string, GraphNodeDefinition>;
    importedFunctions: Record<string, ImportedFunctionSignature>;
    /** Names imported via `import node { ... } from "..."`. */
    importedNodeNames: readonly string[];
    /** Names imported via `import { foo } from "./helpers.js"` (non-Agency). */
    jsImportedNames?: object;
    scopeHas: (name: string) => boolean;
};
/**
 * Tagged union describing where a call name resolved to. The diagnostic
 * only cares whether `kind === "unresolved"`; the other kinds are
 * informational so future analyses can distinguish "user code" from
 * "language built-in" from "JS interop" without re-running the lookup.
 *
 *   def           — locally-defined `def` or `node` in this file.
 *   imported      — function or node imported from another `.agency` file
 *                   (`import { foo } from "./other.agency"` or
 *                   `import node { foo } from "./other.agency"`).
 *   builtin       — has a typed signature in `BUILTIN_FUNCTION_TYPES`.
 *                   True language primitives only: `success`, `failure`,
 *                   `llm`, `approve`, `reject`, `propagate`, `checkpoint`,
 *                   `getCheckpoint`, `restore`, `isSuccess`, `isFailure`.
 *                   Stdlib functions (`print`, `fetch`, `read`, etc.)
 *                   resolve as `imported` instead, via the auto-injected
 *                   `import { ... } from "std::index"` statement.
 *   scopeBinding  — bound in the local scope (lambda, `partial`,
 *                   `for` variable, etc.).
 *   jsGlobal      — flat callable JS global (`parseInt`, `setTimeout`).
 *                   Namespace member calls like `JSON.parse(...)` are
 *                   handled separately via `lookupJsMember`.
 *   unresolved    — none of the above. The diagnostic emits.
 *
 * The other RESERVED_FUNCTION_NAMES entries (`schema` → SchemaExpression,
 * `interrupt` → InterruptStatement, `debugger` → DebuggerStatement) are
 * parsed into their own AST node type and never reach `resolveCall` as a
 * `functionCall`, so there's no `kind: "reserved"` here.
 */
export type CallResolution = {
    kind: "def";
} | {
    kind: "imported";
} | {
    kind: "jsImported";
} | {
    kind: "builtin";
} | {
    kind: "scopeBinding";
} | {
    kind: "jsGlobal";
} | {
    kind: "unresolved";
};
/**
 * Resolution order matters:
 *
 *   1. Local `def`/`node`             — user code wins.
 *   2. Imported from another file     — cross-file `def`/`node`. Stdlib
 *                                       functions (print, fetch, read,
 *                                       …) resolve here via the
 *                                       auto-injected std::index import.
 *   3. JS-imported name               — `import { foo } from "./helpers.js"`.
 *   4. `BUILTIN_FUNCTION_TYPES`       — Agency language primitives.
 *   5. Local scope binding            — lambdas, `partial`, `for` vars.
 *   6. Flat JS global callable        — parseInt, setTimeout, etc.
 *   7. Otherwise: unresolved.
 */
/**
 * Inputs for {@link isJsGlobalBase}. The shape mirrors {@link ResolveCallInput}
 * but adds import-node bookkeeping so user definitions of `JSON` / `Math` /
 * etc. (via `node`, `import node`, or a `let`) cleanly opt out of
 * JS_GLOBALS validation.
 */
export type ShadowingInput = {
    scope: {
        has(name: string): boolean;
    };
    functionDefs: object;
    nodeDefs: object;
    importedFunctions: object;
    importedNodeNames: readonly string[];
    jsImportedNames?: object;
};
/**
 * `true` only when `name` resolves to a JS global *and* nothing user-defined
 * shadows it. Use this to gate JS-namespace member validation (e.g.
 * `JSON.parse(...)`) and avoid checking against `JS_GLOBALS` when the user
 * has their own `node JSON()` / `let JSON = …`.
 */
export declare function isJsGlobalBase(name: string, input: ShadowingInput): boolean;
export declare function resolveCall(name: string, input: ResolveCallInput): CallResolution;
export {};
