UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

116 lines (115 loc) 6.7 kB
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; }