@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
49 lines (48 loc) • 3.05 kB
TypeScript
import type { AstIdMap, 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 { DataflowGraph } from '../../../../graph/graph';
import type { ControlFlowGraph } from '../../../../../control-flow/control-flow-graph';
/** The reads that may force the expression, and the control flow deciding what they can see. */
export interface ForceSites {
readonly cfg: ControlFlowGraph;
readonly sites: readonly NodeId[];
/** the name the deferred expression is bound to, whose binding its own writes replace */
readonly binding: NodeId;
}
/** Where a name is bound and where it is read, so that a deferred expression can reach either. */
interface NameIndex {
readonly definitions: ReadonlyMap<string, NodeId[]>;
readonly uses: ReadonlyMap<string, NodeId[]>;
}
/**
* An expression R evaluates at a time we cannot pin down: the body a `delayedAssign` binds, forced at some
* later read of the name, or a promise a closure carries past the call that created it.
*
* Since the moment is open, every binding the expression may meet is a candidate, and symmetrically so:
* a name it reads may read any definition of that name, and a name it writes may be read by any use of it.
* That is the may-analysis both directions ask for, so nothing the expression really depends on, and nothing
* really depending on it, can be missed.
*/
export declare const Deferred: {
readonly name: "Deferred";
/** Where each name is bound and read, built once and shared by every deferred expression in the graph. */
readonly indexOf: <Info>(this: void, graph: DataflowGraph, idMap: AstIdMap<Info & ParentInformation>) => NameIndex;
/**
* The reads that may be the one forcing `binding`: every read of it that no other read always precedes,
* since an earlier read would already have forced it and cached the value.
*/
readonly forcedAt: (this: void, graph: DataflowGraph, binding: NodeId, cfg: ControlFlowGraph) => readonly NodeId[];
/**
* Links the writes an expression performs to the uses that may observe them, for a call evaluating the
* expression at a point control flow can pin down (`eval`). The reads are settled by the evaluating call
* itself, against the environment in effect there, so only this direction is left open.
*/
readonly publish: <Info>(this: void, graph: DataflowGraph, expr: NodeId, index: NameIndex, idMap: AstIdMap<Info & ParentInformation>, at: NodeId, cfg?: ControlFlowGraph) => void;
/**
* Links the expression rooted at `expr` to the bindings it may meet when it is evaluated. Given the reads
* that may force it, control flow rules out what no force can reach; without them every binding stays a
* candidate.
*/
readonly link: <Info>(this: void, graph: DataflowGraph, expr: NodeId, index: NameIndex, idMap: AstIdMap<Info & ParentInformation>, forces?: ForceSites) => void;
};
export {};