UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

113 lines (112 loc) 5.88 kB
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 and internally generated identifier -- will not be used for comparison but helps with debugging for tracking identities */ 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; /** * Is this a built-in environment that is not allowed to change? Please use this carefully and only for the top-most envs! */ builtInEnv?: true | undefined; } type Jsonified = { id: NodeId; parent: Jsonified | undefined; builtInEnv?: true; memory: BuiltInMemory; }; /** * Please use this function 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; /** if created by a closure, the node id of that closure */ private c?; parent: Environment; memory: BuiltInMemory; cache?: Map<Identifier, IdentifierDefinition[]>; builtInEnv?: true; constructor(parent: Environment, isBuiltInDefault?: true | undefined); /** please only use if you know what you are doing */ setClosureNodeId(nodeId: NodeId): void; /** * Provides the closure linked to this environment. * This is of importance if, for example, if you want to know the function definition associated with this environment. */ get closure(): NodeId | undefined; /** * Create a deep clone of this environment. * @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; private defineInNamespace; defineSuper(definition: IdentifierDefinition & { name: Identifier; }): Environment; /** * Assumes, that all definitions within other replace those within this environment (given the same name). * <b>But</b> if all definitions within other are maybe, then they are appended to the current definitions (updating them to be `maybe` from now on as well), similar to {@link appendEnvironment}. * This always recurses parents. */ overwrite(other: Environment | undefined, applyCds?: readonly ControlDependency[]): Environment; /** * Adds all writes of `other` to this environment (i.e., the operations of `other` *might* happen). * This always recurses parents. */ append(other: Environment | undefined): Environment; remove(id: Identifier): this; removeAll(names: readonly { name: Identifier; }[]): Environment; toJSON(): Jsonified; } /** * An environment describes a ({@link IEnvironment#parent|scoped}) mapping of names to their definitions ({@link BuiltIns}). * * First, yes, R stores its environments differently, potentially even with another differentiation between * the `baseenv`, the `emptyenv`, and other default environments (see https://adv-r.hadley.nz/environments.html). * Yet, during the dataflow analysis, we want sometimes to know more (static {@link IdentifierDefinition|reference information}) * and sometimes know less (to be honest, we do not want that, * but statically determining all attached environments is theoretically impossible --- consider attachments by user input). * * One important environment is the {@link BuiltIns|BuiltInEnvironment} which contains the default definitions for R's built-in functions and constants. * This environment is created and provided by the {@link FlowrAnalyzerEnvironmentContext}. * During serialization, you may want to rely on the {@link builtInEnvJsonReplacer} to avoid the huge built-in environment. * @see {@link define} - to define a new {@link IdentifierDefinition|identifier definition} within an environment * @see {@link resolveByName} - 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 currently active {@link IEnvironment#parent}). Environments are maintained within the dataflow graph. */ readonly current: Environment; /** nesting level of the environment, will be `0` for the global/root environment */ readonly level: number; } /** * Helps to serialize an environment, but replaces the built-in environment with a placeholder. */ export declare function builtInEnvJsonReplacer(k: unknown, v: unknown): unknown; export {};