@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
81 lines (80 loc) • 3.63 kB
TypeScript
import type { MergeableRecord } from '../objects';
import type { QuadSerializationConfiguration } from '../quads';
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
import type { NormalizedAst, ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
import { RFalse, RTrue } from '../../r-bridge/lang-4.x/convert-values';
import type { DataflowGraph } from '../../dataflow/graph/graph';
export declare const enum CfgVertexType {
/** Marks a break point in a construct (e.g., between the name and the value of an argument, or the formals and the body of a function) */
MidMarker = "mid-marker",
/** The explicit exit-nodes to ensure the hammock property */
EndMarker = "end-marker",
/** something like an if, assignment, ... even though in the classical sense of R they are still expressions */
Statement = "statement",
/** something like an addition, ... */
Expression = "expression"
}
export interface CfgVertex {
id: NodeId;
type: CfgVertexType;
name: string;
/** in case of a function definition */
children?: NodeId[];
}
interface CfgFlowDependencyEdge extends MergeableRecord {
label: 'FD';
}
interface CfgControlDependencyEdge extends MergeableRecord {
label: 'CD';
/** the id which caused the control dependency */
caused: NodeId;
when: typeof RTrue | typeof RFalse;
}
export type CfgEdge = CfgFlowDependencyEdge | CfgControlDependencyEdge;
/**
* This class represents the control flow graph of an R program.
* The control flow may be hierarchical when confronted with function definitions (see {@link CfgVertex} and {@link CFG#rootVertexIds|rootVertexIds()}).
*/
export declare class ControlFlowGraph {
private rootVertices;
private vertexInformation;
private edgeInformation;
addVertex(vertex: CfgVertex, rootVertex?: boolean): this;
addEdge(from: NodeId, to: NodeId, edge: CfgEdge): this;
outgoing(node: NodeId): ReadonlyMap<NodeId, CfgEdge> | undefined;
rootVertexIds(): ReadonlySet<NodeId>;
vertices(): ReadonlyMap<NodeId, CfgVertex>;
edges(): ReadonlyMap<NodeId, ReadonlyMap<NodeId, CfgEdge>>;
merge(other: ControlFlowGraph, forceNested?: boolean): this;
}
export interface ControlFlowInformation extends MergeableRecord {
returns: NodeId[];
breaks: NodeId[];
nexts: NodeId[];
/** intended to construct a hammock graph, with 0 exit points representing a block that should not be part of the CFG (like a comment) */
entryPoints: NodeId[];
/** See {@link ControlFlowInformation#entryPoints|entryPoints} */
exitPoints: NodeId[];
graph: ControlFlowGraph;
}
export declare function emptyControlFlowInformation(): ControlFlowInformation;
/**
* Given a normalized AST this approximates the control flow graph of the program.
* This few is different from the computation of the dataflow graph and may differ,
* especially because it focuses on intra-procedural analysis.
*
* @param ast - the normalized AST
* @param graph - additional dataflow facts to consider by the control flow extraction
*/
export declare function extractCFG<Info = ParentInformation>(ast: NormalizedAst<Info>, graph?: DataflowGraph): ControlFlowInformation;
/**
* Returns true if the given CFG equals the other CFG. False otherwise.
*/
export declare function equalCfg(a: ControlFlowGraph | undefined, b: ControlFlowGraph | undefined): boolean;
/**
* @see df2quads
* @see serialize2quads
* @see graph2quads
*/
export declare function cfg2quads(cfg: ControlFlowInformation, config: QuadSerializationConfiguration): string;
export {};