import type { BuiltInMemory } from './built-in';
import type { IdentifierDefinition } from './identifier';
import { Identifier } from './identifier';
import type { ControlDependency } from '../info';
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
/** A single entry/scope within an {@link REnvironmentInformation} */
export interface IEnvironment {
    /** Unique internally generated identifier, used for debugging not comparison */
    readonly id: number;
    /** Lexical parent of the environment, if any (can be manipulated by R code) */
    parent: IEnvironment;
    /** Maps to exactly one definition of an identifier if the source is known, otherwise to a list of all possible definitions */
    memory: BuiltInMemory;
    /** Built-in environment that must not change; only for the top-most envs. */
    builtInEnv?: true | undefined;
}
export declare enum EnvType {
    Namespace = "ns",
    Imports = "imp",
    /** `requireNamespace("pkg")`: `pkg::fn` resolves, bare `fn` does not */
    LoadedNamespace = "lns"
}
interface Jsonified {
    id: NodeId;
    parent: Jsonified | undefined;
    builtInEnv?: true;
    memory: BuiltInMemory;
    n?: string;
    t?: EnvType;
    globalEnv?: true;
}
/**
 * Use only if you do not know the object type; otherwise rely on {@link IEnvironment#builtInEnv}.
 */
export declare function isDefaultBuiltInEnvironment(obj: unknown): boolean;
/** @see REnvironmentInformation */
export declare class Environment implements IEnvironment {
    readonly id: number;
    /** Optional name for namespaced/non-anonymous environments, please only set if you know what you are doing */
    n?: string;
    /** which search-path layer this env is (package/namespace/imports), if any */
    t?: EnvType;
    /** if created by a closure, the node id of that closure */
    private c?;
    parent: Environment;
    memory: BuiltInMemory;
    cache?: Map<Identifier, IdentifierDefinition[]>;
    builtInEnv?: true;
    /** {@link memory} is shared with a clone; writing needs {@link writableMemory} to unshare it first */
    private sharedMemory?;
    /** marks the global environment (`.GlobalEnv`); attached packages (see {@link EnvType}) live below it */
    globalEnv?: true;
    constructor(parent: Environment, isBuiltInDefault?: true | undefined);
    /** Marks this as an attached-package layer (see {@link EnvType}) for package `name`. */
    asLibrary(name: string, type: EnvType): this;
    /** Marks this as the global environment (`.GlobalEnv`); see {@link globalEnv}. */
    asGlobal(): this;
    /** please only use if you know what you are doing */
    setClosureNodeId(nodeId: NodeId): void;
    /** Provides the closure linked to this environment. */
    get closure(): NodeId | undefined;
    /**
     * This environment's {@link memory}, ready to be written to. Every in-place write must go through this
     * rather than through {@link memory} directly, as {@link clone} hands the map itself to the clone and only
     * the first writer of either side copies it (copy-on-write).
     */
    get writableMemory(): BuiltInMemory;
    /**
     * Create a clone of this environment.
     *
     * The clone shares this environment's {@link memory} until either side writes to it (see
     * {@link writableMemory}); cloning a frame is therefore independent of how many definitions it holds, which
     * matters because attached packages contribute frames with thousands of them.
     * @param recurseParents     - Whether to also clone parent environments
     */
    clone(recurseParents: boolean): Environment;
    /**
     * Define a new identifier definition within this environment.
     * @param definition  - The definition to add.
     */
    define(definition: IdentifierDefinition & {
        name: Identifier;
    }): Environment;
    /**
     * Define several identifiers at once in a more performant fashion.
     * @param definitions - The definitions to add.
     */
    defineAll(definitions: Iterable<IdentifierDefinition & {
        name: Identifier;
    }>): Environment;
    /** Only sound on an environment nobody else holds yet. */
    private apply;
    private defineInNamespace;
    defineSuper(definition: IdentifierDefinition & {
        name: Identifier;
    }): Environment;
    /**
     * Definitions within `other` replace those here by name; if all of `other`'s are maybe, they are appended instead (turning existing ones maybe too), like {@link appendEnvironment}. Always recurses parents.
     */
    overwrite(other: Environment | undefined, applyCds?: readonly ControlDependency[]): Environment;
    /**
     * Adds all writes of `other` to this environment (`other`'s operations *might* happen). Always recurses parents.
     */
    append(other: Environment | undefined): Environment;
    /**
     * The environment a merge with `other` settles on without touching either memory, `undefined` if the
     * memories have to be merged. Package blocks are always unioned, never overwritten or appended to.
     */
    private mergeShortcut;
    /**
     * Unions two attached-package blocks, keeping every package once (memory merged for a package in both).
     */
    private mergePackageBlocks;
    remove(id: Identifier): this;
    removeAll(names: readonly {
        name: Identifier;
    }[]): Environment;
    toJSON(): Jsonified;
}
/** Walks up to the global environment (see {@link Environment#globalEnv}), falling back to the last non-builtin env. */
declare function findGlobalEnvironment(this: void, env: Environment): Environment;
/** Walks up to the built-in environment. */
declare function findBuiltInEnvironment(this: void, env: Environment): Environment;
/** The `search()` position directly below the global environment; where R attaches by default. */
export declare const DefaultAttachPosition = 2;
/** Prefix of a package's entry in R's `search()` list. */
export declare const SearchPathPackagePrefix = "package:";
/** Name of the global environment in R's `search()` list. */
export declare const GlobalEnvEntryName = ".GlobalEnv";
/**
 * Splices a package block (`blockTop`..`blockBottom`) into the search path at the 1-based `search()` position `pos`
 * ({@link DefaultAttachPosition|2} being directly below the global environment, the default). A position past the end
 * of the search path attaches directly above the built-in environment, mirroring R's clamping. Returns a fresh
 * `current`, cloning only the path down to the insertion point.
 */
