UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

72 lines 2.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.VisitingQueue = void 0; const fingerprint_1 = require("./fingerprint"); class VisitingQueue { threshold; timesHitThreshold = 0; seen = new Map(); seenByCache = new Set(); idThreshold = new Map(); queue = []; cache = new Map(); // the set of potential additions holds nodes which may be added if a second edge deems them relevant (e.g., found with the `defined-by-on-call` edge) // additionally it holds which node id added the addition so we can separate their inclusion on the structure potentialAdditions = new Map(); cachedCallTargets = new Map(); constructor(threshold, cache) { this.threshold = threshold; this.cache = cache; } /** * Adds a node to the queue if it has not been seen before. * @param target - the node to add * @param env - the environment the node is traversed in * @param envFingerprint - the fingerprint of the environment * @param onlyForSideEffects - whether the node is only used for its side effects */ add(target, env, envFingerprint, onlyForSideEffects) { const idCounter = this.idThreshold.get(target) ?? 0; if (idCounter > this.threshold) { this.timesHitThreshold++; return; } /* we do not include the in call part in the fingerprint as it is 'deterministic' from the source position */ const print = (0, fingerprint_1.fingerprint)(target, envFingerprint, onlyForSideEffects); if (!this.seen.has(print)) { const cached = this.cache?.get(print); if (cached) { this.seenByCache.add(target); for (const id of cached) { this.queue.push({ id, baseEnvironment: env, envFingerprint, onlyForSideEffects }); } } this.idThreshold.set(target, idCounter + 1); this.seen.set(print, target); this.queue.push({ id: target, baseEnvironment: env, envFingerprint, onlyForSideEffects }); } } next() { return this.queue.pop(); } nonEmpty() { return this.queue.length > 0; } hasId(id) { return this.idThreshold.has(id); } memoizeCallTargets(id, targets) { if (!this.cachedCallTargets.has(id)) { this.cachedCallTargets.set(id, targets()); } return this.cachedCallTargets.get(id); } status() { return { timesHitThreshold: this.timesHitThreshold, result: new Set([...this.seen.values(), ...this.seenByCache]) }; } } exports.VisitingQueue = VisitingQueue; //# sourceMappingURL=visiting-queue.js.map