@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
248 lines (247 loc) • 11.5 kB
TypeScript
import type { MergeableRecord } from '../../util/objects';
import type { DataflowFunctionFlowInformation, FunctionArgument } from './graph';
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
import type { REnvironmentInformation } from '../environments/environment';
import type { ControlDependency, ExitPoint } from '../info';
import type { Identifier } from '../environments/identifier';
import type { BuiltInProcName } from '../environments/built-in-proc-name';
import type { Value } from '../eval/values/r-value';
export declare enum VertexType {
Value = "value",
Use = "use",
FunctionCall = "fcall",
VariableDefinition = "vdef",
FunctionDefinition = "fdef"
}
export declare const ValidVertexTypes: Set<string>;
export declare const ValidVertexTypeReverse: {
[k: string]: string;
};
/**
* Arguments required to construct a vertex in the {@link DataflowGraph|dataflow graph}.
* @see DataflowGraphVertexUse
* @see DataflowGraphVertexVariableDefinition
* @see DataflowGraphVertexFunctionDefinition
*/
interface DataflowGraphVertexBase extends MergeableRecord {
/**
* Used to identify and separate different types of vertices.
*/
readonly tag: VertexType;
/**
* The id of the node (the id assigned by the {@link ParentInformation} decoration).
* This unanimously identifies the vertex in the {@link DataflowGraph|dataflow graph}
* as well as the corresponding {@link NormalizedAst|normalized AST}.
*/
id: NodeId;
/**
* The environment in which the vertex is set.
*/
environment?: REnvironmentInformation;
/**
* @see {@link ControlDependency} - the collection of control dependencies which have an influence on whether the vertex is executed.
*/
cds: ControlDependency[] | undefined;
/**
* Describes the collection of AST vertices that contributed to this vertex.
* For example, this is useful with replacement operators, telling you which assignment operator caused them
*/
link?: DataflowGraphVertexAstLink;
}
export interface DataflowGraphVertexAstLink {
origin: NodeId[];
}
/**
* Marker vertex for a value in the dataflow of the program.
* For user-code constants (numbers, strings, logicals) the value is recovered by looking up the
* {@link DataflowGraphVertexBase#id|id} in the {@link NormalizedAst|normalized AST}:
* @example
* ```ts
* const node = graph.idMap.get(value.id)
* ```
*
* For built-in constants whose id is not in the {@link AstIdMap} (e.g. `T` resolving to `built-in:T`),
* the abstract {@link Value} is stored directly in the {@link DataflowGraphVertexValue#value|value} field.
* @see {@link ValueVertex.is} - to check if a vertex is a value vertex
*/
export interface DataflowGraphVertexValue extends DataflowGraphVertexBase {
readonly tag: VertexType.Value;
readonly environment?: undefined;
/** Pre-computed abstract value; set for built-in constants (e.g. `T`, `F`) whose id is not in the AST id map */
readonly value?: Value;
}
/**
* Arguments required to construct a vertex which represents the usage of a variable in the {@link DataflowGraph|dataflow graph}.
* @see {@link UseVertex.is} - to check if a vertex is a use vertex
*/
export interface DataflowGraphVertexUse extends DataflowGraphVertexBase {
readonly tag: VertexType.Use;
/** Does not require an environment to be attached. If we promote the use to a function call, we attach the environment later. */
readonly environment?: undefined;
}
/**
* Arguments required to construct a vertex which represents the call to a function in the {@link DataflowGraph|dataflow graph}.
* This describes all kinds of function calls, including calls to built-ins and control-flow structures such as `if` or `for` (they are
* treated as function calls in R).
* @see {@link FunctionCallVertex.is} - to check if a vertex is a function call vertex
*/
export interface DataflowGraphVertexFunctionCall extends DataflowGraphVertexBase {
readonly tag: VertexType.FunctionCall;
/**
* Effective name of the function call,
* Please be aware that this name can differ from the lexeme.
* For example, if the function is a replacement function, in this case, the actually called fn will
* have the compound name (e.g., `[<-`).
* @see {@link Identifier} - for more information on identifiers
*/
readonly name: Identifier;
/**
* The arguments of the function call, in order (as they are passed to the respective call if executed in R.
* @see {@link FunctionArgument} - for more information on function arguments
*/
args: FunctionArgument[];
/** a performance flag to indicate that the respective call is _only_ calling a builtin function without any df graph attached */
onlyBuiltin: boolean;
/** The environment attached to the call (if such an attachment is necessary, e.g., because it represents the calling closure */
environment: REnvironmentInformation | undefined;
/** More detailed Information on this function call */
origin: FunctionOriginInformation[] | 'unnamed';
/**
* For `new.env()`-family calls: the resolved parent {@link REnvironmentInformation} that the
* freshly-created environment should inherit from. Set by `processNewEnv` when the `parent`
* argument can be statically resolved (tracked env variable or `emptyenv()`-family call).
*/
newEnvParent?: REnvironmentInformation;
}
/** Describes the processor responsible for a function call */
export type FunctionOriginInformation = BuiltInProcName;
/**
* Arguments required to construct a vertex which represents the definition of a variable in the {@link DataflowGraph|dataflow graph}.
* @see {@link VariableDefinitionVertex.is} - to check if a vertex is a variable definition vertex
*/
export interface DataflowGraphVertexVariableDefinition extends DataflowGraphVertexBase {
readonly tag: VertexType.VariableDefinition;
/** Does not require an environment, those are attached to the call */
readonly environment?: undefined;
/** Indicates whether the variable definition is a *partial* definition (e.g,. in `x[a] <- b`) */
readonly par?: true;
/** Points to the source ids of the "value" if there is one, this is more of a best-effort flag and not guaranteed to be there */
readonly source?: readonly NodeId[];
}
/**
* Arguments required to construct a vertex which represents the definition of a function in the {@link DataflowGraph|dataflow graph}.
* @see {@link FunctionDefinitionVertex.is} - to check if a vertex is a function definition vertex
*/
export interface DataflowGraphVertexFunctionDefinition extends DataflowGraphVertexBase {
readonly tag: VertexType.FunctionDefinition;
/**
* The static subflow of the function definition, constructed within {@link processFunctionDefinition}.
* If the vertex is (for example) a function, it can have a subgraph which is used as a template for each call.
* This is the `body` of the function.
*/
subflow: DataflowFunctionFlowInformation;
/**
* All exit points of the function definitions.
* In other words: last expressions/return calls
*/
exitPoints: readonly ExitPoint[];
/** Maps each param to whether it is read, this is an estimate! */
params: Record<NodeId, boolean>;
/** The environment in which the function is defined (this is only attached if the DFG deems it necessary). */
environment?: REnvironmentInformation;
/**
* If the function is a (potential) S3/S4/S7 dispatch
* Please note that flowR may create these flags *on use* (e.g. `s3` as otherwise any func with a `.` would be considered S3).
* This is more of a convenience flag for later processing.
*/
mode?: ('s3' | 's4' | 's7')[];
/**
* If this function statically returns a tracked environment, stores the envState it returns.
* Set by `processFunctionDefinition` when exit points include NewEnv calls or symbols resolving to tracked envs.
*/
returnEnvState?: REnvironmentInformation;
}
/**
* What is to be passed to construct a vertex in the {@link DataflowGraph|dataflow graph}
*/
export type DataflowGraphVertexArgument = DataflowGraphVertexUse | DataflowGraphVertexVariableDefinition | DataflowGraphVertexFunctionDefinition | DataflowGraphVertexFunctionCall | DataflowGraphVertexValue;
/**
* This is the union type of all possible vertices that appear within a {@link DataflowGraph|dataflow graph},
* they can be constructed passing a {@link DataflowGraphVertexArgument} to the graph.
*
* See {@link DataflowGraphVertices} for an id-based mapping.
*/
export type DataflowGraphVertexInfo = Required<DataflowGraphVertexArgument>;
/**
* A mapping of {@link NodeId}s to {@link DataflowGraphVertexInfo|vertices}.
*/
export type DataflowGraphVertices<Vertex extends DataflowGraphVertexInfo = DataflowGraphVertexInfo> = Map<NodeId, Vertex>;
/**
* Helpers for {@link DataflowGraphVertexValue} vertices.
* @example
* ```ts
* ValueVertex.is(graph.getVertex(id)) // true for a constant like `42`
* ```
*/
export declare const ValueVertex: {
name: string;
/** Whether the given vertex is a value vertex. */
is(this: void, vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexValue;
};
/**
* Helpers for {@link DataflowGraphVertexUse} vertices.
* @example
* ```ts
* UseVertex.is(graph.getVertex(id)) // true for a read of `x`
* ```
*/
export declare const UseVertex: {
name: string;
/** Whether the given vertex is a use vertex. */
is(this: void, vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexUse;
};
/**
* Helpers for {@link DataflowGraphVertexFunctionCall} vertices.
* @example
* ```ts
* const vertex = graph.getVertex(id);
* FunctionCallVertex.is(vertex) && vertex.name // the call's effective name
* FunctionCallVertex.hasOrigin(vertex, 'builtin:eval') // the call is an eval
* ```
*/
export declare const FunctionCallVertex: {
name: string;
/** Whether the given vertex is a function call vertex. */
is(this: void, vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexFunctionCall;
/**
* Whether the given vertex is a function call carrying the given origin.
* Deliberately not a type predicate: a `false` says nothing about the tag, the call may simply carry another origin.
*/
hasOrigin(this: void, vertex: DataflowGraphVertexBase | undefined, origin: BuiltInProcName): boolean;
};
/**
* Helpers for {@link DataflowGraphVertexVariableDefinition} vertices.
* @example
* ```ts
* VariableDefinitionVertex.is(graph.getVertex(id)) // true for the `x` of `x <- 1`
* ```
*/
export declare const VariableDefinitionVertex: {
name: string;
/** Whether the given vertex is a variable definition vertex. */
is(this: void, vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexVariableDefinition;
};
/**
* Helpers for {@link DataflowGraphVertexFunctionDefinition} vertices.
* @example
* ```ts
* const vertex = graph.getVertex(id);
* FunctionDefinitionVertex.is(vertex) && vertex.exitPoints // where the body returns
* ```
*/
export declare const FunctionDefinitionVertex: {
name: string;
/** Whether the given vertex is a function definition vertex. */
is(this: void, vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexFunctionDefinition;
};
export {};