declare function attachPackageAt(this: void, current: Environment, blockTop: Environment, blockBottom: Environment, pos?: number): Environment;
/**
 * The 1-based `search()` position of the entry called `name` (`.GlobalEnv`, `package:x`, or a bare package name),
 * or `undefined` if no such entry is on the search path. `package:base` resolves to the built-in environment at the
 * very bottom if base R is not attached as its own layer.
 */
declare function searchPositionOf(this: void, env: Environment, name: string): number | undefined;
/**
 * The packages attached below the global environment, i.e. those whose exports R resolves without a namespace.
 * Base is always among them, as it backs the built-in environment even when it is no layer of its own.
 */
declare function attachedPackagesOf(this: void, env: Environment): Set<string>;
/**
 * Helpers for navigating and manipulating {@link REnvironmentInformation|environments} around the global environment and attached-package search path.
 */
export declare const REnvironment: {
    readonly name: "REnvironment";
    /** Walks up to the global environment (`.GlobalEnv`); see {@link findGlobalEnvironment}. */
    readonly findGlobal: typeof findGlobalEnvironment;
    /** Walks up to the built-in environment; see {@link findBuiltInEnvironment}. */
    readonly findBuiltIn: typeof findBuiltInEnvironment;
    /** Attaches a package block at a `search()` position, below the global by default; see {@link attachPackageAt}. */
    readonly attachAt: typeof attachPackageAt;
    /** The `search()` position of a named entry; see {@link searchPositionOf}. */
    readonly searchPosition: typeof searchPositionOf;
    /** The packages on the search path; see {@link attachedPackagesOf}. */
    readonly attachedPackages: typeof attachedPackagesOf;
};
/**
 * An environment describes a ({@link IEnvironment#parent|scoped}) mapping of names to their definitions ({@link BuiltIns}).
 *
 * The {@link BuiltIns|BuiltInEnvironment} holds R's built-in functions and constants; during serialization use {@link builtInEnvJsonReplacer} to avoid inlining it.
 * @see {@link define} - to define a new {@link IdentifierDefinition|identifier definition} within an environment
 * @see {@link Resolve.byNameAndType} - to resolve an {@link Identifier|identifier/name} to its {@link IdentifierDefinition|definitions} within an environment
 * @see {@link makeReferenceMaybe} - to attach control dependencies to a reference
 * @see {@link pushLocalEnvironment} - to create a new local scope
 * @see {@link popLocalEnvironment} - to remove the current local scope
 * @see {@link appendEnvironment} - to append an environment to the current one
 * @see {@link overwriteEnvironment} - to overwrite the definitions in the current environment with those of another one
 */
export interface REnvironmentInformation {
    /** The currently active environment (the stack is represented by the {@link IEnvironment#parent} chain). */
    readonly current: Environment;
    /** nesting level of the environment, will be `0` for the global/root environment */
    readonly level: number;
}
/** Serializes an environment, replacing the built-in environment with a placeholder. */
export declare function builtInEnvJsonReplacer(k: unknown, v: unknown): unknown;
export {};
