@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
79 lines • 3.14 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.overwriteIEnvironmentWith = overwriteIEnvironmentWith;
exports.overwriteEnvironment = overwriteEnvironment;
const assert_1 = require("../../util/assert");
const environment_1 = require("./environment");
const log_1 = require("../../util/log");
function anyIsMaybeOrEmpty(values) {
if (values.length === 0) {
return true;
}
for (const val of values) {
if (val.controlDependencies !== undefined) {
return true;
}
}
return false;
}
function overwriteIEnvironmentWith(base, next, includeParent = true, applyCds) {
(0, assert_1.guard)(base !== undefined && next !== undefined, 'can not overwrite environments with undefined');
const map = new Map(base.memory);
for (const [key, values] of next.memory) {
if (values.length > 1_000_000) {
log_1.log.warn(`Overwriting environment with ${values.length} definitions for ${key}`);
}
const hasMaybe = applyCds !== undefined ? true : anyIsMaybeOrEmpty(values);
if (hasMaybe) {
const old = map.get(key);
// we need to make a copy to avoid side effects for old reference in other environments
const updatedOld = [...old ?? []];
for (const v of values) {
const index = updatedOld.findIndex(o => o.nodeId === v.nodeId && o.definedAt === v.definedAt);
if (index < 0) {
if (applyCds !== undefined) {
updatedOld.push({
...v,
controlDependencies: applyCds.concat(v.controlDependencies ?? [])
});
}
else {
updatedOld.push(v);
}
}
}
map.set(key, updatedOld);
}
else {
map.set(key, values);
}
}
let parent;
if (includeParent) {
parent = base.parent.builtInEnv ? base.parent : overwriteIEnvironmentWith(base.parent, next.parent, includeParent, applyCds);
}
else {
parent = base.parent;
}
const out = new environment_1.Environment(parent);
out.memory = map;
return out;
}
/**
* Assumes, that all definitions within next replace those within base (given the same name).
* <b>But</b> if all definitions within next are maybe, then they are appended to the base definitions (updating them to be `maybe` from now on as well), similar to {@link appendEnvironment}.
*/
function overwriteEnvironment(base, next, applyCds) {
if (base === undefined) {
return next;
}
else if (next === undefined) {
return base;
}
(0, assert_1.guard)(next.level === base.level, `cannot overwrite environments with differently nested local scopes, base ${base.level} vs. next ${next.level}. This should not happen.`);
return {
current: overwriteIEnvironmentWith(base.current, next.current, true, applyCds),
level: base.level
};
}
//# sourceMappingURL=overwrite.js.map