@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
262 lines (261 loc) • 11 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 } from '../info';
export declare enum VertexType {
Value = "value",
Use = "use",
FunctionCall = "function-call",
VariableDefinition = "variable-definition",
FunctionDefinition = "function-definition"
}
export declare const ValidVertexTypes: Set<string>;
export declare const ValidVertexTypeReverse: {
[k: string]: string;
};
/**
* Identifier for arguments e.g. for `3` in `c(2, 3, 5)` the identifier would be
* ```ts
* {
* index: 2
* }
* ```
*/
export interface UnnamedArgumentId {
readonly index: number;
}
/**
* Identifier for named arguments e.g. for `age` in `list(name = 'John', age = 8)`
* the indentifier would be
* ```ts
* {
* index: 2,
* lexeme: 'age'
* }
* ```
*/
export interface NamedArgumentId {
/**
* Index may be undefined, when no index information is available.
*/
readonly index: number | undefined;
readonly lexeme: string;
}
export declare function isNamedArgumentId(identifier: IndexIdentifier): identifier is NamedArgumentId;
export type IndexIdentifier = UnnamedArgumentId | NamedArgumentId;
/**
* A single index of a container, which is not a container itself.
*
* This can be e.g. a string, number or boolean index.
*/
export interface ContainerLeafIndex {
/**
* Distinctive identifier of index, see {@link IndexIdentifier}.
*/
readonly identifier: IndexIdentifier;
/**
* NodeId of index in graph.
*/
readonly nodeId: NodeId;
}
/**
* A single index of a container, which is a container itself.
*
* This can be, e.g., a list, vector, or data frame.
*
* @see {@link ContainerLeafIndex} - for a single index of a container which is not a container itself
* @see {@link isParentContainerIndex} - to check if an index is a parent container index
*/
export interface ContainerParentIndex extends ContainerLeafIndex {
/**
* Sub-indices of index.
*/
readonly subIndices: ContainerIndices[];
}
export declare function isParentContainerIndex(index: ContainerIndex): index is ContainerParentIndex;
/**
* A single index of a container.
*/
export type ContainerIndex = ContainerLeafIndex | ContainerParentIndex;
/**
* Checks whether {@link index} is accessed by {@link accessLexeme}.
*
* @param index - The {@link ContainerIndex}, which is accessed
* @param accessLexeme - The access lexeme
* @param isIndexBasedAccess - Whether the index of the {@link ContainerIndex} is accessed i.e. the position in the container and not e.g. the name of the index
* @returns true, when {@link accessLexeme} accesses the {@link index}, false otherwise
*/
export declare function isAccessed(index: ContainerIndex, accessLexeme: string, isIndexBasedAccess: boolean): boolean;
export declare function isSameIndex(a: ContainerIndex, b: ContainerIndex): boolean;
/**
* List of indices of a single statement like `list(a=3, b=2)`
*/
export interface ContainerIndices {
readonly indices: ContainerIndex[];
/**
* Differentiate between single and multiple indices.
*
* For `list(name = 'John')` `isContainer` would be true, because a list may define more than one index.
* `isContainer` is true for e.g. single index assignments like `person$name <- 'John'`.
*/
readonly isContainer: boolean;
}
/**
* Collection of Indices of several statements.
*/
export type ContainerIndicesCollection = ContainerIndices[] | undefined;
/**
* 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;
/**
* this attribute links a vertex to indices (pointer links) it may be affected by or related to
*/
indicesCollection?: ContainerIndicesCollection;
}
/**
* Marker vertex for a value in the dataflow of the program.
* This does not contain the _value_ of the referenced constant
* as this is available with the {@link DataflowGraphVertexBase#id|id} in the {@link NormalizedAst|normalized AST}
* (or more specifically the {@link AstIdMap}).
*
* If you have a {@link DataflowGraph|dataflow graph} named `graph`
* with an {@link AstIdMap} and a value vertex object with name `value` the following Code should work:
*
* @example
* ```ts
* const node = graph.idMap.get(value.id)
* ```
*
* This then returns the corresponding node in the {@link NormalizedAst|normalized AST}, for example,
* an {@link RNumber} or {@link RString}.
*
* This works similarly for {@link IdentifierReference|identifier references}
* for which you can use the {@link IdentifierReference#nodeId|`nodeId`}.
*
* @see {@link isValueVertex} - to check if a vertex is a value vertex
*/
export interface DataflowGraphVertexValue extends DataflowGraphVertexBase {
readonly tag: VertexType.Value;
readonly environment?: undefined;
}
/**
* Arguments required to construct a vertex which represents the usage of a variable in the {@link DataflowGraph|dataflow graph}.
*
* @see {@link isUseVertex} - 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 usage of a variable in the {@link DataflowGraph|dataflow graph}.
*
* @see {@link isFunctionCallVertex} - 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., `[<-`).
*/
readonly name: string;
/** The arguments of the function call, in order (as they are passed to the respective call if executed in R. */
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;
}
/**
* Arguments required to construct a vertex which represents the definition of a variable in the {@link DataflowGraph|dataflow graph}.
*
* @see {@link isVariableDefinitionVertex} - 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;
}
/**
* Arguments required to construct a vertex which represents the definition of a function in the {@link DataflowGraph|dataflow graph}.
*
* @see {@link isFunctionDefinitionVertex} - 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 NodeId[];
environment?: 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>;
/**
* Check if the given vertex is a {@link DataflowGraphVertexValue|value vertex}.
*/
export declare function isValueVertex(vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexValue;
/**
* Check if the given vertex is a {@link DataflowGraphVertexUse|use vertex}.
*/
export declare function isUseVertex(vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexUse;
/**
* Check if the given vertex is a {@link DataflowGraphVertexFunctionCall|function call vertex}.
*/
export declare function isFunctionCallVertex(vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexFunctionCall;
/**
* Check if the given vertex is a {@link DataflowGraphVertexVariableDefinition|variable definition vertex}.
*/
export declare function isVariableDefinitionVertex(vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexVariableDefinition;
/**
* Check if the given vertex is a {@link DataflowGraphVertexFunctionDefinition|function definition vertex}.
*/
export declare function isFunctionDefinitionVertex(vertex?: DataflowGraphVertexBase): vertex is DataflowGraphVertexFunctionDefinition;
export {};