UNPKG

@eagleoutice/flowr-dev

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

49 lines (48 loc) 3.05 kB
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 {};