@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
559 lines (558 loc) • 34.3 kB
TypeScript
import { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
import type { MergeableRecord } from '../util/objects';
import { RFalse, RTrue } from '../r-bridge/lang-4.x/convert-values';
/**
* The type of a vertex in the {@link ControlFlowGraph}.
* Please use the helper object (e.g. {@link CfgVertex#getType|getType()}) to work with vertices instead of directly accessing the properties.
*/
export declare enum CfgVertexType {
/**
* The explicit exit-nodes to ensure the hammock property.
* @see {@link CfgVertex.makeMarker|CfgVertex.makeMarker()} - for a helper function to create end marker vertices
*/
Marker = 0,
/**
* something like an if, assignment, ... even though in the classical sense of R they are still expressions
* @see {@link CfgVertex.makeStatement|CfgVertex.makeStatement()} - for a helper function to create statement vertices
*/
Statement = 1,
/**
* something like an addition, ...
* @see {@link CfgVertex.makeExpression|CfgVertex.makeExpression()} - for a helper function to create expression vertices
*/
Expression = 2,
/**
* a (as far as R allows this) 'basic' block
* @see {@link CfgVertex.makeBlock|CfgVertex.makeBlock()} - for a helper function to create basic block vertices
*/
Block = 3
}
export declare const enum CfgEdgeType {
/** a flow dependency */
Fd = 0,
/** a control dependency */
Cd = 1
}
/**
* A vertex in the {@link ControlFlowGraph} that may have markers attached to it (e.g., for function calls).
* - `type`: the type of the vertex, either a statement or an expression
* - `id`: the id of the vertex, which should directly relate to the AST node
* - `children`: child nodes attached to this one
* - `callTargets`: if the vertex calls a function, this links all targets of this call
*/
type CfgBaseVertexWithMarker = [type: CfgVertexType, id: NodeId, mid?: NodeId[], end?: NodeId[], children?: NodeId[], callTargets?: Set<NodeId>];
/**
* @see {@link CfgBaseVertexWithMarker}
*/
export type CfgStatementVertex = [CfgVertexType.Statement, ...a: unknown[]] & CfgBaseVertexWithMarker;
/**
* @see {@link CfgBaseVertexWithMarker}
*/
export type CfgExpressionVertex = [CfgVertexType.Expression, ...a: unknown[]] & CfgBaseVertexWithMarker;
/**
* The root id is only stored if it is not derivable from the canonical id
* @see {@link CfgBaseVertexWithMarker}
*/
export type CfgMarkerVertex = NodeId | [CfgVertexType.Marker, ...a: unknown[]] & [type: CfgVertexType, id: NodeId, rootId?: NodeId];
/**
* A basic block vertex in the {@link ControlFlowGraph}.
* Contains the vertices that are part of this block, only connected by FDs, vertices should never occur in multiple bbs.
*/
export type CfgBasicBlockVertex = [CfgVertexType.Block, ...a: unknown[]] & [type: CfgVertexType, id: NodeId, elems: readonly Exclude<CfgVertex, CfgBasicBlockVertex>[]];
/**
* A vertex in the {@link ControlFlowGraph}.
* Please use the helper object (e.g. {@link CfgVertex#getType|getType()}) to work with vertices instead of directly accessing the properties.
*/
export type CfgVertex = CfgStatementVertex | CfgExpressionVertex | CfgBasicBlockVertex | CfgMarkerVertex;
/**
* Helper object for {@link CfgVertex} - a vertex in the {@link ControlFlowGraph} that may have markers attached to it (e.g., for function calls).
*/
export declare const CfgVertex: {
/**
* Create a new expression vertex with the given id, children, call targets, and markers.
* @param id - the id of the vertex, which should directly relate to the AST node
* @param children - child nodes attached to this one
* @param callTargets - if the vertex calls a function, this links all targets of this call
* @param mid - the ids of the mid-markers attached to this vertex, which should directly relate to the AST nodes of the mid markers
* @param end - the ids of the end-markers attached to this vertex, which should directly relate to the AST nodes of the end markers
* @see {@link CfgVertex#isExpression|isExpression()} - for a way to check whether a vertex is an expression vertex
*/
readonly makeExpression: (this: void, id: NodeId, { children, mid, end, callTargets }?: {
children?: NodeId[];
callTargets?: Set<NodeId>;
mid?: NodeId[];
end?: NodeId[];
}) => CfgExpressionVertex;
/**
* A convenience function to create a new expression vertex with a canonical end marker ({@link CfgVertex#toExitId|toExitId()}) based on the given id and the given id as root id for the end marker.
* @param id - the id of the vertex, which should directly relate to the AST node
* @param children - child nodes attached to this one
* @param callTargets - if the vertex calls a function, this links all targets of this call
* @param mid - the ids of the mid-markers attached to this vertex, which should directly relate to the AST nodes of the mid markers
* @see {@link CfgVertex#makeExpression|makeExpression()} - for a way to create expression vertices with a custom end marker
* @see {@link CfgVertex#makeExitMarker|makeExitMarker()} - for a helper function to create end marker vertices with a canonical id#
* @see {@link CfgVertex#toExitId|toExitId()} - for a way to convert the given id to a canonical end marker id
*/
readonly makeExpressionWithEnd: (this: void, id: NodeId, { children, mid, callTargets }?: {
children?: NodeId[];
callTargets?: Set<NodeId>;
mid?: NodeId[];
}) => CfgExpressionVertex;
/**
* A convenience function to create a new statement vertex with a canonical end marker ({@link CfgVertex#toExitId|toExitId()}) based on the given id and the given id as root id for the end marker.
* @param id - the id of the vertex, which should directly relate to the AST node
* @param children - child nodes attached to this one
* @param callTargets - if the vertex calls a function, this links all targets of this call
* @param mid - the ids of the mid-markers attached to this vertex, which should directly relate to the AST nodes of the mid markers
* @see {@link CfgVertex#makeExpression|makeExpression()} - for a way to create expression vertices with a custom end marker
* @see {@link CfgVertex#makeExitMarker|makeExitMarker()} - for a helper function to create end marker vertices with a canonical id#
* @see {@link CfgVertex#toExitId|toExitId()} - for a way to convert the given id to a canonical end marker id
*/
readonly makeStatementWithEnd: (this: void, id: NodeId, { children, mid, callTargets }?: {
children?: NodeId[];
callTargets?: Set<NodeId>;
mid?: NodeId[];
}) => CfgStatementVertex;
/**
* Create a new statement vertex with the given id, children, call targets, and markers.
* @param id - the id of the vertex, which should directly relate to the AST node
* @param children - child nodes attached to this one
* @param callTargets - if the vertex calls a function, this links all targets of this call
* @param mid - the ids of the mid-markers attached to this vertex, which should directly relate to the AST nodes of the mid markers
* @param end - the ids of the end-markers attached to this vertex, which should directly relate to the AST nodes of the end markers
* @see {@link CfgVertex#isStatement|isStatement()} - for a way to check whether a vertex is a statement vertex
*/
readonly makeStatement: (this: void, id: NodeId, { children, mid, end, callTargets }?: {
children?: NodeId[];
callTargets?: Set<NodeId>;
mid?: NodeId[];
end?: NodeId[];
}) => CfgStatementVertex;
/**
* A convenience function to create a new vertex which is either a statement or an expression.
*/
readonly makeExprOrStm: (this: void, id: NodeId, type: CfgVertexType.Expression | CfgVertexType.Statement, { children, mid, end, callTargets }?: {
children?: NodeId[];
callTargets?: Set<NodeId>;
mid?: NodeId[];
end?: NodeId[];
}) => CfgExpressionVertex | CfgStatementVertex;
/**
* Create a new marker vertex with the given id, root id, children, and call targets.
* @param id - the id of the vertex, which should directly relate to the AST node
* @param rootId - the id of the AST node this end marker corresponds to
* @see {@link CfgVertex#isMarker|isMarker()} - for a way to check whether a vertex is an end marker vertex
* @see {@link CfgVertex#getRootId|getRootId()} - for a way to get the root id of an end marker vertex
* @see {@link CfgVertex#makeExitMarker|makeExitMarker()} - for a helper function to create end marker vertices with a canonical id
*/
readonly makeMarker: (this: void, id: NodeId, rootId: NodeId) => CfgMarkerVertex;
/**
* A convenience function to create a new marker vertex with a canonical id ({@link CfgVertex#toExitId|toExitId()}) based on the given id and the given id as root id.
* @see {@link CfgVertex#makeMarker|makeMarker()} - for a way to create end marker vertices with a custom id
*/
readonly makeExitMarker: (this: void, id: NodeId) => CfgMarkerVertex;
/**
* Create a new basic block vertex with the given id, elements, children, and call targets.
* @param id - the id of the vertex, which should directly relate to the AST node
* @param elems - the vertices that are part of this block, only connected by FDs, vertices should never occur in multiple bbs
* @see {@link CfgVertex#isBlock|isBlock()} - for a way to check whether a vertex is a basic block vertex
*/
readonly makeBlock: (this: void, id: NodeId, elems: readonly Exclude<CfgVertex, CfgBasicBlockVertex>[]) => CfgBasicBlockVertex;
/**
* Check whether the given vertex is an expression vertex.
* @see {@link CfgVertex#makeExpression|makeExpression()} - for a way to create expression vertices
* @see {@link CfgVertex#getType|getType()} - for a way to get the type of a vertex instead of checking against a given type
*/
readonly isExpression: (this: void, vertex: CfgVertex | undefined) => vertex is CfgExpressionVertex;
/**
* Check whether the given vertex is a statement vertex.
* @see {@link CfgVertex#makeStatement|makeStatement()} - for a way to create statement vertices
* @see {@link CfgVertex#getType|getType()} - for a way to get the type of a vertex instead of checking against a given type
*/
readonly isStatement: (this: void, vertex: CfgVertex | undefined) => vertex is CfgStatementVertex;
/**
* Check whether the given vertex is an end marker vertex.
* @see {@link CfgVertex#makeMarker|makeMarker()} - for a way to create end marker vertices
* @see {@link CfgVertex#getType|getType()} - for a way to get the type of a vertex instead of checking against a given type
*/
readonly isMarker: (this: void, vertex: CfgVertex | undefined) => vertex is CfgMarkerVertex;
/**
* Check whether the given vertex is a basic block vertex.
* @see {@link CfgVertex#makeBlock|makeBlock()} - for a way to create basic block vertices
* @see {@link CfgVertex#getType|getType()} - for a way to get the type of a vertex instead of checking against a given type
*/
readonly isBlock: (this: void, vertex: CfgVertex | undefined) => vertex is CfgBasicBlockVertex;
/**
* Get the type of the given vertex.
* @example
* ```ts
* const vertex: CfgVertex = CfgVertex.makeExpr('node-1')
* console.log(CfgVertex.getType(vertex)); // Output: CfgVertexType.Expression
* ```
* @see {@link CfgVertex#isExpression|isExpression()}, {@link CfgVertex#isStatement|isStatement()}, {@link CfgVertex#isMarker|isMarker()}, {@link CfgVertex#isBlock|isBlock()} - for ways to check the type of a vertex against a specific type instead of getting the type and checking it against a specific type
* @see {@link CfgVertex#getId|getId()} - for a way to get the id of a vertex
* @see {@link CfgVertex#typeToString|typeToString()} - for a way to convert the type of a vertex to a string for easier debugging and visualization
*/
readonly getType: (this: void, vertex: CfgVertex) => CfgVertexType;
/**
* Convert the given vertex type to a string for easier debugging and visualization.
* @see {@link CfgVertexType} - for the possible vertex types
* @see {@link CfgVertex#getType|getType()} - for a way to get the type of a vertex and convert it to a string
*/
readonly typeToString: (this: void, type: CfgVertexType) => string;
/**
* Get the id of the given vertex, which should directly relate to the AST node.
* @example
* ```ts
* const vertex: CfgVertex = CfgVertex.makeExpr('node-1')
* console.log(CfgVertex.getId(vertex)); // Output: 'node-1'
* ```
* @see {@link CfgVertex#getType|getType()} - for a way to get the type of a vertex
* @see {@link CfgVertex#getRootId|getRootId()} - for a way to get the root id of a vertex
*/
readonly getId: <T extends CfgVertex | undefined>(this: void, vertex: T) => T extends undefined ? NodeId | undefined : NodeId;
/**
* Check whether two vertices are equal, i.e., they have the same type, id, and if they are basic block vertices, they also have the same elements in the same order.
*/
readonly equal: (this: void, a: CfgVertex, b: CfgVertex) => boolean;
/**
* Get the root id of a vertex, i.e., the id of the AST node it corresponds to.
* For normal vertices, this is the same as the id of the vertex itself, for end marker vertices, this is the root id stored in the vertex.
* @see {@link CfgVertex#unpackRoot|unpackRoot()} - for a way to unpack the root id of a marker vertex
*/
readonly getRootId: (this: void, vertex: CfgVertex) => NodeId;
/**
* Unpack the root id of a marker vertex, i.e., get the root id stored in the vertex or derive it from the canonical id if it is not explicitly stored.
* @see {@link CfgVertex#getRootId|getRootId()} - for a way to get the root id of a vertex, which uses this function for marker vertices
*/
readonly unpackRootId: (this: void, vertex: CfgMarkerVertex) => NodeId;
/**
* Get the elements of a basic block vertex, i.e., the vertices that are part of this block, only connected by FDs, vertices should never occur in multiple bbs.
* @see {@link CfgVertex#isBlock|isBlock()} - for a way to check whether a vertex is a basic block vertex before trying to get the elements
* @see {@link CfgVertex#setBasicBlockElements|setBasicBlockElements()} - for a way to set the elements of a basic block vertex
*/
readonly getBasicBlockElements: (this: void, vertex: CfgBasicBlockVertex) => readonly Exclude<CfgVertex, CfgBasicBlockVertex>[];
/**
* **Sets in-place**
* Set the elements of a basic block vertex, i.e., the vertices that are part of this block, only connected by FDs, vertices should never occur in multiple bbs.
* @see {@link CfgVertex#isBlock|isBlock()} - for a way to check whether a vertex is a basic block vertex before trying to set the elements
* @see {@link CfgVertex#getBasicBlockElements|getBasicBlockElements()} - for a way to get the elements of a basic block vertex
*/
readonly setBasicBlockElements: (this: void, vertex: CfgBasicBlockVertex, elems: readonly Exclude<CfgVertex, CfgBasicBlockVertex>[]) => void;
/**
* Get the ids of the mid-markers attached to this vertex, which should directly relate to the AST nodes of the mid markers.
* @see {@link CfgVertex#getMid|getMid()} - for a way to get the ids of the mid-markers attached to this vertex
* @see {@link CfgVertex#setEnd|setEnd()} - for a way to set the ids of the end-markers attached to this vertex
*/
readonly getEnd: (this: void, vertex: CfgVertex | undefined) => NodeId[] | undefined;
/**
* **Sets in-place**
* Set the ids of the end-markers attached to this vertex, which should directly relate to the AST nodes of the end markers.
* @see {@link CfgVertex#getEnd|getEnd()} - for a way to get the ids of the end-markers attached to this vertex
*/
readonly setEnd: (this: void, vertex: CfgStatementVertex | CfgExpressionVertex, endMarkers: NodeId[] | undefined) => void;
/**
* Get the ids of the mid-markers attached to this vertex, which should directly relate to the AST nodes of the mid markers.
*/
readonly getMid: (this: void, vertex: CfgVertex) => NodeId[] | undefined;
/**
* **Sets in-place**
* Set the ids of the mid-markers attached to this vertex, which should directly relate to the AST nodes of the mid markers.
* @see {@link CfgVertex#getMid|getMid()} - for a way to get the ids of the mid-markers attached to this vertex
* @see {@link CfgVertex#setEnd|setEnd()} - for a way to set the ids of the end-markers attached to this vertex
*/
readonly setMid: (this: void, vertex: CfgStatementVertex | CfgExpressionVertex, midMarkers: NodeId[] | undefined) => void;
/**
* Converts the given id to a, canonical, basic block lift (i.e., it adds 'bb-' as a prefix).
*/
readonly toBasicBlockId: <Id extends NodeId>(this: void, id: Id) => `bb-${Id}`;
/**
* Converts the given id to a canonical, end marker lift (i.e., it adds '-end' as a suffix).
* @see {@link CfgVertex#fromExitId|fromExitId()} - for a way to convert the given id from a canonical end marker lift to the original id (i.e., it removes '-end' as a suffix if it is present)
*/
readonly toExitId: <Id extends NodeId>(this: void, id: Id) => `${Id}-e`;
/**
* Converts the given id from a canonical end marker lift to the original id (i.e., it removes '-end' as a suffix if it is present).
* @see {@link CfgVertex#toExitId|toExitId()} - for a way to convert the given id to a canonical end marker lift (i.e., it adds '-end' as a suffix)
*/
readonly fromExitId: (this: void, exitId: NodeId) => NodeId;
/**
* Get the call targets of a statement or expression vertex, which links all targets of this call.
*/
readonly getCallTargets: (this: void, vertex: CfgVertex | undefined) => Set<NodeId> | undefined;
/**
* **Sets in-place**
* Set the call targets of a statement or expression vertex, which links all targets of this call.
* @see {@link CfgVertex#getCallTargets|getCallTargets()} - for a way to get the call targets of a statement or expression vertex
* @see {@link CfgVertex#mapCallTargets|mapCallTargets()} - for a way to map the call targets of a statement or expression vertex to new call targets
*/
readonly setCallTargets: (this: void, vertex: CfgStatementVertex | CfgExpressionVertex, callTargets: Set<NodeId>) => void;
/**
* Map the call targets of a statement or expression vertex, which links all targets of this call, to new call targets using the given mapping function.
* @see {@link CfgVertex#getCallTargets|getCallTargets()} - for a way to get the call targets of a statement or expression vertex
* @see {@link CfgVertex#setCallTargets|setCallTargets()} - for a way to set the call targets of a statement or expression vertex to new call targets
*/
readonly mapCallTargets: (this: void, vertex: CfgStatementVertex | CfgExpressionVertex, mapFn: (targets: Set<NodeId> | undefined) => Set<NodeId>) => void;
/**
* Get the children of a statement or expression vertex, i.e., the child nodes attached to this one.
*/
readonly getChildren: (this: void, vertex: CfgVertex | undefined) => NodeId[] | undefined;
};
type CfgFlowDependencyEdge = CfgEdgeType.Fd;
type CfgControlDependencyEdge = [c: NodeId, w: typeof RTrue | typeof RFalse];
/**
* An edge in the {@link ControlFlowGraph}.
* @see {@link CfgEdge} - for helper functions to work with edges.
*/
export type CfgEdge = CfgFlowDependencyEdge | CfgControlDependencyEdge;
/**
* Helper object for {@link CfgEdge} - an edge in the {@link ControlFlowGraph}.
*/
export declare const CfgEdge: {
/**
* Check whether the given edge is a flow dependency edge.
*/
readonly isFlowDependency: (this: void, edge: CfgEdge | undefined) => edge is CfgFlowDependencyEdge;
/**
* Check whether the given edge is a control dependency edge.
*/
readonly isControlDependency: (this: void, edge: CfgEdge | undefined) => edge is CfgControlDependencyEdge;
/**
* Create a flow dependency edge.
*/
readonly makeFd: (this: void) => CfgFlowDependencyEdge;
/**
* Create a control dependency edge with the given cause and condition.
* @param controlId - the id of the vertex that causes the control dependency
* @param whenTrue - whether the control dependency is satisfied with a true condition or is it negated (e.g., else-branch)
* @see {@link CfgEdge#makeCdTrue|makeCdTrue()} - for a version of this function that assumes the control dependency is satisfied with a true condition
* @see {@link CfgEdge#makeCdFalse|makeCdFalse()} - for a version of this function that assumes the control dependency is negated (e.g., else-branch)
*/
readonly makeCd: (this: void, controlId: NodeId, whenTrue: typeof RTrue | typeof RFalse) => CfgControlDependencyEdge;
/**
* Create a control dependency edge with the given cause and a true condition.
* @param controlId - the id of the vertex that causes the control dependency
* @see {@link CfgEdge#makeCd|makeCd()} - for a version of this function that allows to specify the condition as well
*/
readonly makeCdTrue: (this: void, controlId: NodeId) => CfgControlDependencyEdge;
/**
* Create a control dependency edge with the given cause and a negated condition (e.g., else-branch).
* @param controlId - the id of the vertex that causes the control dependency
* @see {@link CfgEdge#makeCd|makeCd()} - for a version of this function that allows to specify the condition as well
*/
readonly makeCdFalse: (this: void, controlId: NodeId) => CfgControlDependencyEdge;
/**
* Get the cause of a control dependency edge, i.e., the id of the vertex that causes the control dependency.
* If the edge is not a control dependency edge, this returns undefined.
*
* This is the pendant of {@link CfgEdge#isControlDependency|isControlDependency()} on a {@link CfgEdge}.
* @see {@link CfgEdge#unpackCause|unpackCause()} - for a version of this function that assumes the edge is a control dependency edge and hence does not return undefined
*/
readonly getCause: (this: void, edge: CfgEdge) => NodeId | undefined;
/**
* Get the cause of a control dependency edge, i.e., the id of the vertex that causes the control dependency.
*/
readonly unpackCause: (this: void, edge: CfgControlDependencyEdge) => NodeId;
/**
* Get whether the control dependency edge is satisfied with a true condition or is it negated (e.g., else-branch).
* If the edge is not a control dependency edge, this returns undefined.
*
* This is the pendant of {@link CfgEdge#isControlDependency|isControlDependency()} on a {@link CfgEdge}.
* @see {@link CfgEdge#unpackWhen|unpackWhen()} - for a version of this function that assumes the edge is a control dependency edge and hence does not return undefined
*/
readonly getWhen: (this: void, edge: CfgEdge) => typeof RTrue | typeof RFalse | undefined;
/**
* Get whether the control dependency edge is satisfied with a true condition or is it negated (e.g., else-branch).
*/
readonly unpackWhen: (this: void, edge: CfgControlDependencyEdge) => typeof RTrue | typeof RFalse;
/**
* Check whether two edges are equal.
*/
readonly equals: (this: void, a: CfgEdge, b: CfgEdge) => boolean;
/**
* Check whether the given edge is of the given type.
* @see {@link CfgEdge#getType|getType()} - for a version of this function that returns the type of the edge instead of checking against a given type
*/
readonly isOfType: (this: void, edge: CfgEdge, type: CfgEdgeType) => boolean;
/**
* Get the type of the given edge.
* @see {@link CfgEdge#isOfType|isOfType()} - for a version of this function that checks whether the edge is of a given type
*/
readonly getType: (this: void, edge: CfgEdge) => CfgEdgeType;
/**
* Provide a string representation of the given edge, e.g., for debugging or visualization purposes.
* @see {@link CfgEdge#toString|toString()} - for a version of this function that also includes the details of the edge (e.g., cause and condition for control dependency edges)
*/
readonly typeToString: (this: void, edge: CfgEdge) => string;
/**
* Provide a string representation of the given edge, including its details (e.g., cause and condition for control dependency edges), e.g., for debugging or visualization purposes.
* @see {@link CfgEdge#typeToString|typeToString()} - for a version of this function that only includes the type of the edge
*/
readonly toString: (this: void, edge: CfgEdge) => string;
};
/**
* A read-only view of the {@link ControlFlowGraph}.
*/
export interface ReadOnlyControlFlowGraph {
/**
* Get all ids of the root vertices — vertices that are not part of
* any function definition or basic block and hence part of the "top-level" control flow.
*
* This is the pendant of {@link DataflowGraph#rootIds|rootIds()} on a {@link DataflowGraph}.
* @see {@link ReadOnlyControlFlowGraph#vertices|vertices()} - for a way to get all vertices in the graph.
* @see {@link ReadOnlyControlFlowGraph#getVertex|getVertex()} - for a way to get a specific vertex by its id.
* @see {@link ReadOnlyControlFlowGraph#edges|edges()} - for a way to get all edges in the graph.
*/
readonly rootIds: () => ReadonlySet<NodeId>;
/**
* Provide a view of all vertices in the graph.
* @param includeBasicBlockElements - if true, the elements of basic block elements are included in the result, otherwise only the basic blocks themselves are included
* @see {@link ReadOnlyControlFlowGraph#rootVertexIds|rootVertexIds()} - for a way to get the root vertices of the graph.
* @see {@link ReadOnlyControlFlowGraph#getVertex|getVertex()} - for a way to get a specific vertex by its id.
* @see {@link ReadOnlyControlFlowGraph#edges|edges()} - for a way to get all edges in the graph.
*/
readonly vertices: (includeBasicBlockElements: boolean) => ReadonlyMap<NodeId, CfgVertex>;
/**
* Get all edges in the graph, independent of their sources and targets.
* If you are only interested in the edges of a specific node, please use {@link ReadOnlyControlFlowGraph#outgoingEdges|outgoingEdges()} or {@link ReadOnlyControlFlowGraph#ingoingEdges|ingoingEdges()}.
*
* This is the pendant of {@link DataflowGraph#edges|edges()} on a {@link DataflowGraph}.
*/
readonly edges: () => ReadonlyMap<NodeId, ReadonlyMap<NodeId, CfgEdge>>;
/**
* Receive all outgoing edges of a given vertex.
*
* This is the pendant of {@link DataflowGraph#ingoingEdges|ingoingEdges()} on a {@link DataflowGraph}.
* @see {@link ReadOnlyControlFlowGraph#ingoingEdges|ingoingEdges()} - for a way to get all ingoing edges of a vertex.
*/
readonly outgoingEdges: (id: NodeId) => ReadonlyMap<NodeId, CfgEdge> | undefined;
/**
* Receive all ingoing edges of a given vertex.
*
* This is the pendant of {@link DataflowGraph#outgoingEdges|outgoingEdges()} on a {@link DataflowGraph}.
* @see {@link ReadOnlyControlFlowGraph#outgoingEdges|outgoingEdges()} - for a way to get all outgoing edges of a vertex.
*/
readonly ingoingEdges: (id: NodeId) => ReadonlyMap<NodeId, CfgEdge> | undefined;
/**
* Retrieve a vertex by its id.
* @param id - the id of the vertex to retrieve
* @param includeBlocks - if true, the elements of basic block elements are included in the result, otherwise this will only the basic blocks themselves
*
* This is the pendant of {@link DataflowGraph#getVertex|getVertex()} on a {@link DataflowGraph}.
*/
readonly getVertex: (id: NodeId, includeBlocks?: boolean) => CfgVertex | undefined;
/**
* Check if a vertex with the given id exists in the graph.
* @param id - the id of the vertex to check
* @param includeBlocks - if true, the elements of basic block elements are included in the check, otherwise this will only check the basic blocks themselves
*
* This is the pendant of {@link DataflowGraph#hasVertex|hasVertex()} on a {@link DataflowGraph}.
*/
readonly hasVertex: (id: NodeId, includeBlocks?: boolean) => boolean;
/**
* Obtain the basic block associated with the given element id (i.e. if this is an element within a basic block, return the blockit belongs to).
*/
readonly getBasicBlock: (elemId: NodeId) => CfgBasicBlockVertex | undefined;
/**
* Returns true if the graph may contain basic blocks and false if we know that it does not.
* This can be used for optimizations.
*/
readonly mayHaveBasicBlocks: () => boolean;
}
/**
* 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()}).
*
* There are two very simple visitors to traverse a CFG:
* - {@link visitCfgInOrder} visits the graph in the order of the vertices
* - {@link visitCfgInReverseOrder} visits the graph in reverse order
*
* If you want to prohibit modification, please refer to the {@link ReadOnlyControlFlowGraph} interface.
*/
export declare class ControlFlowGraph<Vertex extends CfgVertex = CfgVertex> implements ReadOnlyControlFlowGraph {
private readonly roots;
/** Nesting-Independent vertex information, mapping the id to the vertex */
private readonly vtxInfos;
/** the basic block children map contains a mapping of ids to all vertices that are nested in basic blocks, mapping them to the Id of the block they appear in */
private readonly bbChildren;
/** basic block agnostic edges */
private readonly edgeInfos;
/** reverse edges for bidirectional mapping */
private readonly revEdgeInfos;
/** used as an optimization to avoid unnecessary lookups */
private _mayBB;
/**
* Add a new vertex to the control flow graph.
* @see {@link ControlFlowGraph#addEdge|addEdge()} - to add an edge
*/
addVertex(vertex: Vertex, rootVertex?: boolean): this;
/**
* Add a new edge to the control flow graph.
* @see {@link ControlFlowGraph#addVertex|addVertex()} - to add vertices
* @see {@link ControlFlowGraph#addEdges|addEdges()} - to add multiple edges at once
*/
addEdge(from: NodeId, to: NodeId, edge: CfgEdge): this;
/**
* Add multiple edges from a given source vertex to the control flow graph.
*/
addEdges(from: NodeId, to: Map<NodeId, CfgEdge>): this;
outgoingEdges(node: NodeId): ReadonlyMap<NodeId, CfgEdge> | undefined;
ingoingEdges(node: NodeId): ReadonlyMap<NodeId, CfgEdge> | undefined;
rootIds(): ReadonlySet<NodeId>;
vertices(includeBasicBlockElements?: boolean): ReadonlyMap<NodeId, CfgVertex>;
getBasicBlock(elemId: NodeId): CfgBasicBlockVertex | undefined;
edges(): ReadonlyMap<NodeId, ReadonlyMap<NodeId, CfgEdge>>;
/**
* Retrieve a vertex by its id.
*/
getVertex(id: NodeId, includeBlocks?: boolean): CfgVertex | undefined;
hasVertex(id: NodeId, includeBlocks?: boolean): boolean;
mayHaveBasicBlocks(): boolean;
/**
* This removes the vertex and all edges to and from it.
* @param id - the id of the vertex to remove
* @see {@link ControlFlowGraph#addVertex|addVertex()} - to add a vertex
* @see {@link ControlFlowGraph#removeEdge|removeEdge()} - to remove a specific edge
*/
removeVertex(id: NodeId): this;
/**
* Removes a all direct edges between `from` and `to` from the control flow graph.
* @see {@link ControlFlowGraph#addEdge|addEdge()} - to add an edge
* @see {@link ControlFlowGraph#removeVertex|removeVertex()} - to remove a vertex and all its edges
*/
removeEdge(from: NodeId, to: NodeId): this;
/** merges b into a */
mergeTwoBasicBlocks(a: NodeId, b: NodeId): this;
/**
* **This Operation is in-place and modifies the current graph.**
* Merge another control flow graph into this one.
* @param other - the other control flow graph to merge into this one
* @param forceNested - should the other graph be assumed to be fully nested (e.g., within a function definition).
*
* This is the pendant of {@link DataflowGraph#mergeWith|mergeWith()} on a {@link DataflowGraph}.
*/
mergeWith(other: ControlFlowGraph<Vertex>, forceNested?: boolean): this;
}
/**
* Summarizes the control information of a program
* @see {@link emptyControlFlowInformation} - to create an empty control flow information object
*/
export interface ControlFlowInformation<Vertex extends CfgVertex = CfgVertex> extends MergeableRecord {
/** all active 'return'(-like) unconditional jumps */
returns: NodeId[];
/** all active 'break'(-like) unconditional jumps */
breaks: NodeId[];
/** all active 'next'(-like) unconditional jumps */
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[];
/** the control flow graph summarizing the flow information */
graph: ControlFlowGraph<Vertex>;
}
/**
* Create an empty control flow information object.
*/
export declare function emptyControlFlowInformation(): ControlFlowInformation;
export {};