@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
315 lines • 14.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataFrameTop = exports.DataFrameBottom = exports.ColNamesTop = exports.ColNamesBottom = exports.IntervalTop = exports.IntervalBottom = void 0;
exports.equalColNames = equalColNames;
exports.leqColNames = leqColNames;
exports.joinColNames = joinColNames;
exports.meetColNames = meetColNames;
exports.subtractColNames = subtractColNames;
exports.wideningColNames = wideningColNames;
exports.satisfiesColsNames = satisfiesColsNames;
exports.equalInterval = equalInterval;
exports.leqInterval = leqInterval;
exports.joinInterval = joinInterval;
exports.meetInterval = meetInterval;
exports.addInterval = addInterval;
exports.subtractInterval = subtractInterval;
exports.minInterval = minInterval;
exports.maxInterval = maxInterval;
exports.extendIntervalToZero = extendIntervalToZero;
exports.extendIntervalToInfinity = extendIntervalToInfinity;
exports.wideningInterval = wideningInterval;
exports.satisfiesInterval = satisfiesInterval;
exports.satisfiesLeqInterval = satisfiesLeqInterval;
exports.equalDataFrameDomain = equalDataFrameDomain;
exports.joinDataFrames = joinDataFrames;
exports.meetDataFrames = meetDataFrames;
exports.wideningDataFrames = wideningDataFrames;
exports.equalDataFrameState = equalDataFrameState;
exports.joinDataFrameStates = joinDataFrameStates;
exports.meetDataFrameStates = meetDataFrameStates;
exports.wideningDataFrameStates = wideningDataFrameStates;
const config_1 = require("../../config");
const set_1 = require("../../util/collections/set");
const MaxColNames = config_1.defaultConfigOptions.abstractInterpretation.dataFrame.maxColNames;
/** The bottom element (least element) of the positive interval domain representing no possible values, explicitly given as "bottom". */
exports.IntervalBottom = 'bottom';
/** The top element (greatest element) of the positive interval domain representing all possible values, defined as the interval from 0 to infinity. */
exports.IntervalTop = [0, Infinity];
/** The bottom element (least element) of the column names domain representing no possible column name, defined as the empty list []. */
exports.ColNamesBottom = [];
/** The top element (greatest element) of the column names domain representing all possible values, explicitly given as "top". */
exports.ColNamesTop = 'top';
/**
* The bottom element (least element) of the data frame shape domain representing no possible value, mapping the columns names to {@link ColNamesBottom}
* and the number of columns and rows to {@link IntervalBottom}.
*/
exports.DataFrameBottom = {
colnames: exports.ColNamesBottom,
cols: exports.IntervalBottom,
rows: exports.IntervalBottom
};
/**
* The top element (greatest element) of the data frame shape domain representing all possible value, mapping the columns names to {@link ColNamesTop}
* and the number of columns and rows to {@link IntervalTop}.
*/
exports.DataFrameTop = {
colnames: exports.ColNamesTop,
cols: exports.IntervalTop,
rows: exports.IntervalTop
};
/** Checks if two abstract values of the column names domain are equal. */
function equalColNames(set1, set2) {
return set1 === set2 || (set1 !== exports.ColNamesTop && set2 !== exports.ColNamesTop && (0, set_1.setEquals)(new Set(set1), new Set(set2)));
}
/** Checks if two abstract values of the column names domain are ordered according to the partial ordering of the column names lattice. */
function leqColNames(set1, set2) {
return set2 === exports.ColNamesTop || (set1 !== exports.ColNamesTop && new Set(set1).isSubsetOf(new Set(set2)));
}
/** Joins two abstract values of the columns names domain according to the column names lattice by creating the least upper bound (LUB). */
function joinColNames(set1, set2, maxColNames = MaxColNames) {
if (set1 === exports.ColNamesTop || set2 === exports.ColNamesTop) {
return exports.ColNamesTop;
}
const join = Array.from(new Set(set1).union(new Set(set2)));
return join.length > maxColNames ? exports.ColNamesTop : join;
}
/** Meets two abstract values of the columns names domain according to the column names lattice by creating the greatest lower bound (GLB). */
function meetColNames(set1, set2) {
if (set1 === exports.ColNamesTop) {
return set2;
}
else if (set2 === exports.ColNamesTop) {
return set1;
}
else {
return Array.from(new Set(set1).intersection(new Set(set2)));
}
}
/** Subtracts an abstract value from another abstract value of the column names domain by performing a set minus. */
function subtractColNames(set1, set2) {
if (set1 === exports.ColNamesTop) {
return exports.ColNamesTop;
}
else if (set2 === exports.ColNamesTop) {
return set1;
}
else {
return Array.from(new Set(set1).difference(new Set(set2)));
}
}
/**
* Widens two abstract values of the column names domain via naive widening to soundly over-approximate the join in (possibly infinite) fixpoint iterations.
*
* This is technically not necessary, as the join is limited by the maximum number of inferred column names.
* However, this speeds up the iteration in larger loops significantly, as we are over-approximating the column names much earlier.
*/
function wideningColNames(set1, set2) {
return leqColNames(set2, set1) ? set1 : exports.ColNamesTop;
}
/** Checks whether an abstract value of the column names domain satisfies a column name */
function satisfiesColsNames(set, value) {
return set === exports.ColNamesTop || set.includes(value);
}
/** Checks if two abstract values of the positive interval domain are equal. */
function equalInterval(interval1, interval2) {
return interval1 === interval2 || (interval1 !== exports.IntervalBottom && interval2 !== exports.IntervalBottom && interval1[0] === interval2[0] && interval1[1] === interval2[1]);
}
/** Checks if two abstract values of the positive interval domain are ordered according to the partial ordering of the positive interval lattice. */
function leqInterval(interval1, interval2) {
return interval1 === exports.IntervalBottom || (interval2 !== exports.IntervalBottom && interval2[0] <= interval1[0] && interval1[1] <= interval2[1]);
}
/** Joins two abstract values of the positive interval domain according to the positive interval lattice by creating the least upper bound (LUB). */
function joinInterval(interval1, interval2) {
if (interval1 === exports.IntervalBottom) {
return interval2;
}
else if (interval2 === exports.IntervalBottom) {
return interval1;
}
else {
return [Math.min(interval1[0], interval2[0]), Math.max(interval1[1], interval2[1])];
}
}
/** Meets two abstract values of the positive interval domain according to the positive interval lattice by creating the greatest lower bound (GLB). */
function meetInterval(interval1, interval2) {
if (interval1 === exports.IntervalBottom || interval2 === exports.IntervalBottom) {
return exports.IntervalBottom;
}
else if (Math.max(interval1[0], interval2[0]) > Math.min(interval1[1], interval2[1])) {
return exports.IntervalBottom;
}
else {
return [Math.max(interval1[0], interval2[0]), Math.min(interval1[1], interval2[1])];
}
}
/** Adds two abstract values of the positive interval domain, by adding the lower bounds and upper bounds. */
function addInterval(interval1, interval2) {
if (interval1 === exports.IntervalBottom || interval2 === exports.IntervalBottom) {
return exports.IntervalBottom;
}
else {
return [interval1[0] + interval2[0], interval1[1] + interval2[1]];
}
}
/** Subtracts an abstract value from another abstract values of the positive interval domain, by subtracting the lower bounds and upper bounds. */
function subtractInterval(interval1, interval2) {
if (interval1 === exports.IntervalBottom || interval2 === exports.IntervalBottom) {
return exports.IntervalBottom;
}
else {
return [Math.max(interval1[0] - interval2[0], 0), Math.max(interval1[1] - interval2[1], 0)];
}
}
/** Creates the minium of two abstract values of the positive interval domain, by creating the minimum of the lower bounds and upper bounds. */
function minInterval(interval1, interval2) {
if (interval1 === exports.IntervalBottom || interval2 === exports.IntervalBottom) {
return exports.IntervalBottom;
}
else {
return [Math.min(interval1[0], interval2[0]), Math.min(interval1[1], interval2[1])];
}
}
/** Creates the maximum of two abstract values of the positive interval domain, by creating the maximum of the lower bounds and upper bounds. */
function maxInterval(interval1, interval2) {
if (interval1 === exports.IntervalBottom || interval2 === exports.IntervalBottom) {
return exports.IntervalBottom;
}
else {
return [Math.max(interval1[0], interval2[0]), Math.max(interval1[1], interval2[1])];
}
}
/** Extrends the lower bound of an abstract value of the positive interval domain to 0. */
function extendIntervalToZero(interval) {
if (interval === exports.IntervalBottom) {
return exports.IntervalBottom;
}
else {
return [0, interval[1]];
}
}
/** Extrends the upper bound of an abstract value of the positive interval domain to infinity. */
function extendIntervalToInfinity(interval) {
if (interval === exports.IntervalBottom) {
return exports.IntervalBottom;
}
else {
return [interval[0], Infinity];
}
}
/** Widens two abstract values of the positive interval domain via naive widening to soundly over-approximate the join in (possibly infinite) fixpoint iterations. */
function wideningInterval(interval1, interval2) {
if (interval1 === exports.IntervalBottom) {
return interval2;
}
else if (interval2 === exports.IntervalBottom) {
return interval1;
}
else {
return [interval1[0] <= interval2[0] ? interval1[0] : 0, interval1[1] >= interval2[1] ? interval1[1] : Infinity];
}
}
/** Checks whether an abstract value of the positive interval domain satisfies a numeric value. */
function satisfiesInterval(interval, value) {
return interval !== exports.IntervalBottom && interval[0] <= value && value <= interval[1];
}
/** Checks whether a numeric value satisfies the less-than relation with an abstract value of the positive interval domain. */
function satisfiesLeqInterval(interval, value) {
return interval !== exports.IntervalBottom && value <= interval[1];
}
/** Checks if two abstract values of the data frame shape domain are equal. */
function equalDataFrameDomain(value1, value2) {
return value1 === value2 || (equalColNames(value1.colnames, value2.colnames) && equalInterval(value1.cols, value2.cols) && equalInterval(value1.rows, value2.rows));
}
/** Joins multiple abstract values of the data frame shape domain by creating the least upper bound (LUB). */
function joinDataFrames(...values) {
let result = values[0] ?? exports.DataFrameTop;
for (let i = 1; i < values.length; i++) {
result = {
colnames: joinColNames(result.colnames, values[i].colnames),
cols: joinInterval(result.cols, values[i].cols),
rows: joinInterval(result.rows, values[i].rows)
};
}
return result;
}
/** Meets multiple abstract values of the data frame shape domain by creating the greatest lower bound (GLB). */
function meetDataFrames(...values) {
let result = values[0] ?? exports.DataFrameTop;
for (let i = 1; i < values.length; i++) {
result = {
colnames: meetColNames(result.colnames, values[i].colnames),
cols: meetInterval(result.cols, values[i].cols),
rows: meetInterval(result.rows, values[i].rows)
};
}
return result;
}
/** Widens two abstract values of the data frame shape domain by widening the column names and number of columns and rows. */
function wideningDataFrames(value1, value2) {
return {
colnames: wideningColNames(value1.colnames, value2.colnames),
cols: wideningInterval(value1.cols, value2.cols),
rows: wideningInterval(value1.rows, value2.rows)
};
}
/** Checks if two abstract states of the data frame shape state domain are equal. */
function equalDataFrameState(state1, state2) {
if (state1 === state2) {
return true;
}
else if (state1.size !== state2.size) {
return false;
}
for (const [nodeId, value] of state1) {
const other = state2.get(nodeId);
if (other === undefined || !equalDataFrameDomain(value, other)) {
return false;
}
}
return true;
}
/** Joins multiple abstract states of the data frame shape state domain by joining each data frame shape of the states. */
function joinDataFrameStates(...states) {
const result = new Map(states[0]);
for (let i = 1; i < states.length; i++) {
for (const [nodeId, value] of states[i]) {
if (result.has(nodeId)) {
result.set(nodeId, joinDataFrames(result.get(nodeId) ?? exports.DataFrameTop, value));
}
else {
result.set(nodeId, value);
}
}
}
return result;
}
/** Meets multiple abstract states of the data frame shape state domain by meeting each data frame shape of the states. */
function meetDataFrameStates(...states) {
const result = new Map(states[0]);
for (let i = 1; i < states.length; i++) {
for (const [nodeId, value] of states[i]) {
if (result.has(nodeId)) {
result.set(nodeId, meetDataFrames(result.get(nodeId) ?? exports.DataFrameTop, value));
}
else {
result.set(nodeId, value);
}
}
}
return result;
}
/** Widens two abstract states of the data frame shape state domain by widening each data frame shape of the states. */
function wideningDataFrameStates(state1, state2) {
const result = new Map(state1);
for (const [nodeId, value] of state2) {
if (result.has(nodeId)) {
result.set(nodeId, wideningDataFrames(result.get(nodeId) ?? exports.DataFrameTop, value));
}
else {
result.set(nodeId, value);
}
}
return result;
}
//# sourceMappingURL=domain.js.map