@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
92 lines • 3.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractDomain = exports.DEFAULT_INFERENCE_LIMIT = void 0;
exports.domainElementToString = domainElementToString;
exports.isAbstractDomain = isAbstractDomain;
const assert_1 = require("../../util/assert");
const lattice_1 = require("./lattice");
/**
* The default limit of inferred constraints in {@link AbstractDomain|AbstractDomains}.
*/
exports.DEFAULT_INFERENCE_LIMIT = 50;
/**
* An abstract domain as complete lattice with a widening operator, narrowing operator, concretization function, and abstraction function.
* All operations of value abstract domains should not modify the domain in-place but return new values using {@link create}.
* @template Concrete - Type of an concrete element of the concrete domain for the abstract domain
* @template Abstract - Type of an abstract element of the abstract domain representing possible elements (excludes `Top` and `Bot`)
* @template Top - Type of the Top element of the abstract domain representing all possible elements
* @template Bot - Type of the Bottom element of the abstract domain representing no possible elements
* @template Value - Type of the abstract elements of the abstract domain (defaults to `Abstract` or `Top` or `Bot`)
*/
class AbstractDomain {
_value;
constructor(value) {
this._value = value;
}
get value() {
return this._value;
}
/**
* Joins the current abstract value with multiple other abstract values.
*/
joinAll(values) {
let result = this.create(this.value);
for (const other of values) {
result = result.join(other);
}
return result;
}
/**
* Meets the current abstract value with multiple other abstract values.
*/
meetAll(values) {
let result = this.create(this.value);
for (const other of values) {
result = result.meet(other);
}
return result;
}
/**
* Joins an array of abstract values by joining the first abstract value with the other values in the array.
* The provided array of abstract values must not be empty or a default value must be provided!
*/
static joinAll(values, defaultValue) {
(0, assert_1.guard)(values.length > 0 || defaultValue !== undefined, 'Abstract values to join cannot be empty');
return values[0]?.joinAll(values.slice(1)) ?? defaultValue;
}
/**
* Meets an array of abstract values by meeting the first abstract value with the other values in the array.
* The provided array of abstract values must not be empty or a default value must be provided!
*/
static meetAll(values, defaultValue) {
(0, assert_1.guard)(values.length > 0 || defaultValue !== undefined, 'Abstract values to meet cannot be empty');
return values[0]?.meetAll(values.slice(1)) ?? defaultValue;
}
}
exports.AbstractDomain = AbstractDomain;
/**
* Converts an element of an abstract domain into a string.
*/
function domainElementToString(value) {
if (typeof value === 'object' && value !== null && value.toString !== Object.prototype.toString) {
// eslint-disable-next-line @typescript-eslint/no-base-to-string
return value.toString();
}
else if (value === lattice_1.Top) {
return lattice_1.TopSymbol;
}
else if (value === lattice_1.Bottom) {
return lattice_1.BottomSymbol;
}
return JSON.stringify(value);
}
/**
* Checks whether a value is an abstract domain.
*/
function isAbstractDomain(value) {
if (typeof value !== 'object' || value === null) {
return false;
}
return ['value', 'top', 'bottom', 'leq', 'join', 'meet', 'widen', 'narrow', 'concretize', 'abstract'].every(property => property in value);
}
//# sourceMappingURL=abstract-domain.js.map