UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

315 lines 14.4 kB
"use strict"; 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