@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
90 lines • 3.98 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractDomain = exports.DEFAULT_INFERENCE_LIMIT = void 0;
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;
}
/**
* Converts an element of an abstract domain into a string.
*/
static toString(value) {
if (value instanceof Map) {
return `{${value.entries().map(([key, value]) => `${AbstractDomain.toString(key)} -> ${AbstractDomain.toString(value)}`).toArray().join(', ')}}`;
}
else if (value instanceof Set) {
return `{${value.values().map(AbstractDomain.toString).toArray().join(', ')}}`;
}
else 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 (Array.isArray(value)) {
return `[${value.map(AbstractDomain.toString).join(', ')}]`;
}
else if (value === lattice_1.Top) {
return lattice_1.TopSymbol;
}
else if (value === lattice_1.Bottom) {
return lattice_1.BottomSymbol;
}
return JSON.stringify(value);
}
}
exports.AbstractDomain = AbstractDomain;
//# sourceMappingURL=abstract-domain.js.map