@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
115 lines • 5.04 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.EdgeType = void 0;
exports.edgeTypeToName = edgeTypeToName;
exports.splitEdgeTypes = splitEdgeTypes;
exports.edgeTypesToNames = edgeTypesToNames;
exports.edgeIncludesType = edgeIncludesType;
exports.edgeDoesNotIncludeType = edgeDoesNotIncludeType;
exports.shouldTraverseEdge = shouldTraverseEdge;
/**
* Represents the relationship between the source and the target vertex in the dataflow graph.
* The actual value is represented as a bitmask so use {@link edgeTypesToNames} to get something more human-readable.
* Similarly, you can access {@link EdgeTypeName} to access the name counterpart.
*/
var EdgeType;
(function (EdgeType) {
/** The edge determines that source reads target */
EdgeType[EdgeType["Reads"] = 1] = "Reads";
/** The edge determines that source is defined by target */
EdgeType[EdgeType["DefinedBy"] = 2] = "DefinedBy";
/** The edge determines that the source calls the target */
EdgeType[EdgeType["Calls"] = 4] = "Calls";
/** The source returns target on call */
EdgeType[EdgeType["Returns"] = 8] = "Returns";
/**
* The edge determines that source (probably argument) defines the target (probably parameter).
* This may also link a function call to definitions it causes to be active (as part of the closure) of the called function definition.
*/
EdgeType[EdgeType["DefinesOnCall"] = 16] = "DefinesOnCall";
/**
* Usually the inverse of `defines-on-call` (in the context of arguments and parameters).
* This may also link an open read (within a function) to the definition that is active at the call site.
*/
EdgeType[EdgeType["DefinedByOnCall"] = 32] = "DefinedByOnCall";
/** Formal used as argument to a function call */
EdgeType[EdgeType["Argument"] = 64] = "Argument";
/** The edge determines that the source is a side effect that happens when the target is called */
EdgeType[EdgeType["SideEffectOnCall"] = 128] = "SideEffectOnCall";
/** The Edge determines that the reference is affected by a non-standard evaluation (e.g., a for-loop body or a quotation) */
EdgeType[EdgeType["NonStandardEvaluation"] = 256] = "NonStandardEvaluation";
})(EdgeType || (exports.EdgeType = EdgeType = {}));
const edgeTypeToHumanReadableName = new Map([
[EdgeType.Reads, "reads" /* EdgeTypeName.Reads */],
[EdgeType.DefinedBy, "defined-by" /* EdgeTypeName.DefinedBy */],
[EdgeType.Calls, "calls" /* EdgeTypeName.Calls */],
[EdgeType.Returns, "returns" /* EdgeTypeName.Returns */],
[EdgeType.DefinesOnCall, "defines-on-call" /* EdgeTypeName.DefinesOnCall */],
[EdgeType.DefinedByOnCall, "defined-by-on-call" /* EdgeTypeName.DefinedByOnCall */],
[EdgeType.Argument, "argument" /* EdgeTypeName.Argument */],
[EdgeType.SideEffectOnCall, "side-effect-on-call" /* EdgeTypeName.SideEffectOnCall */],
[EdgeType.NonStandardEvaluation, "non-standard-evaluation" /* EdgeTypeName.NonStandardEvaluation */]
]);
/**
* Only use this function to retrieve a human-readable name if you know that it is a single bitmask.
* Otherwise, use {@link edgeTypesToNames} which handles these cases.
*/
function edgeTypeToName(type) {
return edgeTypeToHumanReadableName.get(type);
}
function splitEdgeTypes(types) {
const split = [];
for (const bit of edgeTypeToHumanReadableName.keys()) {
if ((types & bit) !== 0) {
split.push(bit);
}
}
return split;
}
function edgeTypesToNames(bits) {
const types = new Set();
for (const [bit, name] of edgeTypeToHumanReadableName.entries()) {
if ((bits & bit) !== 0) {
types.add(name);
}
}
return types;
}
/**
* Check if the given-edge type has any of the given types.
* @example
*
* ```typescript
* edgeIncludesType(EdgeType.Reads, EdgeType.Reads | EdgeType.DefinedBy) // true
*```
*
* Counterpart of {@link edgeDoesNotIncludeType}.
*/
function edgeIncludesType(type, typesToInclude) {
return (typesToInclude & type) !== 0;
}
/**
* Check if the given-edge type does not include the given type.
* Counterpart of {@link edgeIncludesType}.
*/
function edgeDoesNotIncludeType(type, types) {
return (types & type) === 0;
}
const alwaysTraverseEdgeTypes = EdgeType.Reads | EdgeType.DefinedBy | EdgeType.Argument | EdgeType.Calls;
const definedByOnCallTypes = EdgeType.DefinesOnCall | EdgeType.DefinedByOnCall;
function shouldTraverseEdge(types) {
if (edgeIncludesType(types, EdgeType.NonStandardEvaluation)) {
return 0 /* TraverseEdge.Never */;
}
else if (edgeIncludesType(types, alwaysTraverseEdgeTypes)) {
return 3 /* TraverseEdge.Always */;
}
else if (edgeIncludesType(types, definedByOnCallTypes)) {
return 2 /* TraverseEdge.OnlyIfBoth */;
}
else if (edgeIncludesType(types, EdgeType.SideEffectOnCall)) {
return 1 /* TraverseEdge.SideEffect */;
}
return 0 /* TraverseEdge.Never */;
}
//# sourceMappingURL=edge.js.map