@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
113 lines (112 loc) • 5.88 kB
TypeScript
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 {};