@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
133 lines • 4.37 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProductDomain = void 0;
const abstract_domain_1 = require("./abstract-domain");
const lattice_1 = require("./lattice");
/**
* A product abstract domain as named Cartesian product of sub abstract domains.
* The sub abstract domains are represented a record mapping property names to abstract domains.
* The Bottom element is defined as mapping every sub abstract domain to Bottom and the Top element is defined as mapping every sub abstract domain to Top.
* @template Product - Type of the abstract product of the product domain mapping property names to abstract domains
*/
class ProductDomain {
_value;
constructor(value) {
this._value = value;
}
get value() {
return this._value;
}
bottom() {
const result = this.create(this.value);
for (const key in result.value) {
result._value[key] = result.value[key].bottom();
}
return result;
}
top() {
const result = this.create(this.value);
for (const key in result.value) {
result._value[key] = result.value[key].top();
}
return result;
}
equals(other) {
if (this.value === other.value) {
return true;
}
for (const key in this.value) {
if (!this.value[key].equals(other.value[key])) {
return false;
}
}
return true;
}
leq(other) {
if (this.value === other.value) {
return true;
}
for (const key in this.value) {
if (!this.value[key].leq(other.value[key])) {
return false;
}
}
return true;
}
join(...values) {
const result = this.create(this.value);
for (const value of values) {
for (const key in result.value) {
result._value[key] = result.value[key].join(value.value[key]);
}
}
return result;
}
meet(...values) {
const result = this.create(this.value);
for (const value of values) {
for (const key in result.value) {
result._value[key] = result.value[key].meet(value.value[key]);
}
}
return result;
}
widen(other) {
const result = this.create(this.value);
for (const key in result.value) {
result._value[key] = result.value[key].widen(other.value[key]);
}
return result;
}
narrow(other) {
const result = this.create(this.value);
for (const key in result.value) {
result._value[key] = result.value[key].narrow(other.value[key]);
}
return result;
}
concretize(limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) {
let result = new Set([{}]);
for (const key in this.value) {
const concrete = this.value[key].concretize(limit);
if (concrete === lattice_1.Top) {
return lattice_1.Top;
}
const newResult = new Set();
for (const value of concrete) {
for (const entry of result) {
if (newResult.size >= limit) {
return lattice_1.Top;
}
newResult.add({ ...entry, [key]: value });
}
}
result = newResult;
}
return result;
}
abstract(concrete) {
if (concrete === lattice_1.Top) {
return this.top();
}
const result = this.create(this.value);
for (const key in result.value) {
const concreteValues = new Set(concrete.values().map(value => value[key]));
result._value[key] = result.value[key].abstract(concreteValues);
}
return result;
}
toString() {
return '(' + Object.entries(this.value).map(([key, value]) => `${key}: ${value.toString()}`).join(', ') + ')';
}
isTop() {
return Object.values(this.value).every(value => value.isTop());
}
isBottom() {
return Object.values(this.value).every(value => value.isBottom());
}
isValue() {
return true;
}
}
exports.ProductDomain = ProductDomain;
//# sourceMappingURL=product-domain.js.map