@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
89 lines • 2.96 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.optimize = optimize;
function fingerPrintTransformer(transformer) {
return JSON.stringify(transformer);
}
/**
* Optimizations are currently not reflected
* in an update of the search object.
*/
function optimize(generator, search) {
let searchToOptimize = search.slice();
let fingerprint = fingerPrintTransformer(searchToOptimize);
generator = optimizeGenerator(generator);
let lastFingerprint = '{}';
/* maybe we want shared optimizers in the future, but for now we let it be :sparkles: */
while (fingerprint !== lastFingerprint) {
lastFingerprint = fingerprint;
searchToOptimize = optimizeSearch(searchToOptimize, generator);
fingerprint = fingerPrintTransformer(searchToOptimize);
}
return {
generator,
search: searchToOptimize
};
}
function optimizeGenerator(generator) {
return dropAnyNameRegex(generator);
}
/*
* Ideas:
* Replace .tail().last() with .last()
* Replace .take(1) with '.first()'
* Remove duplicate indices in a .select
* Provide unification step after merge (id based)
* Install caches if sorting is required multiple times (especially for repeated use of generators)
*/
function optimizeSearch(search, _generator) {
search = dropDuplicateNoops(search);
search = selectWithSingleCanBeIndex(search);
return search;
}
const noopTransformers = new Set(['first', 'last']);
/* yes we could optimize something like first, last, first too, but why bother :D*/
function dropDuplicateNoops(transformers) {
const newTransformers = [];
let lastTransformer;
for (const transformer of transformers) {
if (lastTransformer === undefined || lastTransformer.name !== transformer.name || !noopTransformers.has(transformer.name)) {
newTransformers.push(transformer);
}
lastTransformer = transformer;
}
return newTransformers;
}
function selectWithSingleCanBeIndex(transformers) {
return transformers.map(transformer => {
if (transformer.name === 'select' && transformer.args.select.length === 1) {
return {
...transformer,
name: 'index',
args: {
index: transformer.args.select[0]
}
};
}
return transformer;
});
}
function dropAnyNameRegex(generator) {
if (generator.name !== 'get' || !generator.args.filter.nameIsRegex) {
return generator;
}
if (generator.args.filter.name === '.*') {
return {
...generator,
args: {
...generator.args,
filter: {
...generator.args.filter,
name: undefined,
nameIsRegex: undefined
}
}
};
}
return generator;
}
//# sourceMappingURL=search-optimizer.js.map