@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
121 lines • 4.26 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BoundedSetDomain = void 0;
const set_1 = require("../../util/collections/set");
const abstract_domain_1 = require("./abstract-domain");
const lattice_1 = require("./lattice");
/**
* The bounded set abstract domain as sets of possible values bounded by a `limit` indicating the maximum number of inferred values.
* The Bottom element is defined as the empty set and the Top element is defined as {@link Top} symbol.
* @template T - Type of the values in the abstract domain
* @template Value - Type of the constraint in the abstract domain (Top, Bottom, or an actual value)
*/
class BoundedSetDomain {
limit;
_value;
constructor(value, limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) {
if (value !== lattice_1.Top) {
this._value = (value.size > limit ? lattice_1.Top : new Set(value));
}
else {
this._value = value;
}
this.limit = limit;
}
get value() {
return this._value;
}
static top(limit) {
return new BoundedSetDomain(lattice_1.Top, limit);
}
static bottom(limit) {
return new BoundedSetDomain(new Set(), limit);
}
static abstract(concrete, limit) {
return new BoundedSetDomain(concrete, limit);
}
top() {
return BoundedSetDomain.top(this.limit);
}
bottom() {
return BoundedSetDomain.bottom(this.limit);
}
equals(other) {
return this.value === other.value || (this.isValue() && other.isValue() && (0, set_1.setEquals)(this.value, other.value));
}
leq(other) {
return other.value === lattice_1.Top || (this.isValue() && this.value.isSubsetOf(other.value));
}
join(...values) {
const result = new BoundedSetDomain(this.value, this.limit);
for (const other of values) {
if (result.value === lattice_1.Top || other.value === lattice_1.Top) {
result._value = lattice_1.Top;
}
else {
const join = result.value.union(other.value);
result._value = join.size > this.limit ? lattice_1.Top : join;
}
}
return result;
}
meet(...values) {
const result = new BoundedSetDomain(this.value, this.limit);
for (const other of values) {
if (result.value === lattice_1.Top) {
result._value = other.value;
}
else if (other.value === lattice_1.Top) {
result._value = result.value;
}
else {
result._value = result.value.intersection(other.value);
}
}
return result;
}
/**
* Subtracts another abstract value from the current abstract value by removing all elements of the other abstract value from the current abstract value.
*/
subtract(other) {
if (this.value === lattice_1.Top) {
return this.top();
}
else if (other.value === lattice_1.Top) {
return new BoundedSetDomain(this.value, this.limit);
}
else {
return new BoundedSetDomain(this.value.difference(other.value), this.limit);
}
}
widen(other) {
return other.leq(this) ? new BoundedSetDomain(this.value, this.limit) : this.top();
}
narrow(other) {
return this.isTop() ? other : this;
}
concretize(limit = this.limit) {
return this.value === lattice_1.Top || this.value.size > limit ? lattice_1.Top : this.value;
}
abstract(concrete) {
return BoundedSetDomain.abstract(concrete, this.limit);
}
toString() {
if (this.value === lattice_1.Top) {
return '⊤';
}
const string = this.value.values().map(abstract_domain_1.domainElementToString).toArray().join(', ');
return `{${string}}`;
}
isTop() {
return this.value === lattice_1.Top;
}
isBottom() {
return this.value !== lattice_1.Top && this.value.size === 0;
}
isValue() {
return this.value !== lattice_1.Top;
}
}
exports.BoundedSetDomain = BoundedSetDomain;
//# sourceMappingURL=bounded-set-domain.js.map