@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
82 lines • 3.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowrAnalyzerControlFlowCache = void 0;
const objectmap_1 = require("../../util/collections/objectmap");
const cfg_simplification_1 = require("../../control-flow/cfg-simplification");
const cfg_kind_1 = require("../cfg-kind");
const assert_1 = require("../../util/assert");
const extract_cfg_1 = require("../../control-flow/extract-cfg");
class FlowrAnalyzerControlFlowCache {
cache = new objectmap_1.ObjectMap();
peek(kind, simplifications) {
return this.cache.get([simplifications ?? [], kind]);
}
async get(force, kind, cfgCacheInfo, simplifications) {
(0, assert_1.guard)(kind === cfg_kind_1.CfgKind.Quick ? simplifications === undefined : true, 'Cannot apply simplifications to quick CFG');
simplifications ??= [];
const orderedSimplifications = this.normalizeSimplificationOrder(simplifications);
const cached = force ?
{ cfg: undefined, missingSimplifications: orderedSimplifications }
: this.tryGetCachedCfg(orderedSimplifications, kind);
let cfg = cached.cfg;
if (!cfg) {
cfg = await this.createAndCacheBaseCfg(kind, cfgCacheInfo);
}
if (cached.missingSimplifications.length > 0) {
const cfgPassInfo = { dfg: (await cfgCacheInfo.dfg()).graph, ctx: cfgCacheInfo.ctx, ast: await cfgCacheInfo.ast() };
cfg = (0, cfg_simplification_1.simplifyControlFlowInformation)(cfg, cfgPassInfo, cached.missingSimplifications);
}
this.cache.set([orderedSimplifications, kind], cfg);
return cfg;
}
/**
* Create and cache the base CFG without simplifications.
*/
async createAndCacheBaseCfg(kind, { cfgQuick, dfg, ctx, ast }) {
let result;
switch (kind) {
case cfg_kind_1.CfgKind.WithDataflow:
result = (0, extract_cfg_1.extractCfg)(await ast(), ctx, (await dfg()).graph);
break;
case cfg_kind_1.CfgKind.NoDataflow:
result = (0, extract_cfg_1.extractCfg)(await ast(), ctx);
break;
case cfg_kind_1.CfgKind.NoFunctionDefs:
result = (0, extract_cfg_1.extractCfg)(await ast(), ctx, undefined, undefined, true);
break;
case cfg_kind_1.CfgKind.Quick:
result = cfgQuick ?? (0, extract_cfg_1.extractCfgQuick)(await ast());
break;
}
this.cache.set([[], kind], result);
return result;
}
/**
* Try to get a cached CFG with some of the requested simplifications already applied.
* Matches the longest prefix of simplifications available.
* @returns The cached CFG and the missing simplifications to be applied, or `undefined` if no cached CFG is available.
*/
tryGetCachedCfg(simplifications, kind) {
for (let prefixLen = simplifications.length; prefixLen >= 0; prefixLen--) {
const prefix = simplifications.slice(0, prefixLen);
const cached = this.cache.get([prefix, kind]);
if (cached !== undefined) {
return {
cfg: cached,
missingSimplifications: simplifications.slice(prefixLen)
};
}
}
return { cfg: undefined, missingSimplifications: simplifications };
}
/**
* Normalize the order of simplification passes.
* Is currently an identity function, but may be extended in the future to enforce a specific order using heuristics.
* @param simplifications - the requested simplification passes.
*/
normalizeSimplificationOrder(simplifications) {
return simplifications;
}
}
exports.FlowrAnalyzerControlFlowCache = FlowrAnalyzerControlFlowCache;
//# sourceMappingURL=flowr-analyzer-controlflow-cache.js.map