UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

164 lines 6.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SetBoundedSetDomain = void 0; const set_1 = require("../../util/collections/set"); const abstract_domain_1 = require("./abstract-domain"); const lattice_1 = require("./lattice"); /** * The set bounded set abstract domain as sets capturing possible values of the concrete set bounded by a `limit` for the maximum number of inferred values. * The Bottom element is defined as the{@link Bottom} 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 SetBoundedSetDomain { limit; _value; constructor(value, limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) { if (value !== lattice_1.Top && value !== lattice_1.Bottom) { 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 SetBoundedSetDomain(lattice_1.Top, limit); } static bottom(limit) { return new SetBoundedSetDomain(lattice_1.Bottom, limit); } static abstract(concrete, limit) { if (concrete === lattice_1.Top) { return SetBoundedSetDomain.top(limit); } else if (concrete.size === 0) { return SetBoundedSetDomain.bottom(limit); } return new SetBoundedSetDomain(concrete.values().reduce((result, set) => result.union(set)), limit); } top() { return SetBoundedSetDomain.top(this.limit); } bottom() { return SetBoundedSetDomain.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 this.value === lattice_1.Bottom || other.value === lattice_1.Top || (this.isValue() && other.isValue() && this.value.isSubsetOf(other.value)); } join(...values) { const result = new SetBoundedSetDomain(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 if (result.value === lattice_1.Bottom) { result._value = other.value; } else if (other.value === lattice_1.Bottom) { result._value = result.value; } 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 SetBoundedSetDomain(this.value, this.limit); for (const other of values) { if (result.value === lattice_1.Bottom || other.value === lattice_1.Bottom) { result._value = lattice_1.Bottom; } else 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 (this.value === lattice_1.Bottom) { return this.bottom(); } else if (other.value === lattice_1.Top || other.value === lattice_1.Bottom) { return new SetBoundedSetDomain(this.value, this.limit); } else { return new SetBoundedSetDomain(this.value.difference(other.value), this.limit); } } widen(other) { if (this.value === lattice_1.Bottom) { return new SetBoundedSetDomain(other.value, this.limit); } else if (other.value === lattice_1.Bottom) { return new SetBoundedSetDomain(this.value, this.limit); } return other.leq(this) ? new SetBoundedSetDomain(this.value, this.limit) : this.top(); } narrow(other) { if (this.value === lattice_1.Bottom || other.value === lattice_1.Bottom) { return this.bottom(); } return this.isTop() ? other : this; } concretize(limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) { if (this.value === lattice_1.Bottom) { return new Set(); } else if (this.value === lattice_1.Top || 2 ** (this.value.size) > limit) { return lattice_1.Top; } const subsets = [new Set()]; for (const element of this.value.values()) { const newSubsets = subsets.map(subset => new Set([...subset, element])); for (const subset of newSubsets) { subsets.push(subset); } } return new Set(subsets); } abstract(concrete) { return SetBoundedSetDomain.abstract(concrete, this.limit); } toString() { if (this.value === lattice_1.Top) { return '⊤'; } else if (this.value === lattice_1.Bottom) { 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.Bottom; } isValue() { return this.value !== lattice_1.Top && this.value !== lattice_1.Bottom; } } exports.SetBoundedSetDomain = SetBoundedSetDomain; //# sourceMappingURL=set-bounded-set-domain.js.map