@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
116 lines (115 loc) • 6.7 kB
TypeScript
import type { ControlFlowInformation } from '../control-flow/control-flow-graph';
import { CfgVertex } from '../control-flow/control-flow-graph';
import type { SemanticCfgGuidedVisitorConfiguration } from '../control-flow/semantic-cfg-guided-visitor';
import { SemanticCfgGuidedVisitor } from '../control-flow/semantic-cfg-guided-visitor';
import type { DataflowGraph } from '../dataflow/graph/graph';
import { type DataflowGraphVertexFunctionCall, type DataflowGraphVertexVariableDefinition } from '../dataflow/graph/vertex';
import type { NoInfo, RNode } from '../r-bridge/lang-4.x/ast/model/model';
import type { NormalizedAst, ParentInformation } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
import { type AnyAbstractDomain } from './domains/abstract-domain';
import type { StateAbstractDomain } from './domains/state-abstract-domain';
import { MutableStateAbstractDomain } from './domains/state-abstract-domain';
import { BuiltInProcName } from '../dataflow/environments/built-in-proc-name';
export type AbsintVisitorConfiguration = Omit<SemanticCfgGuidedVisitorConfiguration<NoInfo, ControlFlowInformation, NormalizedAst>, 'defaultVisitingOrder' | 'defaultVisitingType'>;
/**
* A control flow graph visitor to perform abstract interpretation.
*
* However, the visitor does not yet support inter-procedural abstract interpretation and abstract condition semantics.
*/
export declare abstract class AbstractInterpretationVisitor<Domain extends AnyAbstractDomain, Config extends AbsintVisitorConfiguration = AbsintVisitorConfiguration> extends SemanticCfgGuidedVisitor<NoInfo, ControlFlowInformation, NormalizedAst, DataflowGraph, Config & {
defaultVisitingOrder: 'forward';
defaultVisitingType: 'exit';
}> {
/**
* The abstract trace of the abstract interpretation visitor mapping node IDs to the abstract state at the respective node.
*/
protected readonly trace: Map<NodeId, MutableStateAbstractDomain<Domain>>;
/**
* The current abstract state domain at the currently processed AST node.
*/
private _currentState;
/**
* A set of nodes representing variable definitions that have already been visited but whose assignment has not yet been processed.
*/
private readonly unassigned;
/**
* Whether the current abstract state has been copied/cloned and is save to modify in place.
*/
private stateCopied;
constructor(config: Config);
get currentState(): StateAbstractDomain<Domain>;
removeState(node: NodeId): void;
updateState(node: NodeId, value: Domain): void;
/**
* Resolves the inferred abstract value of an AST node.
* This requires that the abstract interpretation visitor has been completed, or at least started.
* @param id - The ID of the node to get the inferred value for
* @param state - An optional state abstract domain used to resolve the inferred abstract value (defaults to the state at the requested node)
* @returns The inferred abstract value of the node, or `undefined` if no value was inferred for the node
*/
getAbstractValue(id: RNode<ParentInformation> | NodeId | undefined, state?: StateAbstractDomain<Domain>): Domain | undefined;
/**
* Gets the inferred abstract state at the location of a specific AST node.
* This requires that the abstract interpretation visitor has been completed, or at least started.
* @param id - The ID of the node to get the abstract state at
* @returns The abstract state at the node, or `undefined` if the node has no abstract state (i.e. the node has not been visited or is unreachable).
*/
getAbstractState(id: NodeId | undefined): StateAbstractDomain<Domain> | undefined;
/**
* Gets the inferred abstract state at the end of the program (exit nodes of the control flow graph).
* This requires that the abstract interpretation visitor has been completed, or at least started.
* @returns The inferred abstract state at the end of the program
*/
getEndState(): StateAbstractDomain<Domain>;
/**
* Gets the inferred abstract trace mapping AST nodes to the inferred abstract state at the respective node.
* @returns The inferred abstract trace of the program
*/
getAbstractTrace(): ReadonlyMap<NodeId, StateAbstractDomain<Domain>>;
start(): void;
protected startVisitor(start: readonly NodeId[]): void;
protected visitNode(vertexId: NodeId): boolean;
protected onDispatchFunctionCallOrigin(call: DataflowGraphVertexFunctionCall, origin: BuiltInProcName): void;
protected onVariableDefinition({ vertex }: {
vertex: DataflowGraphVertexVariableDefinition;
}): void;
protected onAssignmentCall({ target, source }: {
call: DataflowGraphVertexFunctionCall;
target?: NodeId;
source?: NodeId;
}): void;
protected onReplacementCall({ target }: {
call: DataflowGraphVertexFunctionCall;
target?: NodeId;
source?: NodeId;
}): void;
/**
* This event triggers for every function call that is not a condition, loop, assignment, replacement call, or access operation.
*
*
* For example, this triggers for `data.frame` in `x <- data.frame(id = 1:5, name = letters[1:5])`.
*
* This bundles all function calls that are no conditions, loops, assignments, replacement calls, and access operations.
* @protected
*/
protected onFunctionCall(_data: {
call: DataflowGraphVertexFunctionCall;
}): void;
/** Gets all AST nodes for the predecessor vertices that are leaf nodes and exit vertices */
protected getPredecessorNodes(vertexId: NodeId): NodeId[];
/** Gets each variable origin that has already been visited and whose assignment has already been processed */
protected getVariableOrigins(nodeId: NodeId): NodeId[];
/** We only perform widening at `for`, `while`, or `repeat` loops with more than one ingoing CFG edge */
protected isWideningPoint(nodeId: NodeId): boolean;
/**
* Checks whether a control flow graph vertex should be skipped during visitation.
* By default, we only process entry vertices of widening points, vertices of leaf nodes, and exit vertices (no entry nodes of complex nodes).
*/
protected shouldSkipVertex(vertex: CfgVertex): boolean;
/**
* Whether widening should be performed at a widening point.
* By default, we perform widening when the number of visits of the widening point reaches the widening threshold of the config.
*/
protected shouldWiden(wideningPoint: CfgVertex): boolean;
}